基于人臉關鍵點的多表情實時檢測系統
在計算機視覺領域,人臉表情識別技術已經取得了顯著的進展。它不僅可以用于娛樂應用(如動態表情包生成),還能在心理健康監測、智能安防、人機交互等領域發揮重要作用。今天,我將分享一個基于人臉關鍵點的多表情實時檢測系統,該系統能夠通過攝像頭實時識別微笑、大笑、哭泣和憤怒等多種表情。
1. 項目背景與動機
人臉表情是人類情感的重要外在表現形式。通過分析人臉的表情,我們可以更好地理解他人的情緒狀態。傳統的表情識別方法主要依賴于深度學習模型,這些模型雖然精度高,但計算復雜度較高,難以在資源受限的設備上實現實時檢測。相比之下,基于人臉關鍵點的方法更加輕量級,通過分析關鍵點的位置關系來推斷表情狀態,適合在實時系統中應用。
本項目的目標是開發一個實時系統,能夠通過攝像頭捕捉人臉圖像,并根據人臉關鍵點的位置關系判斷當前的表情狀態。我們將重點實現微笑、大笑、哭泣和憤怒這四種常見表情的檢測。
2. 技術棧與工具
為了實現這個項目,我們使用了以下技術和工具:
- Python:作為主要的開發語言,Python 提供了豐富的庫支持,便于快速開發和調試。
- OpenCV:用于圖像處理和視頻流操作,能夠高效地讀取攝像頭數據并進行圖像繪制。
- dlib:提供了強大的人臉檢測和關鍵點定位功能,是實現人臉關鍵點提取的核心工具。
- scikit-learn:用于計算歐幾里得距離,幫助我們分析關鍵點之間的空間關系。
- Pillow:用于在圖像上繪制中文文本,方便在實時視頻中顯示識別結果。
3. 關鍵技術實現
3.1 人臉檢測與關鍵點提取
人臉檢測是表情識別的第一步。我們使用 dlib 提供的 get_frontal_face_detector
方法來檢測圖像中的人臉區域。一旦檢測到人臉,我們再利用 shape_predictor
模型提取人臉的 68 個關鍵點。這些關鍵點包括眼睛、眉毛、鼻子、嘴巴等部位的特征點,為后續的表情分析提供了基礎數據。
detector = dlib.get_frontal_face_detector() # 構造臉部位置檢測器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 讀取人臉關鍵點定位模型
faces = detector(frame, 0) # 獲取人臉
for face in faces: # 循環遍歷每一個人臉shape = predictor(frame, face) # 獲取關鍵點shape = np.array([[p.x, p.y] for p in shape.parts()]) # 將關鍵點轉換為坐標(x,y)的形式
3.2 表情特征計算
為了判斷不同表情,我們定義了多個特征指標,包括嘴寬比(MWR)、嘴高比(MHR)和眼睛寬高比(EAR)等。
- 嘴高比(MHR):計算嘴巴的平均高度與嘴巴寬度的比值。嘴巴的高度通過關鍵點 50、51、52 與 58、57、56 的距離計算,嘴巴寬度通過關鍵點 48 和 54 的距離計算。當 MHR 超過一定閾值時,可能表示大笑。
- 嘴寬比(MWR):計算嘴巴寬度與下頜寬度的比值。嘴巴寬度通過關鍵點 48 和 54 的距離計算,下頜寬度通過關鍵點 3 和 13 的距離計算。當 MWR 超過一定閾值時,可能表示微笑。
- 眼睛寬高比(EAR):計算眼睛的寬高比,用于檢測眼睛閉合程度。當 EAR 小于一定閾值時,可能表示眼睛閉合,進而推斷出哭泣等表情。
def MAR(shape):A = euclidean_distances(shape[50].reshape(1, 2), shape[58].reshape(1, 2))B = euclidean_distances(shape[51].reshape(1, 2), shape[57].reshape(1, 2))C = euclidean_distances(shape[52].reshape(1, 2), shape[56].reshape(1, 2))D = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2))return ((A + B + C) / 3) / Ddef MJR(shape):M = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2)) # 嘴寬度J = euclidean_distances(shape[3].reshape(1, 2), shape[13].reshape(1, 2)) # 下頜寬度return M / Jdef EAR(shape):A = euclidean_distances(shape[37].reshape(1, 2), shape[41].reshape(1, 2))B = euclidean_distances(shape[38].reshape(1, 2), shape[40].reshape(1, 2))C = euclidean_distances(shape[36].reshape(1, 2), shape[39].reshape(1, 2))return (A + B) / (2.0 * C)
3.3 實時視頻流處理
我們通過 OpenCV 的 VideoCapture
方法獲取攝像頭的實時視頻流,并在每一幀圖像上進行人臉檢測和表情識別。識別結果會以中文文本的形式顯示在視頻窗口中,同時繪制嘴巴的凸包輪廓,以便直觀地觀察嘴巴的形狀變化。
cap = cv2.VideoCapture(0)
while True:ret, frame = cap.read()if not ret:breakgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = detector(gray, 0)for face in faces:shape = predictor(gray, face)shape = np.array([[p.x, p.y] for p in shape.parts()])mar = MAR(shape)mjr = MJR(shape)ear = EAR(shape)result = "正常"if mar > 0.5:result = "大笑"elif mjr > 0.45:result = "微笑"elif ear < 0.2: # 眼睛閉合,可能是在哭result = "哭"elif euclidean_distances(shape[19].reshape(1, 2), shape[24].reshape(1, 2)) < 20: # 眉毛距離變小,可能是在憤怒result = "憤怒"print("MAR:", mar, "\tMJR:", mjr, "\tEAR:", ear, "\t表情:", result)mouthHull = cv2.convexHull(shape[48:61])frame = cv2AddChineseText(frame, result, (mouthHull[0, 0][0], mouthHull[0, 0][1] - 20))cv2.drawContours(frame, [mouthHull], -1, (0, 255, 0), 1)cv2.imshow("Frame", frame)if cv2.waitKey(1) == 27: # 按ESC退出breakcv2.destroyAllWindows()
cap.release()
5. 總結
通過本項目,我們成功實現了一個基于人臉關鍵點的多表情實時檢測系統。這個項目不僅展示了人臉關鍵點在表情識別中的應用,還為后續的擴展和優化提供了基礎。希望這個項目能夠為對人臉表情識別感興趣的朋友提供一些參考和啟發。