python3+dlib人臉識別及情緒分析

1、介紹

我想作的是基於人臉識別的表情(情緒)分析。看到網上也是有不少的開源庫提供使用,爲開發提供了很大的方便。我選擇目前用的比較多的dlib庫進行人臉識別與特徵標定。使用python也縮短了開發週期。html

官網對於dlib的介紹是:Dlib包含普遍的機器學習算法。全部的設計都是高度模塊化的,快速執行,而且經過一個乾淨而現代的C ++ API,使用起來很是簡單。它用於各類應用,包括機器人技術,嵌入式設備,手機和大型高性能計算環境。python

雖然應用都比較高大上,可是本身在PC上作個情緒分析的小軟件仍是挺有意思的。git

按照本身的想法與思路設計識別方式。目前也比較火的keras好像就是根據嘴型的變化做爲情緒分析的一個指標。算法

而個人想法是利用嘴的張開比例,眼睛的睜開程度,眉毛的傾斜角度做爲情緒分析的三個指標。可是因爲人與人長相的差別較大,五官的也是千差萬別,再加上個人計算方法也比較簡單。因此識別效率並非很高。api

識別規則:app

一、嘴巴張開距離佔面部識別框寬度的比例越大,說明情緒越激動,多是很是開心,也多是極度憤怒。機器學習

二、眉毛上揚,17-21 或者 22-26 號特徵點距離面部識別框頂部與識別框高度的比值越小,說明眉毛上揚越厲害,可表示驚訝、開心。眉毛的傾斜角度,開心時眉毛通常是上揚,憤怒時皺眉,同時眉毛下壓的比較厲害。ide

三、眯眼睛,人在開懷大笑的時候會不自覺的眯起眼睛,憤怒或者驚訝的時候會瞪大眼睛。模塊化

系統缺點:不能捕捉細微表情的變化,只能大體的判斷出人的情緒,開心、憤怒、驚訝、天然。函數

系統優勢:結構簡單,易於上手。

應用領域:微笑抓拍,捕捉瞬間的美好、緩解兒童自閉症、交互式遊戲開發。

因爲人感情的複雜性,這些表情確實不能完徹底全的表明一我的心裏深處的情緒波動,如要提升判斷的準確性,則須要心率檢測、語音處理等綜合評價。

2、開發環境搭建:

一、安裝VS2015,由於最新版的dlib-19.10須要這個版本的vscode

二、安裝opencv(whl方式安裝):
從pythonlibs下載須要的版本whl文件,好比(opencv_python?3.3.0+contrib?cp36?cp36m?win_amd64.whl)
而後在本地使用pip install 安裝。 注意文件位置下安裝(如:C:\download\xxx.whl)

三、安裝dlib(whl方式安裝):
在這裏下載dlib的各類版本的whl文件,而後在根目錄下打開cmd直接安裝便可。
可是爲了學習使用dlib中的各類python實例程序,仍是須要下載一個dlib的壓縮包。
直接訪問dlib官網便可下載:http://dlib.net/ml.html

dlib各類版本的whl文件:https://pypi.python.org/simple/dlib/

四、若是想要使用人臉模型特徵標定的話,還須要一我的臉面部形狀預測器,這個能夠經過本身的照片進行訓練,也可使用dlib做者給出的一個訓練好的預測器:         

點擊下載:http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2

3、實施思路

4、具體步驟

首先是利用dlib進行人臉識別:)

import cv2
import dlib
from skimage import io

# 使用特徵提取器get_frontal_face_detector
detector = dlib.get_frontal_face_detector()
# dlib的68點模型,使用做者訓練好的特徵預測器
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)

# 特徵提取器的實例化
dets = detector(img, 1)
print("人臉數:", len(dets))

for k, d in enumerate(dets):
        print("", k+1, "我的臉d的座標:",
              "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))

而後實例化一個 shape_predictor 對象,使用dlib做者訓練好人臉特徵檢測器,進行人臉的特徵點標定。

標定的時候使用opencv的circle方法,在特徵點的座標上面添加水印,內容就是特徵點的序號和位置。

        # 利用預測器預測
        shape = predictor(img, d)
        # 標出68個點的位置
        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個特徵點的信息就獲取到了,下面就須要跟根據這個68個特徵點的座標信息,進行綜合 計算,做爲每一個表情的判斷指標。

根據上面說到的個人判斷指標,先計算嘴巴的張開比例,因爲人離攝像頭距離的遠近,致使人臉識別框的大小不一,故選擇比例來做爲判斷指標。

在選擇指標的標準數值以前,先對多個開心的人臉照片進行分析。計算開心時的嘴巴張卡比例的平均。

下面是截取對人眉毛的數據處理方法,對左邊眉毛上面的5個特徵點進行線性擬合,擬合出一個一次函數直線,用擬合直線的斜率近似表明眉毛的傾斜程度。

                    # 眉毛
                    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)    # 擬合出曲線的斜率和實際眉毛的傾斜方向是相反的

我計算了25我的臉的開心表情的嘴巴張開比例、嘴巴寬度、眼睛張開程度、眉毛傾斜程度,導入excel表格生成折線圖:

經過折線圖能很明顯的看出什麼參數可使用,什麼參數的可信度不高,什麼參數在那個範圍內能夠做爲一個指標。

一樣的方法,計算人憤怒、驚訝、天然時的數據折線圖。

經過對多個不一樣表情數據的分析,得出每一個指標的參考值,能夠寫出簡單的表情分類標準:

                      # 分狀況討論
                        # 張嘴,多是開心或者驚訝
                        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)

                        # 沒有張嘴,多是正常和生氣
                        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)

5、實際運行效果:

識別以後:

 

完整項目代碼:https://gitee.com/Andrew_Qian/face/blob/master/from_video.py

參考資料:

8種方法用Python實現線性迴歸,爲你解析最高效選擇

利用python開發,藉助Dlib庫捕獲攝像頭中的人臉,進行實時人臉68個特徵點標定;

49 款人臉檢測/識別的API、庫和軟件

相關文章
相關標籤/搜索