聊聊人像抠图背后的算法技术
本文將從算法概述、工程實(shí)現(xiàn)、優(yōu)化改進(jìn)三個(gè)方面闡述如何實(shí)現(xiàn)一個(gè)實(shí)時(shí)、優(yōu)雅、精確的視頻人像摳圖項(xiàng)目。
什么是摳圖
對(duì)于一張圖I, 我們感興趣的人像部分稱為前景F,其余部分為背景B,則圖像I可以視為F與B的加權(quán)融合:I = alpha * F + (1 - alpha) * BI=alpha?F+(1?alpha)?B,而摳圖任務(wù)就是找到合適的權(quán)重alpha。值得一提的是,如圖,查看摳圖ground truth可以看到,alpha是[0, 1]之間的連續(xù)值,可以理解為像素屬于前景的概率,這與人像分割是不同的。如圖,在人像分割任務(wù)中,alpha只能取0或1,本質(zhì)上是分類任務(wù),而摳圖是回歸任務(wù)。
摳圖ground truth:
分割ground truth:
相關(guān)工作
我們主要關(guān)注比較有代表性的基于深度學(xué)習(xí)的摳圖算法。目前流行的摳圖算法大致可以分為兩類,一種是需要先驗(yàn)信息的Trimap-based的方法,寬泛的先驗(yàn)信息包括Trimap、粗糙mask、無人的背景圖像、Pose信息等,網(wǎng)絡(luò)使用先驗(yàn)信息與圖片信息共同預(yù)測(cè)alpha;另一種則是Trimap-free的方法,僅根據(jù)圖片信息預(yù)測(cè)alpha?,對(duì)實(shí)際應(yīng)用更友好,但效果普遍不如Trimap-based的方法。
Trimap-based
Trimap是最常用的先驗(yàn)知識(shí),顧名思義Trimap是一個(gè)三元圖,每個(gè)像素取值為{0,128,255}其中之一,分別代表前景、未知與背景,如圖。
Deep Image Matting
多數(shù)摳圖算法采用了Trimap作為先驗(yàn)知識(shí)。Adobe在17年提出了Deep Image Matting[^1],這是首個(gè)端到端預(yù)測(cè)alpha的算法,整個(gè)模型分Matting encoder-decoder stage與Matting refinement stage兩個(gè)部分,Matting encoder-decoder stage是第一部分,根據(jù)輸入圖像與對(duì)應(yīng)的Trimap,得到較為粗略的alpha matte。Matting refinement stage是一個(gè)小的卷積網(wǎng)絡(luò),用來提升alpha matte的精度與邊緣表現(xiàn)。
本文在當(dāng)時(shí)達(dá)到了state-of-the-art,后續(xù)很多文章都沿用了這種“粗略-精細(xì)”的摳圖思路,此外,由于標(biāo)注成本高,過去摳圖任務(wù)的數(shù)據(jù)是非常有限的。本文還通過合成提出了一個(gè)大數(shù)據(jù)集Composition-1K,將精細(xì)標(biāo)注的前景與不同背景融合,得到了45500訓(xùn)練圖像和1000測(cè)試圖像,大大豐富了摳圖任務(wù)的數(shù)據(jù)。
Background Matting
Background Matting[^2]是華盛頓大學(xué)提出的摳圖算法,后續(xù)發(fā)布了Backgroun MattingV2,方法比較有創(chuàng)新點(diǎn),并且在實(shí)際工程應(yīng)用中取得了不錯(cuò)的效果。
同時(shí),由于Adobe的數(shù)據(jù)都是基于合成的,為了更好的適應(yīng)真實(shí)輸入,文中提出一個(gè)自監(jiān)督網(wǎng)絡(luò)訓(xùn)練G_{Real}GReal?來對(duì)未標(biāo)注的真實(shí)輸入進(jìn)行學(xué)習(xí)。G_{Real}GReal?輸入與G_{Adobe}GAdobe?相同,用G_{Adobe}GAdobe?輸出的alpha matte與F來監(jiān)督G_{Real}GReal?的輸出得到loss,此外,G_{Real}GReal?的輸出合成得到的RGB還將通過一個(gè)鑒別器來判斷真?zhèn)蔚玫降诙€(gè)loss,共同訓(xùn)練G_{Real}GReal?。
文中列舉了一些使用手機(jī)拍攝得到的測(cè)試結(jié)果,可以看到大部分情況結(jié)果還是很不錯(cuò)的。
Background Matting V2
Background Matting得到了不錯(cuò)的效果,但該項(xiàng)目無法實(shí)時(shí)運(yùn)行,也無法很好的處理高分辨率輸入。所以項(xiàng)目團(tuán)隊(duì)又推出了Background Matting V2[^3],該項(xiàng)目可以以30fps的速度在4k輸入上得到不錯(cuò)的結(jié)果。
文章實(shí)現(xiàn)高效高分辨率摳圖的一個(gè)重要想法是,alpha matte中大部分像素是0或1,只有少量的區(qū)域包含過渡像素。因此文章將網(wǎng)絡(luò)分為base網(wǎng)絡(luò)和refine網(wǎng)絡(luò),base網(wǎng)絡(luò)對(duì)低分辨率圖像進(jìn)行處理,refine網(wǎng)絡(luò)根據(jù)base網(wǎng)絡(luò)的處理結(jié)果選擇原始高分辨率圖像上特定圖像塊進(jìn)行處理。
base網(wǎng)絡(luò)輸入為c倍下采樣的圖像與背景,通過encoder-decoder輸出粗略的alpha matte、F、error map與hidden features。將采樣c倍得到的error map E_cEc?上采樣到原始分辨率的\frac{1}{4}41?為E_4E4?,則E_4E4?每個(gè)像素對(duì)應(yīng)原圖4x4圖像塊,從E_4E4?選擇topk error像素,即為原始topk error 4x4圖像塊。在選擇出的像素周圍裁剪出多個(gè)8x8圖像塊送入refine網(wǎng)絡(luò)。refine網(wǎng)絡(luò)是一個(gè)two-stage網(wǎng)絡(luò),首先將輸入通過部分CBR操作得到第一階段輸出,與原始輸入中提取的8x8圖像塊cat后輸入第二階段,最后將refine后的圖像塊與base得到的結(jié)果交換得到最終的alpha matte和F。
此外文章還發(fā)布了兩個(gè)數(shù)據(jù)集:視頻摳圖數(shù)據(jù)集VideoMatte240K與圖像摳圖數(shù)據(jù)集PhotoMatte13K/85。VideoMatte240K收集了484個(gè)高分辨率視頻,使用Chroma-key軟件生成了240000+前景和alpha matte對(duì)。PhotoMatte13K/85則是在良好光照下拍攝照片使用軟件和手工調(diào)整的方法得到13000+前景與alpha matte數(shù)據(jù)對(duì)。大型數(shù)據(jù)集同樣是本文的重要貢獻(xiàn)之一。
此外還有一些文章如Inductive Guided Filter[^4]、MGMatting[^5]等,使用粗略的mask作為先驗(yàn)信息預(yù)測(cè)alpha matte,在應(yīng)用時(shí)也比trimap友好很多。MGMatting同時(shí)也提出了一個(gè)有636張精確標(biāo)注人像的摳圖數(shù)據(jù)集RealWorldPortrait-636,可以通過合成等數(shù)據(jù)增廣方法擴(kuò)展使用。
Trimap-free
實(shí)際應(yīng)用中先驗(yàn)信息獲取起來是很不方便的,一些文章將先驗(yàn)信息獲取的部分也放在網(wǎng)絡(luò)中進(jìn)行。
Semantic Human Matting
阿里巴巴提出的Semantic Human Matting[^6]同樣分解了摳圖任務(wù),網(wǎng)絡(luò)分為三個(gè)部分,T-Net對(duì)像素三分類得到Trimap,與圖像concat得到六通道輸入送入M-Net,M-Net通過encoder-decoder得到較為粗糙的alpha matte,最后將T-Net與M-Net的輸出送入融合模塊Fusion Module,最終得到更精確的alpha matte。
網(wǎng)絡(luò)訓(xùn)練時(shí)的alpha loss分為alpha loss與compositional loss,與DIM類似,此外還加入了像素分類lossL_tLt?,最終loss為:L = L_p + L_t=L_\alpha + L_c + L_tL=Lp?+Lt?=Lα?+Lc?+Lt?。文章實(shí)現(xiàn)了端到端Trimap-free的摳圖算法,但較為臃腫。此外文章提出Fashion Model數(shù)據(jù)集,從電商網(wǎng)站收集整理了35000+標(biāo)注的圖片,但并沒有開放。
Modnet
modnet[^7]認(rèn)為神經(jīng)網(wǎng)絡(luò)更擅長(zhǎng)學(xué)習(xí)單一任務(wù),所以將摳圖任務(wù)分為三個(gè)子任務(wù),分別進(jìn)行顯式監(jiān)督訓(xùn)練和同步優(yōu)化,最終可以以63fps在512x512輸入下達(dá)到soft結(jié)果,因此在后續(xù)的工程實(shí)現(xiàn)中我也選擇了modnet作為Baseline。
網(wǎng)絡(luò)的三個(gè)子任務(wù)分別是Semantic Estimation、Detail Prediction和Semantic-Detail Fusion,Semantic Estimation部分由backbone與decoder組成,輸出相對(duì)于輸入下采樣16倍的semantics,用來提供語義信息,此任務(wù)的ground truth是標(biāo)注的alpha經(jīng)過下采樣與高斯濾波得到的。 Detail Prediction任務(wù)輸入有三個(gè):原始圖像、semantic分支的中間特征以及S分支的輸出S_pSp?,D分支同樣是encoder-decoder結(jié)構(gòu),值得留意的該分支的loss,由于D分支只關(guān)注細(xì)節(jié)特征,所以通過ground truth alpha生成trimap,只在trimap的unknown區(qū)域計(jì)算d_pdp?與\alpha_gαg?的L_1L1?損失。F分支對(duì)語義信息與細(xì)節(jié)預(yù)測(cè)進(jìn)行融合,得到最終的alpha matte與ground truth計(jì)算L_1L1?損失,網(wǎng)絡(luò)訓(xùn)練的總損失為:L=\lambda_sL_s + \lambda_dL_d+\lambda_{\alpha}L_{\alpha}L=λs?Ls?+λd?Ld?+λα?Lα?。
最后,文章還提出了一種使視頻結(jié)果在時(shí)間上更平滑的后處理方式OFD,在前后兩幀較為相似而中間幀與前后兩幀距離較大時(shí),使用前后幀的平均值平滑中間幀,但該方法會(huì)導(dǎo)致實(shí)際結(jié)果比輸入延遲一幀。
此外,U^2U2-Net、SIM等網(wǎng)絡(luò)可以對(duì)圖像進(jìn)行顯著性摳圖,感興趣的話可以關(guān)注一下。
數(shù)據(jù)集
-
Adobe Composition-1K
-
matting_human_datasets
-
VideoMatte240K
-
PhotoMatte85
-
RealWorldPortrait-636
評(píng)價(jià)指標(biāo)
常用的客觀評(píng)價(jià)指標(biāo)來自于2009年CVPR一篇論文[^8],主要有:
此外,可以在paperwithcode上查看Image Matting任務(wù)的相關(guān)文章,在Alpha Matting網(wǎng)站上查看一些算法的evaluation指標(biāo)。
本項(xiàng)目的最終目的是在HiLens Kit硬件上落地實(shí)現(xiàn)實(shí)時(shí)視頻讀入與背景替換,開發(fā)環(huán)境為HiLens配套在線開發(fā)環(huán)境HiLens Studio,先上一下對(duì)比baseline的改進(jìn)效果:
使用modnet預(yù)訓(xùn)練模型modnet_photographic_portrait_matting.ckpt進(jìn)行測(cè)試結(jié)果如下:
可以看到由于場(chǎng)景較為陌生、逆光等原因會(huì)導(dǎo)致?lián)笀D結(jié)果有些閃爍,雖然modnet可以針對(duì)特定視頻進(jìn)行自監(jiān)督finetune,但我們的目的是在普遍意義上效果更好,因此沒有對(duì)本視頻進(jìn)行自監(jiān)督學(xué)習(xí)。
優(yōu)化后的模型效果如下:
本視頻并沒有作為訓(xùn)練數(shù)據(jù)。可以看到,摳圖的閃爍情況減少了很多,毛發(fā)等細(xì)節(jié)也基本沒有損失。
工程落地
為了測(cè)試baseline效果,首先我們要在使用場(chǎng)景下對(duì)baseline進(jìn)行工程落地。根據(jù)文檔導(dǎo)入/轉(zhuǎn)換本地開發(fā)模型可知
昇騰310 AI處理器支持模型格式為".om",對(duì)于Pytorch模型來說可以通過"Pytorch->Caffe->om"或"Pytorch->onnx->om"(新版本)的轉(zhuǎn)換方式得到,這里我選擇的是第一種。Pytorch->Caffe模型轉(zhuǎn)換方法與注意事項(xiàng)在之前的博客中有具體闡述過,這里不贅述。轉(zhuǎn)換得到Caffe模型后,可以在HiLens Studio中直接轉(zhuǎn)為om模型,非常方便。
首先在HiLens Studio中新建一個(gè)技能,此處選擇了空模板,只需要修改一下技能名稱就可以。
將Caffe模型上傳到model文件夾下:
在控制臺(tái)中運(yùn)行模型轉(zhuǎn)換命令即可得到可以運(yùn)行的om模型:
/opt/ddk/bin/aarch64-linux-gcc7.3.0/omg --model=./modnet_portrait_320.prototxt --weight=./modnet_portrait_320.caffemodel --framework=0 --output=./modnet_portrait_320 --insert_op_conf=./aipp.cfg接下來完善demo代碼。在測(cè)試時(shí)HiLens Studio可以在工具欄選擇使用視頻模擬攝像頭輸入,或連接手機(jī)使用手機(jī)進(jìn)行測(cè)試:
具體的demo代碼如下:
# -*- coding: utf-8 -*- # !/usr/bin/python3 # HiLens Framework 0.2.2 python demo ? import cv2 import os import hilens import numpy as np from utils import preprocess import time ? ? def run(work_path):hilens.init("hello") # 與創(chuàng)建技能時(shí)的校驗(yàn)值一致 ?camera = hilens.VideoCapture('test/camera0_2.mp4') # 模擬輸入的視頻路徑display = hilens.Display(hilens.HDMI) ?# 初始化模型model_path = os.path.join(work_path, 'model/modnet_portrait_320.om') # 模型路徑model = hilens.Model(model_path) ?while True:try:input_yuv = camera.read()input_rgb = cv2.cvtColor(input_yuv, cv2.COLOR_YUV2RGB_NV21)# 摳圖后替換的背景bg_img = cv2.cvtColor(cv2.imread('data/tiantan.jpg'), cv2.COLOR_BGR2RGB) crop_img, input_img = preprocess(input_rgb) # 預(yù)處理s = time.time()matte_tensor = model.infer([input_img.flatten()])[0]print('infer time:', time.time() - s)matte_tensor = matte_tensor.reshape(1, 1, 384, 384) ?alpha_t = matte_tensor[0].transpose(1, 2, 0)matte_np = cv2.resize(np.tile(alpha_t, (1, 1, 3)), (640, 640))fg_np = matte_np * crop_img + (1 - matte_np) * bg_img # 替換背景view_np = np.uint8(np.concatenate((crop_img, fg_np), axis=1))print('all time:', time.time() - s) ?output_nv21 = hilens.cvt_color(view_np, hilens.RGB2YUV_NV21)display.show(output_nv21) ?except Exception as e:print(e)break ?hilens.terminate()其中預(yù)處理部分的代碼為:
import cv2 import numpy as np ? ? TARGET_SIZE = 640 MODEL_SIZE = 384 ? ? def preprocess(ori_img):ori_img = cv2.flip(ori_img, 1)H, W, C = ori_img.shapex_start = max((W - min(H, W)) // 2, 0)y_start = max((H - min(H, W)) // 2, 0)crop_img = ori_img[y_start: y_start + min(H, W), x_start: x_start + min(H, W)]crop_img = cv2.resize(crop_img, (TARGET_SIZE, TARGET_SIZE))input_img = cv2.resize(crop_img, (MODEL_SIZE, MODEL_SIZE)) ?return crop_img, input_imgdemo部分的代碼非常簡(jiǎn)單,點(diǎn)擊運(yùn)行即可在模擬器中看到效果:
模型推理耗時(shí)44ms左右,端到端運(yùn)行耗時(shí)60ms左右,達(dá)到了我們想要的實(shí)時(shí)的效果。
效果改進(jìn)
預(yù)訓(xùn)練模型在工程上存在著時(shí)序閃爍的問題,原論文中提出了一種使視頻結(jié)果在時(shí)間上更平滑的后處理方式OFD,即用前后兩幀平均誤差大的中間幀。但這種辦法只適合慢速運(yùn)動(dòng),同時(shí)會(huì)導(dǎo)致一幀延遲,而我們希望可以對(duì)攝像頭輸入進(jìn)行實(shí)時(shí)、普適的時(shí)序處理,因此OFD不適合我們的應(yīng)用場(chǎng)景。
在Video Object Segmentation任務(wù)中有一些基于Memory Network的方法(如STM),摳圖領(lǐng)域也有新論文如DVM考慮引入時(shí)序記憶單元使摳圖結(jié)果在時(shí)序上更穩(wěn)定,但這些方法普遍需要前后n幀信息,在資源占用、推理實(shí)時(shí)性、適用場(chǎng)景上都與我們希望的場(chǎng)景不符合。
考慮到資源消耗與效果的平衡,我們采用將前一幀的alpha結(jié)果cat到當(dāng)前幀RGB圖像后共同作為輸入的方法來使網(wǎng)絡(luò)在時(shí)序上更穩(wěn)定。
網(wǎng)絡(luò)上的修改非常簡(jiǎn)單,只需在模型初始化時(shí)指定in_channels = 4:
modnet = MODNet(in_channels=4, backbone_pretrained=False)訓(xùn)練數(shù)據(jù)方面,我們選擇一些VideoMatting的數(shù)據(jù)集:VideoMatte240K、ConferenceVideoSegmentationDataset。
最初,我們嘗試將前一幀alpha作為輸入、缺失前幀時(shí)補(bǔ)零這種簡(jiǎn)單的策略對(duì)模型進(jìn)行訓(xùn)練:
if os.path.exists(os.path.join(self.alpha_path, alpha_pre_path)):alpha_pre = cv2.imread(os.path.join(self.alpha_path, alpha_pre_path)) else:alpha_pre = np.zeros_like(alpha)net_input = torch.cat([image, alpha_pre], dim=0)收斂部署后發(fā)現(xiàn),在場(chǎng)景比較穩(wěn)定時(shí)模型效果提升較大,而在人進(jìn)、出畫面時(shí)模型適應(yīng)較差,同時(shí)如果某一幀結(jié)果較差,將對(duì)后續(xù)幀產(chǎn)生很大影響。針對(duì)這些問題,考慮制定相應(yīng)的數(shù)據(jù)增強(qiáng)的策略來解決問題。
- 人進(jìn)、出畫面時(shí)模型適應(yīng)較差:數(shù)據(jù)集中空白幀較少,對(duì)人物入畫出畫學(xué)習(xí)不夠,因此在數(shù)據(jù)處理時(shí)增加空白幀概率:
- 某一幀結(jié)果較差,將對(duì)后續(xù)幀產(chǎn)生很大影響:目前的結(jié)果較為依賴前一幀alpha,沒有學(xué)會(huì)拋棄錯(cuò)誤結(jié)果,因此在數(shù)據(jù)處理時(shí)對(duì)alpha_pre進(jìn)行一定概率的仿射變換,使網(wǎng)絡(luò)學(xué)會(huì)忽略偏差較大的結(jié)果;
- 此外,光照問題仍然存在,在背光或光線較強(qiáng)處摳圖效果較差:對(duì)圖像進(jìn)行光照增強(qiáng),具體的,一定概率情況下模擬點(diǎn)光源或線光源疊加到原圖中,使網(wǎng)絡(luò)對(duì)光照更魯棒。光照數(shù)據(jù)增強(qiáng)有兩種比較常用的方式,一種是通過opencv進(jìn)行簡(jiǎn)單的模擬,具體可以參考augmentation.py,另外還有通過GAN生成數(shù)據(jù),我們使用opencv進(jìn)行模擬。
重新訓(xùn)練后,我們的模型效果已經(jīng)可以達(dá)到前文展示的效果,在16T算力的HiLens Kit上完全達(dá)到了實(shí)時(shí)、優(yōu)雅的效果。進(jìn)一步的,我還想要模型成為耗時(shí)更少、效果更好的優(yōu)秀模型~目前在做的提升方向是:
- 更換backbone:針對(duì)應(yīng)用硬件選擇合適的backbone一向是提升模型性價(jià)比最高的方法,直接根據(jù)耗時(shí)與資源消耗針對(duì)硬件搜一個(gè)模型出來最不錯(cuò),目前搜出來的模型轉(zhuǎn)為onnx測(cè)試結(jié)果(輸入192x192):
- 模型分支:在使用的觀察中發(fā)現(xiàn),大部分較為穩(wěn)定的場(chǎng)景可以使用較小的模型得到不錯(cuò)的結(jié)果,所有考慮finetune LRBranch處理簡(jiǎn)單場(chǎng)景,HRBranch與FusionBranch依舊用來處理復(fù)雜場(chǎng)景,這項(xiàng)工作還在進(jìn)行中。
[^1]: Xu, Ning, et al. “Deep image matting.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2017
[^2]:Sengupta, Soumyadip, et al. “Background matting: The world is your green screen.” Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2020.
[^3]:Lin, Shanchuan, et al. “Real-Time High-Resolution Background Matting.” arXiv preprint arXiv:2012.07810 (2020).
[^4]:Li, Yaoyi, et al. “Inductive Guided Filter: Real-Time Deep Matting with Weakly Annotated Masks on Mobile Devices.” 2020 IEEE International Conference on Multimedia and Expo (ICME). IEEE, 2020.
[^5]: Yu, Qihang, et al. “Mask Guided Matting via Progressive Refinement Network.” arXiv e-prints (2020): arXiv-2012.
[^6]: Chen, Quan, et al. “Semantic human matting.” Proceedings of the 26th ACM international conference on Multimedia. 2018.
[^7]: Ke, Zhanghan, et al. “Is a Green Screen Really Necessary for Real-Time Human Matting?.” arXiv preprint arXiv:2011.11961 (2020).
[^8]:Rhemann, Christoph, et al. “A perceptually motivated online benchmark for image matting.” 2009 IEEE Conference on Computer Vision and Pattern Recognition. IEEE, 2009.
?
點(diǎn)擊關(guān)注,第一時(shí)間了解華為云新鮮技術(shù)~
總結(jié)
以上是生活随笔為你收集整理的聊聊人像抠图背后的算法技术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【leetcode_1220】【困难】c
- 下一篇: (七)视频背景移除/去背景/换背景/抠图