變裝之faceswap

程序整體思想分爲以下幾個部分,

 

(1)使用Dlib進行人臉檢測和68個關鍵點定位

這裏使用的是ERT方法,源自論文 One Millisecond Face Alignment with an Ensemble of RegressionTrees,算是一種比較老的方法了。但是效果很好。

(2)進行旋轉,縮放,平移等變換,即aligement操作,使得第二個圖和原始圖相互吻合

這裏使用的是普式變換(Ordinary Procrustes Analysis),最終結果是要使得變換過程滿足下面式子最小化,簡單的說,就是第一個圖的68個點經過仿射變換(warp_affine)後,和第二個圖的68個點的距離最小。

其中,R是2*2的旋轉變換矩陣,S是一個線性縮放矩陣,T是一個二維平移向量,p,q分別爲上面計算的2個人的68個點。

那麼問題來了,現在只已經2個圖的68個點,如何求解上面的S,R,T呢,這裏使用奇異值SVD分解( Singular Value Decomposition),從而求出R。

U, S, Vt = numpy.linalg.svd(points1.T * points2)
R = (U * Vt).T

最終返回變換矩陣

return numpy.vstack([numpy.hstack(((s2 / s1) * R,
                                       c2.T - (s2 / s1) * R * c1.T)),
                         numpy.matrix([0., 0., 1.])])

有了該變換矩陣,就可以使用opencv的warpAffine函數,將第二張圖片變爲和第一種圖片同樣的空間位置。

(3)將第二個圖的顏色匹配到第一個圖

如果直接將第二個圖覆蓋到第一個圖,會發現,在邊緣地方2個人的膚色和關照等會出現明顯的區別,這裏使用了顏色平衡( RGB scaling colour-correction)的方法,這裏主要進行的操作就是,分別對圖片1,2進行高斯濾波,生成高斯濾波後的1,2圖片,然後對第二個圖片除以自己的高斯濾波後的圖片,再乘以第一個圖片的高斯濾波後的圖片,從而生成最終變換後的圖片。

這裏高斯核的選擇是一個重點,太小的話,會將第一個圖的特徵顯示到第二個圖上,太大又會將人臉以外的區域覆蓋到第二個圖上,這裏選取0.6倍的瞳距。

im1_blur = cv2.GaussianBlur(im1, (blur_amount, blur_amount), 0)
im2_blur = cv2.GaussianBlur(im2, (blur_amount, blur_amount), 0)

# Avoid divide-by-zero errors.
im2_blur += 128 * (im2_blur <= 1.0)

return (im2.astype(numpy.float64) * im1_blur.astype(numpy.float64) /
                                                im2_blur.astype(numpy.float64))

(4)將第二個圖的人臉特徵,通過使用掩碼的方式混合融合進第一個圖

這裏主要是要生成一個掩碼,通過該掩碼來進行圖像融合,在掩碼爲1的地方顯示圖像2,掩碼爲1的地方顯示圖像1,掩碼0-1之間的地方進行融合。

生成掩碼的思路爲,先通過人臉關鍵點生成一個凸包(convexHull),然後扣出凸包中的像素,進行高斯濾波,生成mask,然後將1,2兩幅圖的mask進行max操作,生成最終的mask。

最終通過一個阿爾法變換,用2個圖片生成最終想要的結果。

output_im = im1 * (1.0 - combined_mask) + warped_corrected_im2 * combined_mask

當然這個並沒有網上的H5的效果好,但是基本還是有模有樣的。

實驗效果如下,第一張是變換後的圖,第二張是原圖。

 

 

reference:

https://github.com/matthewearl/faceswap

http://matthewearl.github.io/2015/07/28/switching-eds-with-python/

https://github.com/hrastnik/FaceSwap

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章