基於阿里Semantatic Human Matting算法,實現精細化人物摳圖

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第4天,點擊查看活動詳情

人像摳圖

基於深度學習技術研發的人像摳圖技術。可識別視頻圖像中的人像區域,包括頭部、半身、全身位置,摳出人像部分後,配以不同背景圖片、效果,實現娛樂化需求,支持用户玩轉更多個性化操作,常用於直播、視頻場景中。

2018年阿里的論文《Semantatic Human Matting》給出了摳圖領域的一個新方法,論文、代碼和使用的數據集如下:

代碼:http://github.com/lizhengwei1992/Semantic_Human_Matting

論文鏈接:http://arxiv.org/pdf/1809.01354v2.pdf

數據集:http://pan.baidu.com/share/init?surl=R9PJJRT-KjSxh-2-3wCGxQ 密碼是:dzsn

數據集介紹

北京玩星匯聚科技有限公司所高質量標註並開源的一份人像摳圖(matting) 數據集,是目前已知最大的人像matting數據集,包含 34427 張圖像和對應的matting結果圖. 數據集中的原始圖片來源於Flickr、百度、淘寶. 基於該數據集所訓練的人像軟分割模型已商用。

數據集下載

數據集分享在百度網盤(國內):

鏈接:http://pan.baidu.com/s/1R9PJJRT-KjSxh-2-3wCGxQ

提取碼:dzsn

MEGA(國外):

http://mega.nz/#F!Gh8CFAyb!e2ppUh-copP76GbE8IWAEQ

數據集文件為:matting_human_half.zip,解壓後其目錄結構為:

Python - matting_human_half/ - clip_img #人像圖片(半身),.jpg 格式 - matting #人像標註,.png 格式 clip_img文件夾:原圖; matting文件夾:原圖對應的mask圖,四個維度,第四個維度是圖片對應的mask;

該數據集中,圖片是經過人臉檢測和區域裁剪後生成了600x800的半身人像. 標註的人像 matting 圖片為 png 格式,可以從 png 圖片中提取人像的 mask圖,代碼如下:

```Python

!/usr/bin/python3

!---- coding:utf-8 ----

import cv2 import matplotlib.pyplot as plt

png = cv2.imread('./data/matting/1803151818/matting_00000000/1803151818-00000006.png', cv2.IMREAD_UNCHANGED) print(png.shape)

(800, 600, 4)

png_img = cv2.cvtColor(png[:,:,:3], cv2.COLOR_BGR2RGB) alpha = png[:,:,3]

plt.figure(figsize=(10, 8)) plt.subplot(1, 2, 1) plt.imshow(png_img) plt.title("Matting PNG img") plt.axis("off") plt.subplot(1, 2, 2) plt.imshow(alpha) plt.title("Matting Alpha img") plt.axis("off") plt.show() ```

運行結果: 在這裏插入圖片描述

計算alpha圖

下載代碼,並解壓,將clip_img文件夾和matting文件夾。如下圖: 在這裏插入圖片描述

生成train.txt

在data文件夾下,新建get_train_txt.py生成train.txt

```python import os

pic_path = "matting/"

with open("train.txt", "w", encoding="UTF-8") as ff: for name_0 in os.listdir(pic_path): for name_1 in os.listdir(pic_path + "/" + name_0): for name_2 in os.listdir(pic_path + "/" + name_0 + "/" + name_1): pic_input_path = name_0 + "/" + name_1 + "/" + name_2 ff.write(pic_input_path + "\n") ff.close() print("well done______!") ``` 遍歷matting,寫入train.txt,運行結果:

1803151818/matting_00000000/1803151818-00000003.png 1803151818/matting_00000000/1803151818-00000004.png 1803151818/matting_00000000/1803151818-00000006.png 1803151818/matting_00000000/1803151818-00000007.png 1803151818/matting_00000000/1803151818-00000008.png 1803151818/matting_00000000/1803151818-00000009.png 1803151818/matting_00000000/1803151818-00000010.png 1803151818/matting_00000000/1803151818-00000012.png 1803151818/matting_00000000/1803151818-00000015.png 1803151818/matting_00000000/1803151818-00000017.png 1803151818/matting_00000000/1803151818-00000020.png 1803151818/matting_00000000/1803151818-00000021.png

生成mask

在data新建get_mask.py生成mask。

```Python import os import cv2

matting_path = "matting/" mask_path = "mask/"

for name_0 in os.listdir(matting_path): if not os.path.exists(mask_path + "/" + name_0): os.makedirs(mask_path + "/" + name_0) for name_1 in os.listdir(matting_path + "/" + name_0): if not os.path.exists(mask_path + name_0 + "/" + name_1): os.mkdir(mask_path + name_0 + "/" + name_1) for name_2 in os.listdir(matting_path + "/" + name_0 + "/" + name_1):

        pic_input_path = matting_path + "/" + name_0 + "/" + name_1 + "/" + name_2
        pic_output_path = mask_path + "/" + name_0 + "/" + name_1 + "/" + name_2
        print("pic_input_path=", pic_input_path)

        in_image = cv2.imread(pic_input_path, cv2.IMREAD_UNCHANGED)
        alpha = in_image[:, :, 3]
        cv2.imwrite(pic_output_path, alpha)

``` 運行結果: 在這裏插入圖片描述

