美顏技術分享 | 從AR口紅虛擬試妝



隨着人工智能技術的不斷髮展,各大美顏軟件的妝容變得越來越“自然無痕跡”,大家可能會好奇這背後的技術原理是什麼。因此,本期“技術的真相”將通過簡易的AR口紅試妝帶大家走進虛擬試妝技術。

美顏技術學習交流羣(歡迎加入)


一、   項目簡介

在剛剛過去的七夕選禮物的重要儀式中,大家有沒有在挑選口紅時感到茫然,就怕一不小心買成“直男”色號。其實,在許多電商平臺都已經具備了試妝功能,點擊按鈕之後就能夠嘗試口紅、睫毛、腮紅、眉毛、眼影等多種美妝產品的試戴效果,實現足不出戶就能選到心儀的美妝產品,而這種功能的背後就是虛擬試妝算法。

虛擬試妝算法是一種典型的計算機視覺與計算機圖形學相結合的技術,它通過檢測面部區域的關鍵點,在特定區域使用AR增強現實的渲染技術,最終可以實現模擬化妝效果,能夠在電商、直播、短視頻等平臺具有廣泛的應用。本文將從零開始搭建一個簡單的AR口紅試妝系統,幫助大家加深對於虛擬試妝技術的理解。

二、 技術實現

通常虛擬試妝算法主要包含檢測上妝區域以及妝容渲染兩個步驟,下面本文將分別介紹實現方案。


01 檢測上妝區域

1. 人臉關鍵點檢測

在上妝之前,我們需要知道在哪些位置進行上妝,因此,我們首先對於輸入的圖片進行人臉的關鍵點檢測。

