基於阿里Semantatic Human Matting演算法,實現精細化人物摳圖
持續創作,加速成長!這是我參與「掘金日新計劃 · 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
- YoloV5實戰:手把手教物體檢測——YoloV5
- 基於阿里Semantatic Human Matting演算法,實現精細化人物摳圖
- PPv3-OCR自定義資料從訓練到部署
- 如何下載pytorch的歷史版本?
- WinForm——Button總結
- WinForm——MDI窗體
- 升級 pip
- 將8位的tif圖片改為png圖片
- RepLKNet實戰:使用RepLKNet實現對植物幼苗的分類(非官方)(二)
- 關於OpenCV imread和imdecode讀取圖片是BGR的證明
- opencv讀取圖片通道以及顯示
- 萬字整理聯邦學習系統架構設計參考
- 編譯器堆空間不足
- 【影象分類】實戰——使用EfficientNetV2實現影象分類(Pytorch)
- MMDetection實戰:MMDetection訓練與測試
- UNet語義分割實戰:使用UNet實現對人物的摳圖
- MobileVIT實戰:使用MobileVIT實現影象分類
- SwinIR實戰:如何使用SwinIR和預訓練模型實現圖片的超分
- 【影象分類】手撕ResNet——復現ResNet(Pytorch)
- Deeplab實戰:使用deeplabv3實現對人物的摳圖