傳統演算法和深度學習的結合和實踐,解讀與優化 deepfake

前言

前一段時間用於人物換臉的deepfake火爆了朋友圈,早些時候Cycle GAN 就可以輕鬆完成換臉任務,其實換臉是計算機視覺常見的領域,比如Cycle GAN3dmm,以及下文引用的論文均可以使用演算法實現換臉(一定程度上能模仿表情),而不需要使用PS等軟體手工換臉(表情僵硬,不符合視頻上下文),只能說deepfake用一個博取眼球的角度切入了換臉演算法,所以一開始我並沒有太過關注這方面,以為是Cycle GAN乾的,後來隱約覺得不對勁,因為GAN系列確實在image to image 的領域有著非凡的成績,但GAN的訓練是出了名的不穩定,而且收斂時間長,某些特定的數據集時不時需要有些trick,才能保證效果。但deepfake似乎可以無痛的在各個數據集里跑,深入閱讀開源代碼後(github.com/deepfakes/fa),發現這東西很多值得一說的地方和優化的空間才有了這一篇文章。

(本文首發於公眾號AI研習社)

本文主要包括以下兩方面:

  • 解讀deepfake的model和預處理與後處理的演算法以引用論文。(目前大多文章只是介紹了其中的神經網路,然而這個項目並不是單純的end2end的輸出,所以本文還會涉及其他CV的演算法以及deepfake的介紹)
  • 引入膚色檢測演算法,提升換臉的視覺效果。

乾貨和口水齊飛,各位客官可安心食用

DeepFake Model

雖然原作者沒有指出,但從模型和整體方法設計來說,該模型應該是參考了論文arxiv.org/abs/1611.0957,其網路結構總體仍是encoder - decoder的形式,但與我們所熟知autoencoder不同的是,他由一個Encoder和兩個Decoder組成,兩個Decoder分別對應imageA和imageB的解碼。

  1. Encoder部分採用了簡單的堆疊5x5卷積核,採用aplha=0.1的LeakRelu作為激活函數。
  2. Decoder部分使用了卷積和PixelShuffer來做上採樣,結構上採用了4x4,8x8……64x64這樣逐解析度增加的重建方式(網路整體是類U-net的結構)。

(圖為u-net)

如果你想要復現和改進模型的話,需要主要一點的是,雖然我們期望輸入A臉然後輸出B臉,輸入B臉輸出A臉,但訓練卻不把AB臉作為pair輸進神經網路(輸入A臉,期望在另一端獲得B臉),仍然是像訓練普通autoencoder的一樣,我給出A臉,你要復原A臉,B臉亦然。(用不同的decoder),這樣訓練的結果是decoderA能學會用A的信息復原A,decoderB用B的信息復原B,而他們共用的Encoder呢?則學會了提取A,B的共有特徵,比如眼睛的大小,皮膚的紋理,而解碼器根據得到的編碼,分別找對應的信息復原,這樣就能起到換臉的效果了。

而Encoder獲取到共同的特徵,比單獨學習A/B的特徵,信息要損失得更為嚴重,故會產生更模糊得效果,另一個照片模糊得原因是autoencoder使用得是均方誤差(mse)這一點已經是不可置否的了,後文提及的使用GAN來優化,可以一定程度上緩解模糊的問題。

預處理和後處理

在文處,我就強調了這個不是end2end的東西,接下來就著找介紹deepfake里的預處理和後處理。

我們都知道在CV里用深度學習解決問題前,需要用進行數據增強,然而涉及人臉的數據增強的演算法和平時的有一點點不一樣。

在開源代碼中,作者分別使用了random_transform,random_warp 兩個函數來做數據增強。但這個兩個函數只是做一些一些有關比例之類的參數的封裝,真正做了轉換的是opencv的warpAffine,rmap,兩個函數。下面分別解讀這兩個函數做了些什麼。