生成Trimap圖

源代碼有這個腳本文件gen_trimap.py,需要做一些修改。 首先對參數做修改: python def get_args(): parser = argparse.ArgumentParser(description='Trimap') parser.add_argument('--mskDir', type=str, default='mask', help="masks directory") parser.add_argument('--saveDir', type=str, default='trimap', help="where trimap result save to") parser.add_argument('--list', type=str, default='train.txt', help="list of images id") parser.add_argument('--size', type=int, default=10, help="kernel size") args = parser.parse_args() print(args) return args 註釋掉gen_trimap.py第37/43/49行的斷言語句 ```

assert(cnt1 == cnt2 + cnt3)

``` 導入os包

python import os 在67行,插入: python trimap_name_1 = trimap_name.split("/")[:-1] trimap_path = "/".join(trimap_name_1) if not os.path.exists(trimap_path): os.makedirs(trimap_path) 如果trimap路徑不存在則創建路徑。 修改完成後,運行gen_trimap.py,生成trimap圖。運行結果: 在這裏插入圖片描述 單張圖: 在這裏插入圖片描述

生成alpha圖

修改./data/knn_matting.py腳本,主要修改該main方法。 python def main(): with open('train.txt') as fs: list_path = fs.read().splitlines() for image_path in list_path: img_name = os.path.join(rgbDir, image_path) trimap_name = os.path.join(trimapDir, image_path[:-4] + '.png') alpha_name = os.path.join(alphaDir, image_path[:-4] + '.png') img_name = img_name.replace('\\', '/') trimap_name = trimap_name.replace('\\', '/') alpha_name = alpha_name.replace('\\', '/') index_path = alpha_name.rindex('/') alpha_dir = alpha_name[:index_path] if not os.path.exists(alpha_dir): os.makedirs(alpha_dir) img_name = './' + img_name img = cv2.imread(img_name) trimap = cv2.imread(trimap_name) alpha = knn_matte(img, trimap) cv2.imwrite(alpha_name, alpha * 255) 運行結果: 在這裏插入圖片描述 可以看出,我們己經得到比較精細的Alpha圖了。不過計算過程比較慢,幾分鐘一張圖。如果時間太長可以直接使用mask圖。

訓練

修改dataset.py文件

將dataset.py文件第17/18/19行修改為:

```python image_name = os.path.join(data_dir, 'clip_img', file_name['image'].replace("matting", "clip").replace("png", "jpg")) trimap_name = os.path.join(data_dir, 'trimap', file_name['trimap'].replace("clip", "matting")) alpha_name = os.path.join(data_dir, 'alpha', file_name['alpha'].replace("clip", "matting"))

`` ./data/clip_img/1803201916/clip_00000000/1803201916-00000117.png,這張圖片的格式有問題,需要修改為.jpg`格式

將dataset.py文件第101/102/103行,修改為 ``` trimap[trimap == 0] = 0 trimap[trimap >= 250] = 2 trimap[np.where(~((trimap == 0) | (trimap == 2)))] = 1

``` 原因:trimap圖是三色圖,但是它的“三色”並不像上圖中0/128/255只有這三色,它是在[0, 255]這個區間範圍內。所以新改的代碼,將這“三色”用區間區分,作為三種不同的label傳入訓練。

訓練T-Net

python train.py --dataDir='./data' --saveDir='./ckpt' --trainData='human_matting_data' --trainList='./data/train.txt' --lrdecayType='keep' --nEpochs=200 --save_epoch=1 --load='human_matting' --patch_size=320 --lr=1e-5 --nThreads=4 --train_batch=4 --train_phase='pre_train_t_net'

訓練M-Net:

python train.py --dataDir='./data' --saveDir='./ckpt' --trainData='human_matting_data' --trainList='./data/train.txt' --lrdecayType='keep' --nEpochs=400 --save_epoch=1 --load='human_matting' --patch_size=320 --lr=5e-6 --gpus='0' --nThreads=4 --train_batch=4 --train_phase='end_to_end'

測試

打開test_camera.py,修改如下參數: parser = argparse.ArgumentParser(description='human matting') parser.add_argument('--model', default='./ckpt/human_matting/model/model_obj.pth', help='preTrained model') parser.add_argument('--size', type=int, default=320,help='input size') parser.add_argument('--without_gpu', action='store_true', default=False, help='no use gpu') 然後,運行test_camera.py就可以得到運行結果,由於目前沒有訓練好,只是調通了算法 等調通算法後再展示詳細的結果。

代碼

http://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/85564296?spm=1001.2014.3001.5503 參考文章:

【SHM】Semantic Human Matting摳圖算法調試_zzZ_CMing的博客-CSDN博客_human matting