手把手:用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中去。對左圖每個三角形重複該過程,得到右圖這一結果。右圖只是將左圖扭曲到平均臉。

  • 第四步:人臉平均

現在,激動人心的時刻到了!

經過了上述處理之後,我們就可以對這些照片的像素取平均值,得到神奇的平均臉了。

當然,你也可以生成對稱臉,將一張臉及其鏡像進行平均。比如:

對奧巴馬的圖像(左)及其鏡像(右)進行平均得到對稱臉(中)

彩蛋部分!文摘菌也製作了編輯大大們的平均臉。噔噔噔噔!

歡迎評論猜他們都是誰呀:)

Advertisements

你可能會喜歡