手把手:用OpenCV親手給小扎、Musk等科技大佬們做一張「平均臉」
作者:SATYA MALLICK
編譯:HAPPEN、Chloe、錢天培
請緊盯這張照片5秒鐘,你能否看出任何異樣呢?
照片中的女性同時擁有白人血統、西班牙人血統、亞洲人血統以及印度人血統。
她皮膚光彩無暇,眼神撲朔迷離,似乎美得不真實。
她並不真實存在,但她也並非完全虛構。
創造她的正是文摘菌今天要介紹的一項黑科技——「平(da)均(zhong)臉」。
文摘菌今天的手把手專欄將為大家介紹,如何用OpenCV隨心所欲幫各種人組合「平均臉」。完整的python代碼可在後台回復「平均臉」獲取。
讓我們先來看兩張文摘菌好奇的平均臉。
成功男性科技界企業家平均臉長什麼樣?
下圖是小扎,馬斯克,拉里·佩奇,和傑夫·貝索斯的平均臉。傑夫·貝索斯似乎拉低了發量平均值,不過幸好這張平均臉並沒有全禿。
Advertisements
小扎,馬斯克,拉里·佩奇,和傑夫·貝索斯的平均臉
奧斯卡最佳女主角平均臉又長什麼樣呢?
下圖為布麗·拉爾森,朱麗安·摩爾,凱特·布蘭切特,詹妮弗·勞倫斯的平均臉。這張平均臉真是非常迷人了!她的牙齒比企業家平均臉潔白整齊得多。一點也不意外!
近四屆奧斯卡最佳女主角:布麗·拉爾森,朱麗安·摩爾,凱特·布蘭切特,詹妮弗·勞倫斯的平均臉
最後,文摘菌還用平均臉生成了一張文摘家主編大大們的平均臉,翻到文末看大大們的顏值哦~
「平均臉」的歷史
為何平均臉的顏值看起來如此之高?在進入代碼實操之前,讓我們先來簡單了解一下平均臉的歷史。
「平均臉」源於達爾文的堂兄Francis Galton在1878年提出的一種新的攝影技術——通過對準眼睛來合成人臉。他認為,通過生成罪犯的平均臉,人們就可以根據面部特徵來預測一個人是否是罪犯。很顯然,他的假設是錯誤的——你不能通過照片來預測一個人是否是罪犯。然而,「平均臉」這個創意卻流傳了下來。
Advertisements
此後,多項研究證明,平均臉其實比個體臉更具有吸引力。在其中一項研究中,研究者們生成了22名入圍2002年德國小姐評選決賽的選手的平均臉,並讓吃瓜群眾打分。結果顯示人們認為平均臉比22位選手的臉更有吸引力,包括贏得比賽的柏林小姐。緊接著人們發現,柏林小姐的長相和這張平均臉非常接近。噢!原來柏林小姐的臉吸引人,正是因為她的臉接近平均水平!
按常理說,平均臉不應該很平庸嗎?為什麼平均臉吸引人?
根據進化假說,有性繁殖的動物會尋找長著平均臉的伴侶,因為偏離平均值可能產生不利的突變。平均臉也是對稱的,因為臉的左邊和右邊的變化是平均的。(文摘菌頓悟瞬間——原來「大眾臉」可以是個褒義詞。)
接下來,就讓我們一起來OpenCV學習創造「平均臉」!
美國總統的平均臉:從Carter到Obama
文摘菌將以美國總統的臉為例(因為美國總統像清晰且高度一致!),給大家介紹生成平均臉的關鍵技術步驟,完整的python代碼可在後台回復「平均臉」獲取。
步驟一:面部特徵檢測
首先,我們需要使用dlib庫在每張面部圖像上建立68個面部基準點。安裝dlib庫的步驟較為複雜,如果你無法成功安裝dlib,可以跳過該步,使用文摘菌為大家準備的面部基準點示例文檔(即為faces文檔中的txt文件)。
面部特徵檢測案例
步驟二:坐標轉換
我們手頭的面部圖像的尺寸很可能是不一樣的,同時面部也很可能處於圖像的不同位置,所以我們需要標準化面部特徵,並把它們放到同一參考坐標系下。
為了實現這一點,我們將圖像大小轉為600*600,把左眼(外眼角)放在像素位置(180,200),右眼(外眼角)放在像素位置(420,200)。我們稱該坐標系統為輸出坐標系統,稱原始圖像坐標為輸入坐標系統。
為什麼我要選擇上述點呢?
因為我希望確保兩隻眼睛的點都在一個水平線上,面部中心大約在離頂端三分之一高度的位置。所以我將眼角位置設為(0.3*寬,高/3)和(0.7*寬,高/3)。
在原始圖像的68個面部基準點中,左眼外眼角和右眼外眼角分別在基準點36和45。因此我們可以利用這兩個點計算圖像的相似變換矩陣(旋轉、變換和縮放),將輸入坐標系統的點進行轉換為輸出坐標系統。
3000*2300大小的輸入圖像通過相似變換矩陣轉為600*600大小的輸出圖像
什麼是相似變換矩陣?(不想學數學的同學可以簡單略過)
如果你想對一個正方形作出轉換,使正方形在x和y方向上分別縮放s_x和s_y,同時將它旋轉theta角度,再在x和y方向上平移t_x和t_y,對應的相似變換矩陣就是
對於一個(x, y)點來說,它的新位置就將會是
代碼實現很簡單(這裡你需要安裝cv2庫):
cv2.estimateRigidTransform(inPts, outPts, False)
相似變換矩陣是一個2*3矩陣,用於轉換點坐標或整個圖像。矩陣前兩列用於轉換與縮放,最後一列用於變換(如移位)。
這兒還存在一個小問題:
OpenCV要求你至少提供3個點,雖然通過兩點你就可以計算相似變換矩陣了。好消息是,我們可以簡單假設第三個點,讓它與已知的兩個點組成等邊三角形,然後我們就可以使用 estimateRigidTransform了。
得到相似變換矩陣后,我們就可以用來它將輸入圖像和基準點轉換生成輸出坐標了。我們使用warpAffine來轉換圖像,用transform來轉換點。(詳見代碼)
步驟三:人臉對齊
第二步后直接生成的平均臉
上一步中,我們能夠將所有的圖像和關鍵點變換到輸出圖像坐標系。現在所有圖像都是相同大小,並且眼睛的兩角都分別對齊。似乎對這些圖像每個像素的值進行平均我們就能得到平均臉啦。但如果你真這麼做了,會得到上圖這樣的結果。當然眼睛肯定是對齊的,但是其他面部特徵都沒對齊。
如果我們知道兩張輸入圖像的點如何一一對應,那我們很容易就能將兩張圖像完美對齊。然而我們並沒有這些信息。我們只知道這些輸入圖像68個對應點的位置。所以,我們可以用這68個點把圖像分成若干三角形區域,然後對齊這些區域,再對像素值進行平均。
平均基準點的Delaunay三角剖分
首先,我們需要計算這68個基準點的坐標平均值,我們利用這68個點(圖6藍色點)以及輸出圖像邊界上的8個點(上圖綠色點)來計算Delaunay三角剖分(上圖紅色邊框)。更多Delaunay三角剖分細節請看這裡(https://www.learnopencv.com/delaunay-triangulation-and-voronoi-diagram-using-opencv-c-python/)。
Delaunay三角剖分將圖像分解成若干三角形。Delaunay三角剖分的結果是一個三角形列表,用76個點(68個人臉基準點+8個邊界點)的序號表示。下面的矩陣展示了部分三角形列表,我們看到,關鍵點62、68和60形成一個三角形,32、50和49形成另一個三角形,等等。
[
62 68 60
32 50 49
15 16 72
9 8 58
53 35 36
… ]
基於Delaunay三角剖分的圖像扭曲
至此,我們計算出了人臉基準點的平均位置,並用這些位置計算出Delaunay三角剖分,將圖像分成若干三角形。如上圖所示,左圖是變換后輸入圖像的Delaunay三角剖分,中圖是平均關鍵點的三角剖分。注意,左圖的三角形1對應中圖的三角形1。用左圖三角形1的三個頂點及其對應的中圖三個頂點計算變換矩陣。用這一變換將左圖三角形1中的所有像素變換到中圖的三角形1中去。對左圖每個三角形重複該過程,得到右圖這一結果。右圖只是將左圖扭曲到平均臉。
第四步:人臉平均
現在,激動人心的時刻到了!
經過了上述處理之後,我們就可以對這些照片的像素取平均值,得到神奇的平均臉了。
當然,你也可以生成對稱臉,將一張臉及其鏡像進行平均。比如:
對奧巴馬的圖像(左)及其鏡像(右)進行平均得到對稱臉(中)
彩蛋部分!文摘菌也製作了編輯大大們的平均臉。噔噔噔噔!
歡迎評論猜他們都是誰呀:)