萬聖節教你用 OpenCV Remix 一張 n 合1臉

大家好,我是爲人造的智能操碎了心的智能禪師。

在這個多逝之秋,禪師要哀悼一下金庸先生。昨晚上驚聞噩耗,頓感無比感慨。金庸先生的武俠,影響了好幾代人。滄海一聲笑,滔滔兩岸潮。浮沉隨浪只記今朝,先生一路走好!

今天是萬聖節?,就是國外的中元節。可能是唯一一個沒有被過程情人節、能讓人體會真正快樂的,年輕人中流行的節日。禪師在這裏,祝願大家每年萬聖節都是 Coser,不被 Cos。?

每年萬聖節,大家一般都是化妝成?啊、?啊,?啊……反正是怎麼?怎麼醜怎麼來。

今年禪師就想,老是這些東西也沒什麼新鮮的。昨晚上打開櫃子,看着裏面躺着去年買的?面具,前年買的?面具,大前年買的?,?,?……突然有一個大膽的想法:

要是所有兇惡的臉,用 CV 給合成爲一張量,是不是就能出現一張獨一無二、天下第一兇惡的臉呢?

緣,妙不可言。

咱們的特約作者李燁老師還真就有一篇 OpenCV + dlib + Caffe 合成人臉的文章。

順便推薦一下 Google 的萬聖節 Doodle 對戰小遊戲,可以和網友 battle。下面是禪師的對戰視頻:

全文大約2000字。讀完可能需要好幾首下面這首歌的時間

?

解決方案

通過 Image Morphing 技術,給定兩張圖片 I 和 J ,就可以疊加(或者叫做混合)I 和 J 來獲得一張中間狀態的圖片 M。

I 和 J 的疊加由一個參數[0,1]區間內的參數 alpha 來控制。當 alpha=0時,M 就等同於 I,而 aphla=1時,M 就爲 J。

換言之, M 中的每一個像素 M(x,y),都可以通過這樣一個公式來得到它的值:

M(x,y) = (1 – alpha)·I(x,y) + alpha·J(x,y)

當 alpha=0.5的時候,I 和 J 就五五開,平均貢獻了 M。如果 I 和 J 是兩張人臉照片的話,M 自然也就成了它們的“平均臉”。

看起來好容易哦,那我們趕緊找兩張照片來試試吧!就用這兩張:

這兩張照片alpha=0.5後直接疊加的結果是這樣的:

從這張“重影圖”上不難看出來,之所以這樣,是因爲最基本的五官都沒有對齊。雖然差強人意,但還算的上比較順利吧。接下來我們把把兩個人的眼睛和嘴對齊,看看是什麼效果。

對齊人臉

要想對齊兩張人臉,需要建立兩張照片中像素的對應關係。

對 I 中的某一個像素點(xi,yi),找到它在 J 中的對應點 (xj,yj),進一步找到 M 中這兩個點疊加之後所處位置(xm,ym)。再用下面算式1(記住這個標號,後面有用)計算出 M 中對應點的像素值:

xm = (1-alpha) · xi + alpha · xj

ym = (1-alpha) · yi + alpha · yj

將上面的過程運用到整幅畫每一個像素點上算式2(記住這個標號,後面有用):

M(xm,ym) = (1 – alpha)·I(xi,yi) + alpha·J(xj,yj)

接下來,可以把一張人臉分割成若干三角形的區域,疊加兩張臉上對應的三角區域。

具體方法如下:

1. 獲取人臉特徵

我們先在每張面孔上獲取68個面部基準點?。

2. Delaunay 三角剖分

在獲得了68個面部基準點之後,我們結合人臉所在的矩形的四個頂點和每條邊的中心點,將人臉所在的矩形分割成如下圖所示的三角形的組合。

3. 基於Delaunay剖分三角形的仿射變換

得到這些Delaunay剖分三角形後,再分別對齊各個區域,對其中像素值進行平均。

使用前述的算式1,根據圖像I和圖像J中已經獲得的76個點,在疊加的結果圖像M中找到76個點(xm, ym)

從圖像I中選取一個三角形 ti,在 M 中找到對應區域 tm,通過 ti 三個頂點到 tm 三個頂點的映射關係來計算 ti 到 tm 的仿射變換。同理計算出tj到tm的仿射變換。

重複這個過程,處理圖像 I 中的每一個三角形,得到一個扭曲的(warped)圖像 I'。用同樣的方法處理圖像 J,獲得扭曲的圖像 J'。

得到了扭曲的圖像 I'和圖像 J'。這兩個圖像就可以直接使用算式2進行疊加了。最後得到疊加結果:

疊加人臉

算式2用於疊加2張人臉,在alpha=0.5時求取的是兩張臉的平均。

那麼我們把算式推廣一下,從圖像I和圖像J推廣爲圖像I_1, I_2, I_3, ..., I_n;令 alpha=1/n;則算式2變形爲如下:

M(xm,ym) = 1/n · [I_1(xi_1, yi_1) + I_2(xi_2, yi_2) + ... ... + I_n(xi_n, yi_n)]

由此,我們也就得到了n張臉的平均。

用這個方法,我們可以得到6位美國總統的平均臉:

他們平均之後的樣子是這樣的:

代碼實現

代碼下載: https://github.com/juliali/AverageFace

之前是從描述角度來講解平均臉原理。現在,我們來看看code。

[Code -1 ] 使用dlib來進行人臉識別和人臉特徵點的提取

[Code-2] 根據特徵點獲得Delaunay剖分三角

[Code-3] 計算仿射變換

[Code-4] 通過仿射變換扭曲Delaunay剖分三角形

區分性別

經過嘗試,合成後的臉怎麼看都感覺是男的。至於如何訓練模型來區分性別,掃描下方二維碼來獲取答案吧 ?

參考資料

【1】 AverageFace 代碼、模型及樣例圖片

【2】 FaceGenderClassification 配置文件及命令

【3】 原始的性別分類模型

【4】Delaunay三角剖分原理

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