教你一個(gè)簡單的深度學(xué)習(xí)方法檢測人臉面部特征
筆者按:你可能在一些手機(jī)軟件上已經(jīng)看到了給人臉增加特效的app,它們將一些可愛有趣的物體添加到自拍視頻中,有些更有趣的還能檢測表情自動(dòng)選擇相應(yīng)的物體。這篇文章將會(huì)科普一種使用深度學(xué)習(xí)進(jìn)行人臉表情檢測的方法,并簡要介紹下傳統(tǒng)的檢測方法。
在過去,檢測面部及其特征,包括眼睛、鼻子、嘴巴,甚至從它們的形狀中提取表情是非常困難的,而現(xiàn)在,這項(xiàng)任務(wù)可以通過深度學(xué)習(xí)“神奇”地得到解決,任何一個(gè)聰明的年輕人都可以在幾個(gè)小時(shí)內(nèi)完成。雷鋒網(wǎng) AI 科技評論編譯的這篇來自佐治亞理工大學(xué)學(xué)生 Peter Skvarenina 的文章將介紹這一實(shí)現(xiàn)方法。
“傳統(tǒng)”的方法(CLM)
假設(shè)你和我一樣,現(xiàn)在需要進(jìn)行人臉追蹤(在這篇文章的情況下,是指將一個(gè)人的面部動(dòng)作通過網(wǎng)絡(luò)攝像頭同步到一個(gè)動(dòng)畫人物上去),你可能會(huì)發(fā)現(xiàn),以前實(shí)現(xiàn)這個(gè)任務(wù)最好的算法是局部約束模型(CLM),基于Cambridge Face Tracker或者OpenFace。這種方法是將檢測的任務(wù)進(jìn)行分解,分成檢測形狀向量特征(ASM)、布丁圖像模板(AAM)和使用預(yù)先訓(xùn)練的線性SVM進(jìn)行檢測優(yōu)化這幾個(gè)步驟逐一處理。
首先對關(guān)鍵點(diǎn)進(jìn)行粗略估計(jì),然后使用含有部分人臉信息的預(yù)訓(xùn)練的圖像進(jìn)行SVM處理,同時(shí)對關(guān)鍵點(diǎn)的位置進(jìn)行校正。重復(fù)這個(gè)過程多次,直到其產(chǎn)生的誤差低于我們的要求。另外,值得一提的是,這一方法假定了圖像上的人臉位置已經(jīng)被估計(jì),如使用Viola-Jones檢測器(Haar級(jí)聯(lián))。但是,這種方法非常復(fù)雜并不是高中級(jí)別的學(xué)生可以輕易實(shí)現(xiàn)的,整體架構(gòu)如下:
深度學(xué)習(xí)(Deep Learning)
為了實(shí)現(xiàn)文中一開始提到的,使得青少年可以進(jìn)行人臉檢測的目標(biāo),我們向大家介紹深度學(xué)習(xí)的方法。在這里,我們將會(huì)使用一種非常簡單的卷積神經(jīng)網(wǎng)絡(luò)(CNN,convolutional neural network)并在一些含有人臉的圖像上進(jìn)行人臉重要部位的檢測。為此,我們首先需要一個(gè)訓(xùn)練的數(shù)據(jù)庫,這邊我們可以使用Kaggle提供的人臉部位識(shí)別挑戰(zhàn)賽的數(shù)據(jù)庫,包含15個(gè)關(guān)鍵點(diǎn);或者一個(gè)更復(fù)雜些的數(shù)據(jù)庫MUCT,它有76個(gè)關(guān)鍵點(diǎn)(超棒的!)。
很顯然的,有質(zhì)量的圖像訓(xùn)練數(shù)據(jù)庫是必不可少的,這里,我們向“可憐的”本科學(xué)生致敬,他們?yōu)榱水厴I(yè)“犧牲”了自己的時(shí)間和精力對這些圖像進(jìn)行了標(biāo)注,從而使得我們可以進(jìn)行這些有趣的實(shí)驗(yàn)。
如下是基于Kaggle數(shù)據(jù)庫的巴洛克面部和關(guān)鍵點(diǎn)的樣子:
這個(gè)數(shù)據(jù)庫是由灰度96*96分辨率的圖像組成的,并且有15個(gè)關(guān)鍵點(diǎn),分別包含兩個(gè)眼睛各5個(gè)點(diǎn)、鼻子嘴巴共5個(gè)點(diǎn)。
對于任何一個(gè)圖像來說,我們首先要對臉部進(jìn)行定位,即使用上文提到的Viola-Jones檢測器并基于Haar級(jí)聯(lián)架構(gòu)(如果說你仔細(xì)看看這一實(shí)現(xiàn)過程,會(huì)發(fā)現(xiàn)它與CNN的概念相近)。如果你想更近一步,也可以使用全卷積網(wǎng)絡(luò)(FCN,F(xiàn)ully Convolutional Network)并使用深度預(yù)測進(jìn)行圖像分割。
不管你使用什么方法,這對OpenCV來說都很簡單:
- Grayscale_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
- face_cascade =
- cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’
- )
- bounding_boxes =
- face_cascade.detectMultiScale(grayscale_image, 1.25, 6)
使用如上的幾行代碼,可將圖像中的人臉框出來。
然后,對每一個(gè)返回的人臉框,我們提取其中相應(yīng)的子圖像,將它們調(diào)整到灰度圖像并將尺寸轉(zhuǎn)換為96*96。新產(chǎn)生的圖像數(shù)據(jù)則成為了我們完成的CNN網(wǎng)絡(luò)的輸入。CNN的架構(gòu)采用最通用的,5*5的卷積層(實(shí)際上是3個(gè)layer,每層分別是24、36和48個(gè)ReLU),然后用2個(gè)3*3的卷積層(每個(gè)有64個(gè)ReLU),最后使用3個(gè)全連接層(包含500、90和30個(gè)單元)。同時(shí)使用Max Pooling來避免過擬合并使用global average pooling來減少平滑參數(shù)的數(shù)量。這一架構(gòu)的最終輸出結(jié)果是30個(gè)浮點(diǎn)數(shù),這對應(yīng)著15個(gè)關(guān)鍵點(diǎn)每個(gè)的想x,y坐標(biāo)值。
如下是Keras的實(shí)現(xiàn)過程:
- model = Sequential()
- model.add(BatchNormalization(input_shape=(96, 96, 1)))
- model.add(Convolution2D(24, 5, 5, border_mode=”same”,
- init=’he_normal’, input_shape=(96, 96, 1),
- dim_ordering=”tf”))
- model.add(Activation(“relu”))
- model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
- border_mode=”valid”))
- model.add(Convolution2D(36, 5, 5))
- model.add(Activation(“relu”))
- model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
- border_mode=”valid”))
- model.add(Convolution2D(48, 5, 5))
- model.add(Activation(“relu”))
- model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
- border_mode=”valid”))
- model.add(Convolution2D(64, 3, 3))
- model.add(Activation(“relu”))
- model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2),
- border_mode=”valid”))
- model.add(Convolution2D(64, 3, 3))
- model.add(Activation(“relu”))
- model.add(GlobalAveragePooling2D());
- model.add(Dense(500, activation=”relu”))
- model.add(Dense(90, activation=”relu”))
- model.add(Dense(30))
你可能想選擇均方根傳播(rmsprop)優(yōu)化和均方誤差(MSE)作為損失函數(shù)和精度指標(biāo)。只需要在輸入圖像上使用批處理正?;腿制骄闅v(global average polling)和HE normal weight初始化,你就可以在30個(gè)訓(xùn)練周期內(nèi)獲得80%-90%的驗(yàn)證準(zhǔn)確率并實(shí)現(xiàn)<0.001的誤差:
- model.compile(optimizer=’rmsprop’, loss=’mse’, metrics=
- [‘accuracy’])
- checkpointer = ModelCheckpoint(filepath=’face_model.h5',
- verbose=1, save_best_only=True)
- epochs = 30
- hist = model.fit(X_train, y_train, validation_split=0.2,
- shuffle=True, epochs=epochs, batch_size=20, callbacks=
- [checkpointer], verbose=1)
簡單的執(zhí)行如下指令對關(guān)鍵點(diǎn)位置進(jìn)行預(yù)測:
- features = model.predict(region, batch_size=1)
好了!現(xiàn)在你已經(jīng)學(xué)會(huì)了怎么去檢測面部關(guān)鍵點(diǎn)了!
提醒一下,你的預(yù)測結(jié)果是15對(x,y)坐標(biāo)值,可在如下圖像中表現(xiàn)出來:
如果上述的操作還不能滿足你的需求,你還可以進(jìn)行如下步驟:
- 實(shí)驗(yàn)如何在保持精度和提高推理速度的同時(shí)減少卷積層和濾波器的數(shù)量;
- 使用遷移學(xué)習(xí)來替代卷積的部分(Xception是我的最愛)
- 使用一個(gè)更詳細(xì)的數(shù)據(jù)庫
- 做一些高級(jí)的圖像增強(qiáng)來提高魯棒性
你可能依然覺得太簡單了,那么推薦你學(xué)習(xí)去做一些3D的處理,你可以參考Facebook和NVIDIA是怎么進(jìn)行人臉識(shí)別和追蹤的。
另外,你可以用已經(jīng)學(xué)到的這些進(jìn)行一些新奇的事情(你可能一直想做但不知道怎么實(shí)現(xiàn)):
- 在視頻聊天時(shí),把一些好玩的圖片放置在人臉面部上,比如:墨鏡,搞笑的帽子和胡子等;
- 交換面孔,包括你和朋友的臉,動(dòng)物和物體等;
- 在自拍實(shí)時(shí)視頻中用一些新發(fā)型、珠寶和化妝進(jìn)行產(chǎn)品測試;
- 檢測你的員工是因?yàn)楹染茻o法勝任一些任務(wù);
- 從人們的反饋表情中提取當(dāng)下流行的表情;
- 使用對抗網(wǎng)絡(luò)(GANs)來進(jìn)行實(shí)時(shí)的人臉-卡通變換,并使用網(wǎng)絡(luò)實(shí)現(xiàn)實(shí)時(shí)人臉和卡通動(dòng)畫表情的同步。
好了~你現(xiàn)在已經(jīng)學(xué)會(huì)了怎么制作你自己的視頻聊天濾鏡了,快去制作一個(gè)有趣的吧!