首先解讀rmap 其直譯過來就是重映射,其所做的就是將原圖的某一個像素以某種規則映射到新的圖中。利用該函數,可以完成圖像的平移,反轉等功能。

在數據增強中,我們不希望改動數據會影響label的分布,在常見的有監督任務中,數據的標籤由人工打上,如類別,位置等,圖像的扭曲,反轉不會影響到label的分布,但在deepfake中,我們做的是生成任務,作為無監督任務中的一種,其反向轉播的誤差由圖像自己的提供,而要使得數據增強後(代碼中的warped_image)有對應的樣本(代碼中的target_image),作者使用了rmap構造除warped_image,而使用umeyamawarpAffine 構造出target_image

umeyama是一種點雲匹配演算法,簡單點來理解就是將源點雲(source cloud)變換到目標點雲(target cloud)相同的坐標系下,包含了常見的矩陣變換和SVD的分解過程,(礙於篇幅本文不作詳解)。調用umeyama後獲取變換所需的矩陣,最後將原圖和所求得矩陣放進warpAffine即可獲的增強後對應的target_image。其中warpAffine的功能就是根據變換矩陣對源矩陣進行變換。

上圖是經過變型處理的warped_image ,下圖是target_image .

後處理

說完了數據增強部分後,我們來分解後處理。

在deepfake(上述鏈接中)的命令行版本中,有一個-P參數,選中後可以實時演示圖片的變化過程。在通過預覽這個演變過程中,不難發現進入神經網路的不是整張圖片,也不是使用extract出來的整個256x256的部分(頭像),而是僅僅只有臉部的小區域(64x64)。因此在預測階段,首先就是截取人臉,然後送進網路,再根據網路的輸出覆蓋原圖部分。

至於將頭像部分傳進網路,也並非不行,臉部還是會可以進行轉換,但背景部分也會變得模糊,且很難修復,因此我們只選擇臉部替換。

在臉部替換後,會出現如下問題:

  • 膚色差異,即使是同種人,也會有細微的差異。
  • 光照差異,每張照片的光照環境不同
  • 假臉邊界明顯

前兩者的造成原因一是客觀差異,二是和數據集的大小相關,作為想給普通的用戶用,數據集太大了,用戶承受不起,數據集太小,神經網路學習不多。

至於最後一點則是前兩者造成的,但這一點可以通過降低解析度緩解。這也是很多網上小視頻假臉邊界不明顯的原因,因為很少會有一張臉占屏幕80%的畫面。但如果你直接用在256x256的頭像圖上則邊界效果明顯(如下圖)

(原圖,下文所有圖片的原圖都是這個,由官方提供)

該圖使用的是官方提供的預訓練權重和數據。接下來在試試低尺寸下的視覺效果

使用64x64後,相對來說,邊界效果沒那明顯了。

至於另外的兩個問題,官方給出了下面的幾種後處理方法緩減:

smooth_mask

這個方法解釋其實起來很簡單,你神經網路輸出的圖像不是很模糊嗎?要模糊變清晰很難,但清晰變糊還不簡單嗎?直接用高斯模糊將邊界進行處理,從而讓過度看起來自然。

adjust_avg_color

這個方法背後的理論同樣很簡單,假設A圖要換成B圖,那麼做法就是A圖加上自身和B圖的每一個像素的均值的差值,算是作為一種色彩的調和。

(左圖未經處理,右圖經過上述兩種方法處理。)

以上兩種便是deepfake默認的處理方式。下面介紹另外一種圖像編輯常用的演算法,這種演算法作為deepfake的後備選項,由參數-S 控制。

泊松融合

此外,deepfake給出了基於泊松融合演算法 的來進行後處理,泊松融合的大致思想提供一個一個mask矩陣,背景區域為0,ROI區域(region of insteresing 這裡就是指臉部,下文同一簡稱ROI)的區域為255,演算法通過該矩陣得知拿一步分是融合的部分,然後通過計算梯度,用梯度場作為指示,修改ROI的像素值,使得邊界與原圖更為貼切。

