python3+dlib實(shí)現(xiàn)人臉識(shí)別和情緒分析
一、介紹
我想做的是基于人臉識(shí)別的表情(情緒)分析??吹骄W(wǎng)上也是有很多的開(kāi)源庫(kù)提供使用,為開(kāi)發(fā)提供了很大的方便。我選擇目前用的比較多的dlib庫(kù)進(jìn)行人臉識(shí)別與特征標(biāo)定。使用python也縮短了開(kāi)發(fā)周期。
官網(wǎng)對(duì)于dlib的介紹是:Dlib包含廣泛的機(jī)器學(xué)習(xí)算法。所有的設(shè)計(jì)都是高度模塊化的,快速執(zhí)行,并且通過(guò)一個(gè)干凈而現(xiàn)代的C ++ API,使用起來(lái)非常簡(jiǎn)單。它用于各種應(yīng)用,包括機(jī)器人技術(shù),嵌入式設(shè)備,手機(jī)和大型高性能計(jì)算環(huán)境。
雖然應(yīng)用都比較高大上,但是自己在PC上做個(gè)情緒分析的小軟件還是挺有意思的。
按照自己的想法與思路設(shè)計(jì)識(shí)別方式。目前也比較火的keras好像就是根據(jù)嘴型的變化作為情緒分析的一個(gè)指標(biāo)。
而我的想法是利用嘴的張開(kāi)比例,眼睛的睜開(kāi)程度,眉毛的傾斜角度作為情緒分析的三個(gè)指標(biāo)。但是由于人與人長(zhǎng)相的差異較大,五官的也是千差萬(wàn)別,再加上我的計(jì)算方法也比較簡(jiǎn)單。所以識(shí)別效率并不是很高。
識(shí)別規(guī)則:
1、嘴巴張開(kāi)距離占面部識(shí)別框?qū)挾鹊谋壤酱?,說(shuō)明情緒越激動(dòng),可能是非常開(kāi)心,也可能是極度憤怒。
2、眉毛上揚(yáng),17-21 或者 22-26 號(hào)特征點(diǎn)距離面部識(shí)別框頂部與識(shí)別框高度的比值越小,說(shuō)明眉毛上揚(yáng)越厲害,可表示驚訝、開(kāi)心。眉毛的傾斜角度,開(kāi)心時(shí)眉毛一般是上揚(yáng),憤怒時(shí)皺眉,同時(shí)眉毛下壓的比較厲害。
3、瞇眼睛,人在開(kāi)懷大笑的時(shí)候會(huì)不自覺(jué)的瞇起眼睛,憤怒或者驚訝的時(shí)候會(huì)瞪大眼睛。
系統(tǒng)缺點(diǎn):不能捕捉細(xì)微表情的變化,只能大致的判斷出人的情緒,開(kāi)心、憤怒、驚訝、自然。
系統(tǒng)優(yōu)點(diǎn):結(jié)構(gòu)簡(jiǎn)單,易于上手。
應(yīng)用領(lǐng)域:微笑抓拍,捕捉瞬間的美好、緩解兒童自閉癥、交互式游戲開(kāi)發(fā)。
由于人感情的復(fù)雜性,這些表情確實(shí)不能完完全全的代表一個(gè)人內(nèi)心深處的情緒波動(dòng),如要提高判斷的準(zhǔn)確性,則需要心率檢測(cè)、語(yǔ)音處理等綜合評(píng)價(jià)。
二、開(kāi)發(fā)環(huán)境搭建:
1、安裝VS2015,因?yàn)樽钚掳娴膁lib-19.10需要這個(gè)版本的vscode
2、安裝opencv(whl方式安裝):
從pythonlibs下載需要的版本whl文件,比如(opencv_python?3.3.0+contrib?cp36?cp36m?win_amd64.whl)
然后在本地使用pip install 安裝。 注意文件位置下安裝(如:C:\download\xxx.whl)
3、安裝dlib(whl方式安裝):
在這里下載dlib的各種版本的whl文件,然后在根目錄下打開(kāi)cmd直接安裝即可。
但是為了學(xué)習(xí)使用dlib中的各種python實(shí)例程序,還是需要下載一個(gè)dlib的壓縮包。
直接訪問(wèn)dlib官網(wǎng)即可下載:http://dlib.net/ml.html
dlib各種版本的whl文件:https://pypi.python.org/simple/dlib/
4、如果想要使用人臉模型特征標(biāo)定的話,還需要一個(gè)人臉面部形狀預(yù)測(cè)器,這個(gè)可以通過(guò)自己的照片進(jìn)行訓(xùn)練,也可以使用dlib作者給出的一個(gè)訓(xùn)練好的預(yù)測(cè)器:
點(diǎn)擊下載:http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
三、實(shí)施思路
四、具體步驟
首先是利用dlib進(jìn)行人臉識(shí)別:)
import cv2 import dlib from skimage import io # 使用特征提取器get_frontal_face_detector detector = dlib.get_frontal_face_detector() # dlib的68點(diǎn)模型,使用作者訓(xùn)練好的特征預(yù)測(cè)器 predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 圖片所在路徑 img = io.imread("2.jpg") # 生成dlib的圖像窗口 win = dlib.image_window() win.clear_overlay() win.set_image(img) # 特征提取器的實(shí)例化 dets = detector(img, 1) print("人臉數(shù):", len(dets)) for k, d in enumerate(dets): print("第", k+1, "個(gè)人臉d的坐標(biāo):", "left:", d.left(), "right:", d.right(), "top:", d.top(), "bottom:", d.bottom()) width = d.right() - d.left() heigth = d.bottom() - d.top() print('人臉面積為:',(width*heigth))
然后實(shí)例化一個(gè) shape_predictor 對(duì)象,使用dlib作者訓(xùn)練好人臉特征檢測(cè)器,進(jìn)行人臉的特征點(diǎn)標(biāo)定。
標(biāo)定的時(shí)候使用opencv的circle方法,在特征點(diǎn)的坐標(biāo)上面添加水印,內(nèi)容就是特征點(diǎn)的序號(hào)和位置。
# 利用預(yù)測(cè)器預(yù)測(cè) shape = predictor(img, d) # 標(biāo)出68個(gè)點(diǎn)的位置 for i in range(68): cv2.circle(img, (shape.part(i).x, shape.part(i).y), 4, (0, 255, 0), -1, 8) cv2.putText(img, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255)) # 顯示一下處理的圖片,然后銷毀窗口 cv2.imshow('face', img) cv2.waitKey(0)
到此,68個(gè)特征點(diǎn)的信息就獲取到了,下面就需要跟根據(jù)這個(gè)68個(gè)特征點(diǎn)的坐標(biāo)信息,進(jìn)行綜合 計(jì)算,作為每個(gè)表情的判斷指標(biāo)。
根據(jù)上面說(shuō)到的我的判斷指標(biāo),先計(jì)算嘴巴的張開(kāi)比例,由于人離攝像頭距離的遠(yuǎn)近,導(dǎo)致人臉識(shí)別框的大小不一,故選擇比例來(lái)作為判斷指標(biāo)。
在選擇指標(biāo)的標(biāo)準(zhǔn)數(shù)值之前,先對(duì)多個(gè)開(kāi)心的人臉照片進(jìn)行分析。計(jì)算開(kāi)心時(shí)的嘴巴張卡比例的平均。
下面是截取對(duì)人眉毛的數(shù)據(jù)處理方法,對(duì)左邊眉毛上面的5個(gè)特征點(diǎn)進(jìn)行線性擬合,擬合出一個(gè)一次函數(shù)直線,用擬合直線的斜率近似代表眉毛的傾斜程度。
# 眉毛 brow_sum = 0 # 高度之和 frown_sum = 0 # 兩邊眉毛距離之和 for j in range(17,21): brow_sum+= (shape.part(j).y - d.top()) + (shape.part(j+5).y- d.top()) frown_sum+= shape.part(j+5).x - shape.part(j).x line_brow_x.append(shape.part(j).x) line_brow_y.append(shape.part(j).y) self.excel_brow_hight.append(round((brow_sum/10)/self.face_width,3)) self.excel_brow_width.append(round((frown_sum/5)/self.face_width,3)) brow_hight[0]+= (brow_sum/10)/self.face_width # 眉毛高度占比 brow_width[0]+= (frown_sum/5)/self.face_width # 眉毛距離占比 tempx = np.array(line_brow_x) tempy = np.array(line_brow_y) z1 = np.polyfit(tempx, tempy, 1) # 擬合成一次直線 self.brow_k = -round(z1[0], 3) # 擬合出曲線的斜率和實(shí)際眉毛的傾斜方向是相反的
我計(jì)算了25個(gè)人臉的開(kāi)心表情的嘴巴張開(kāi)比例、嘴巴寬度、眼睛張開(kāi)程度、眉毛傾斜程度,導(dǎo)入excel表格生成折線圖:
通過(guò)折線圖能很明顯的看出什么參數(shù)可以使用,什么參數(shù)的可信度不高,什么參數(shù)在那個(gè)范圍內(nèi)可以作為一個(gè)指標(biāo)。
同樣的方法,計(jì)算人憤怒、驚訝、自然時(shí)的數(shù)據(jù)折線圖。
通過(guò)對(duì)多個(gè)不同表情數(shù)據(jù)的分析,得出每個(gè)指標(biāo)的參考值,可以寫出簡(jiǎn)單的表情分類標(biāo)準(zhǔn):
# 分情況討論 # 張嘴,可能是開(kāi)心或者驚訝 if round(mouth_higth >= 0.03): if eye_hight >= 0.056: cv2.putText(im_rd, "amazing", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4) else: cv2.putText(im_rd, "happy", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4) # 沒(méi)有張嘴,可能是正常和生氣 else: if self.brow_k <= -0.3: cv2.putText(im_rd, "angry", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4) else: cv2.putText(im_rd, "nature", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4)
五、實(shí)際運(yùn)行效果:
識(shí)別之后:
完整項(xiàng)目代碼:https://gitee.com/Andrew_Qian/face/blob/master/from_video.py
大家如果在測(cè)試制作的時(shí)候有任何疑問(wèn)可以在下方的留言區(qū)討論,感謝大家對(duì)腳本之家的支持。
- Python 40行代碼實(shí)現(xiàn)人臉識(shí)別功能
- python實(shí)現(xiàn)人臉識(shí)別代碼
- python+opencv實(shí)現(xiàn)的簡(jiǎn)單人臉識(shí)別代碼示例
- python使用opencv進(jìn)行人臉識(shí)別
- 詳解如何用OpenCV + Python 實(shí)現(xiàn)人臉識(shí)別
- Python3結(jié)合Dlib實(shí)現(xiàn)人臉識(shí)別和剪切
- 基于python3 OpenCV3實(shí)現(xiàn)靜態(tài)圖片人臉識(shí)別
- 20行python代碼實(shí)現(xiàn)人臉識(shí)別
- Python三十行代碼實(shí)現(xiàn)簡(jiǎn)單人臉識(shí)別的示例代碼
相關(guān)文章
python使用socket制作聊天室詳細(xì)源碼(可以直接運(yùn)行)
Python是一個(gè)非常靈活的編程語(yǔ)言,我們現(xiàn)在到處可見(jiàn)用Python編寫的應(yīng)用程序,下面這篇文章主要給大家介紹了關(guān)于python使用socket制作聊天室的相關(guān)資料,文中的代碼可以直接運(yùn)行,需要的朋友可以參考下2023-12-12Python字典操作詳細(xì)介紹及字典內(nèi)建方法分享
這篇文章主要介紹了Python字典操作詳細(xì)介紹及字典內(nèi)建方法分享,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Python使用difflib標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)查找文本間的差異
在文本處理和比較中,查找文本之間的差異是一項(xiàng)常見(jiàn)的任務(wù),本文將詳細(xì)介紹如何使用difflib模塊來(lái)查找文本之間的差異,包括單行和多行文本的比較、生成差異報(bào)告,需要的可以參考下2024-03-03Python-Selenium自動(dòng)化爬蟲(chóng)
本文介紹Python-Selenium自動(dòng)化爬蟲(chóng),Selenium是一個(gè)Web的自動(dòng)化測(cè)試工具,最初是為網(wǎng)站自動(dòng)化測(cè)試而開(kāi)發(fā)的,Selenium?可以直接運(yùn)行在瀏覽器上,它支持所有主流的瀏覽器,可以接收指令,讓瀏覽器自動(dòng)加載頁(yè)面,獲取需要的數(shù)據(jù),甚至頁(yè)面截屏,xiamian?neir?需要的朋友可以參考下2022-01-01Python常用標(biāo)準(zhǔn)庫(kù)詳解(pickle序列化和JSON序列化)
這篇文章主要介紹了Python常用標(biāo)準(zhǔn)庫(kù),主要包括pickle序列化和JSON序列化模塊,通過(guò)使用場(chǎng)景分析給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05分享Pytest fixture參數(shù)傳遞的幾種方式
這篇文章主要分享的是Pytest fixture參數(shù)傳遞的幾種方式,文章基于python的相關(guān)資料展開(kāi)對(duì)主題的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04Flask SocketIO實(shí)現(xiàn)動(dòng)態(tài)繪圖的示例詳解
Flask-SocketIO 是基于 Flask 的一個(gè)擴(kuò)展,用于簡(jiǎn)化在 Flask 應(yīng)用中集成 WebSocket 功能,本文主要介紹了Flask SocketIO如何實(shí)現(xiàn)動(dòng)態(tài)繪圖,需要的可以參考下2023-11-11使用Python實(shí)現(xiàn)數(shù)據(jù)庫(kù)文檔生成工具
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)數(shù)據(jù)庫(kù)文檔生成工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-04-04