目前市面上有多家視覺廠商提供了人臉關鍵點檢測的功能,本文選擇使用了Face++人工智能開放平臺提供的人臉關鍵點檢測 (https://www.faceplusplus.com.cn/sdk/face-landmarks/) 註冊控制檯賬號,創建API Key,下載SDK開始實現。對於試妝來說關鍵點數量越多,最終的試妝效果越好,本文以介紹流程爲主,因此使用的關鍵點數量較少,有興趣的讀者可以選擇使用Face++提供的人臉稠密關鍵點。

(圖:可視化人臉關鍵點)

2. 人臉關鍵點平滑

通常我們使用的AR試妝系統均爲實時系統,因此,我們需要將視頻流拆解成單幀圖像輸入到人臉關鍵點檢測網絡,這導致輸出的視頻中人臉關鍵點會有一定的抖動。其中一方面是因爲預測的關鍵點與實際關鍵點位置有小幅度的偏差,導致視頻中相鄰幀之間預測點位差異超過了實際點位的差異。另一方面,視頻中人眼觀察的靜止與圖像實際的靜止狀態存在差異,實際圖像在像素級別存在差異,而模型對這種圖像微小差異不夠魯棒。爲了緩解關鍵點抖動問題,我們需要對人臉關鍵點進行平滑後處理,這裏我們選擇使用一階的卡爾曼濾波進行處理,其中有兩點需要注意:

(1)使用關鍵點的移動距離來估計系統過程噪聲。 如果檢測關鍵點與前一個時刻的預測點的距離差別較小,則變化大概率由於檢測誤差引起的,需要降低過程噪聲,反之當兩者距離差別較大時,則需要提高系統的過程噪聲。這樣的處理也可以從另一個角度來理解,當檢測關鍵點與前一個時刻的預測值距離較大時,說明關鍵點的真實值進行了移動,這時我們很難觀察到關鍵點是否有抖動,通過提高系統過程噪聲誤差,能夠減少預測的關鍵點與真實的關鍵點之間的距離,從而提高關鍵點的跟隨性。而當檢測的關鍵點與前一個時刻預測值的距離較小時,關鍵點的抖動較爲明顯,適當降低系統的過程誤差,能夠減弱觀測輸入帶來的影響。

(2)根據實際模型估計系統觀測誤差R。 通常系統觀測誤差R與關鍵點檢測模型具有較強的相關性,當系統觀測誤差R的增大,預測關鍵點的抖動效果會減弱,同時會產生“拖影”效果,爲了準確的估計系統觀測誤差,往往需要根據實際的使用效果進行調節,使其能夠在抖動與“拖影”中取得平衡。

關鍵點卡爾曼濾波

       
       
       
#系統觀測誤差,根據模型進行調節 R = 0.05 #輸入爲前一個時刻的預測值、前一個時刻的預測誤差,當前時刻的觀測值 #輸出爲當前時刻的預測值、當前時刻的預測誤差 def kalman_filter(last_predict_point, last_P, input_point): #通過當前觀測值與前一時刻預測值的距離,計算系統過程噪聲 distance = dis(input_point - last_predict_point) alpha = clamp(distance/max_distance, 0.0, 1.0) #系統過程噪聲誤差 Q = alpha + eps #系統預測誤差 P = last_P + Q #卡爾曼增益 K = P / (P + R) #當前時刻的預測值 cnt_predict_point = last_predict_point + K * (input_point - last_predict_point) #更新當前時刻預測誤差 cnt_P = (1 - K)* P return cnt_predict_point, cnt_P


02 妝容渲染

1. 人像美化

如果簡單的對輸入圖片進行口紅渲染,會使得效果非常突兀。通常小姐姐們在塗口紅前,都需要上一層粉底,以達到提亮膚色、襯托口紅的效果, 因此我們在妝容渲染之前也需要進行一步人像美化 。人像美化主要包含磨皮、美白、瘦臉、大眼等功能,本文將主要實現磨皮、美白功能。

磨皮

目前較爲通用的磨皮算法的框架如下圖,對於輸入圖像,首先進行膚色的檢測得到膚色的區域圖,然後對於輸入圖像進行相應的濾波算法。最後,根據膚色區域將原圖與濾波後的圖像進行融合,在膚色區域使用濾波後的圖片,其他區域使用輸入圖像,通常爲了提升融合效果,會先對膚色檢測的結果進行高斯模糊,再根據係數進行融合。

皮膚檢測

又名膚色檢測、皮膚概率檢測。在磨皮算法中,通常需要確定圖像中磨皮的位置,以達到精確磨皮的效果。之所以選擇根據膚色檢測結果而不是人臉檢測區域進行磨皮,是因爲人臉檢測只能確定面部區域,這會導致脖子與面部交界的位置出現明顯區別,影響效果。爲了解決這個問題,一種比較簡單的想法是統計大量皮膚像素的顏色數據,分析皮膚顏色的取值範圍,得到基於RGB空間的膚色判斷條件如下:

R>95&&G>40&&B>20&&R>G&&R>B&&max(R,G,B)−min(R,G,B)>15&&abs(RG)>15

如果輸入像素顏色滿足該條件,即爲膚色像素,通常我們會生成一個與原圖相同大小的mask,並對mask進行高斯blur,用於濾波圖像與原圖的融合。

 (圖:皮膚檢測區域)

濾波算法

這裏使用的濾波算法主要作用是在平滑皮膚的同時,保留五官的細節,因此需要選擇一些能夠保留邊緣信息的濾波算法。目前可以做磨皮的保邊濾波主要有以下幾種:表面模糊、雙邊濾波、導向濾波等。考慮到性能與效果的平衡,我們選擇使用表面模糊的算法。表面模糊是一種Photoshop中常用的濾波算法,其思想是計算像素鄰域內不同像素的加權平均,對於邊緣處的像素,權重比較小,能夠較爲完整的保留;對於非邊緣處的區域,權重比較大,平滑的效果較好。假設像素I(i,j)I(i,j)周圍半徑R大小的鄰域爲S,鄰域內的像素爲I(k,l)I(k,l),則濾波後的像素值爲:

表面模糊處理有2個參數,即模糊半徑R和模糊閾值Y,前者確定模糊的範圍,後者確定模糊的程度,代碼實現如下:

表面模糊

       
       
       
#表面模糊Surface Blur #references:https://blog.csdn.net/shinian1987/article/details/78345408 def sur_blur ( I_in, thre=20, half_size=10): I_out = I_in * 1.0 row, col = I_in.shape w_size = half_size * 2 + 1 for ii in range (half_size, row-1-half_size): for jj in range (half_size, col-1-half_size): aa = I_in [ii-half_size:ii+half_size+1, jj-half_size : jj+half_size+1] p0 = I_in [ii, jj] mask_1 = numpy.matlib.repmat(p0, w_size, w_size) mask_2 = 1-abs(aa-mask_1)/(2.5*thre); mask_3 = mask_2 * (mask_2 > 0) t1 = aa * mask_3 I_out[ii, jj] = t1.sum()/mask_3.sum()
return I_out


磨皮效果如下:

(圖:磨皮效果,左:原圖,右:磨皮後)

美白

美白算法主要的目的爲提亮膚色,一個比較常見的方式是通過顏色查找表方式將膚色映射到理想的範圍。顏色查找表的原理是對於每一個給定的RGB顏色,都能夠在查找表中找到一個顏色與之對應,並將映射後的顏色使用一張圖像的方式進行存儲。我們使用的查找表如下圖:


使用查找表的代碼如下:

查找表

       
       
       
#獲取濾鏡顏色 #輸入爲圖像、查找表、圖像中位置 #輸出爲對應位置的顏色值 def getBGR(img, table, i, j): #獲取圖像顏色 b, g, r = img[i][j] #計算標準顏色表中顏色的位置座標 x = int(g/4 + int(b/32) * 64) y = int(r/4 + int((b%32) / 4) * 64) #返回濾鏡顏色表中對應的顏色 return table[x][y]
#簡單使用代碼 img = cv2.imread('input.png') lut_map = cv2.imread('lut.png') rows, cols = img.shape[:2] dst = np.zeros((rows, cols, 3), dtype="uint8") for i in range(rows): for j in range(cols): dst[i][j] = getBGR(img, lut_map, i, j)


最終效果如下:


其中左邊爲原圖,右邊爲增加美白濾鏡後的圖片,美白不宜添加過渡,容易喧賓奪主。

2.妝容渲染

爲了保證妝容渲染能夠達到實時的效果,通常需要使用OpenGL的技術進行渲染,這裏將簡單介紹妝容渲染的主要流程。

素材生成需要根據指定的顏色、材質等信息,生成對應的素材,如需要形狀等靜態效果只需要加載靜態圖片資源作爲紋理即可,如需要光效等動態效果則需要在shader中進行實現。

位置對齊通常將人臉關鍵點的位置作爲頂點座標,將素材作爲紋理,關鍵點對應的位置作爲紋理座標進行渲染,以達到將素材位置與實際位置對齊的效果

顏色融合這一步會將口紅mask與底色進行融合,通常在shader中進行實現,融合的方式有多種,對於口紅來說,可以使用透明度融合的方式,但口紅mask透明度儘量控制在30%以下,以保證效果較爲自然,也可以嘗試選用其他的融合方式如疊加等。


三、 總結與展望

本文簡單介紹了口紅虛擬試妝系統的主要流程,並提供了部分功能的核心代碼,其他區域的妝容渲染大同小異,讀者可以自行進行嘗試。由於每個人對於美的定義都有所區別,讀者也可以根據個人的需求調整美妝效果。未來將進一步介紹膚質檢測相關算法,敬請期待。

四、 參考文獻

1. Face++開放平臺:https://github.com/FacePlusPlus/facepp-python-sdk
2. 卡爾曼濾波:https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/
3. 人臉關鍵點:https://zhuanlan.zhihu.com/p/73783609
4. 美顏美妝:https://blog.csdn.net/dQCFKyQDXYm3F8rB0/article/details/104889909

努力分享優質的計算機視覺相關內容,歡迎關注:

交流羣


歡迎加入公衆號讀者羣一起和同行交流,目前有美顏、三維視覺計算攝影、檢測、分割、識別、醫學影像、GAN算法競賽等微信羣


     
           
           
           
個人微信(如果沒有備註不拉羣!
請註明: 地區+學校/企業+研究方向+暱稱



下載1:何愷明頂會分享


AI算法與圖像處理」公衆號後臺回覆:何愷明,即可下載。總共有6份PDF,涉及 ResNet、Mask RCNN等經典工作的總結分析


下載2:終身受益的編程指南:Google編程風格指南


AI算法與圖像處理」公衆號後臺回覆:c++,即可下載。歷經十年考驗,最權威的編程規範!



   
         
         
         
下載3 CVPR2021

AI算法與圖像處公衆號後臺回覆: CVPR 即可下載1467篇CVPR 2020論文 和 CVPR 2021 最新論文


本文分享自微信公衆號 - AI算法與圖像處理(AI_study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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