(圖片源於網路)

deepfake中的泊松融合可以選擇兩種模式。一種以人臉矩形框為邊界,另一種以人的特徵點(即人臉輪廓和眼睛輪廓)為邊界。

(左圖未經處理,右圖在整個替換區域進行泊松融合)

事實上,這裡得補充一點,人臉檢測和定位如果不想自己實現,一般有兩種實現方法(在本地實現),一種是使用dlib庫提供的api,另一種是使用opencv。dlib,face_recongize的模型比opencv的精度要高的,但要自己下載模型(模型比較大),且這個庫的編譯在windows上比較麻煩,但對於特徵點檢測,opencv沒有現成的特徵點檢測的介面。如果有童孩不想依賴dlib,這裡提供一種方法來代替在泊松融合時的特徵點定位問題。(人臉檢測可以使用opencv即可)

膚色檢測

顯然,我們選擇人臉的特徵點的位置信息,目的時為了只替換人臉,這樣可以盡量將信息損失(模糊)局限於人臉部分,而其他部分則保留原圖的清晰度,而我們剛才說過了,deepfake並不將全圖放進神經網路,而是將人臉部分(由人臉檢測演算法確定),定位後的ROI是以人臉為主的矩形,這時唯一的膚色就只有人臉部分了,不用太過擔心其餘噪音干擾。

如果再人臉定位這一步出錯,那麼使用膚色檢測還是人臉特徵點兩種方法,都不會有太大差別。因此,使用膚色檢測在這種場景上,在效果上一定程度能代替人臉特徵點檢測這種方法。

下面解釋膚色檢測如何使用。總的來說,膚色檢測一般常見RGB,HSV和YCrCb空間的檢測,所謂的YCrCb空間,Y代表的是亮度,Cr 與Cb代表的都是色度,而HSV空間H代表色調,S飽和度,V亮度,RGB則是常見的紅綠藍空間。

下面只介紹RGB空間下的膚色檢測,無需依賴其他庫,手寫即可,亦可以達到不錯的效果。

規則部分:

  1. R>G and R>B and |R - G| > 15
  2. 在(1)滿足下,(R > 95) and (G > 40) and (B > 20) and (max(R, G, B) - min(R, G, B) > 15)
  3. 在(1)滿足,(2)不滿足下,(R > 220) and (G > 210) and (B > 170),則可認為該像素是膚色。

( 左圖未經處理,右圖經過膚色模型構造mask矩陣,再進行泊松融合)

可以優化的空間

最後說說deepfake可以優化的空間。

deepfake出現後也有很多工作對deepfake進行優化,包括使用GAN的,這些優化的針對生成圖像的質量,但目前看質量沒有太大的提升,同時幾乎沒有工作是針對模型的訓練速度和圖像的後處理。

本文最後提出的膚色檢測代替原來人臉特徵點檢測的,算是一種補充。

我也曾經嘗試過一些模型壓縮的演算法,雖然在原始數據下可以恢復精度,但遷移的能力差(因為參數少了)。而deepfake的目的是做成一款app,(已經有了,叫fakeapp,在deepfake的基礎上添加了GUI),那麼就不能不考慮軟體的體積,fakeapp共1.8G,以及沒有GPU的普通用戶在自己數據集上遷移的時間。

在Reddit上,作者是指出,在GPU上模型訓練要幾小時,而CPU要近3天,這已經超出很多人的忍受範圍了。

深度學習走入尋常百姓家,尤其是有自定製需求的深度學習,仍然任重道遠。


推薦閱讀:

利用點雲掃描技術增強FM視覺功能
【生成高清人臉】ProgressiveGAN 筆記
圖像檢索之Large-Scale Image Retrieval with Attentive Deep Local Features
【技術綜述】從alexnet到resnet,初探深度學習演算法玩攝影
Rocket Training: 一種提升輕量網路性能的訓練方法

TAG:計算機視覺 | 深度學習DeepLearning |