- 要實現眨眼偵測,我們會使用一種基於臉部特徵點識別的技術,特別是對眼睛周圍區域的特徵點進行分析。這種技術在許多場合下非常有用,如駕駛疲勞監測、人機互動、虛擬實境等。眨眼偵測主要是通過計算眼睛的開合程度,依據眼睛周圍特徵點的相對位置來進行。這裡介紹的是一個被廣泛應用的算法——眼睛長寬比(Eye Aspect Ratio, EAR),它首次於2016年由Tereza Soukupová和Jan Čech在他們的論文《Real-Time Eye Blink Detection using Facial Landmarks》中提出。由於演算法的本身會從眼睛的特徵開始分析起因此我們需要有一個模型能夠針對眼睛給出各個特徵座標點,像下圖這樣所示:
內容目錄
一.安裝dlib 環境
- 要實現眨眼偵測,我們首先需要獲取眼睛周圍的特徵點座標。這裡,我們選擇使用 dlib 這個函式庫來達成這一目的。dlib 是一個集成了許多機器學習算法的 C++ 函式庫,非常適合於臉部偵測、臉部識別及臉部特徵點偵測等任務。下面是利用 dlib 實現眨眼偵測的具體步驟:
a.安裝 dlib:首先,確保你已經安裝了 dlib。如果你是 Python 使用者,可以通過 pip 來安裝 dlib:
pip install dlib
- 這裡我試了很久都是錯誤,找網路資料後才知道dlib官網釋放的大多是python3.6編譯完成, 如果要用在python3.9 必須重新從來源再build 一次,剛好找到網路上有人分享python3.9 版本的dlib wheel, 直接pip install 安裝就成功,這個博主甚至把python 3.7、3.8、3.9、3.10 都編譯好了,省了我好多的工作
b.加載人臉檢測器:使用 dlib 提供的人臉檢測器來識別圖片中的人臉。
import dlib
# 加載前置人臉檢測器
detector = dlib.get_frontal_face_detector()
c.加載特徵點預測器:為了獲取臉部特徵點,需要加載一個預訓練的特徵點預測模型,模型可以在官網下載。dlib 有一個基於 68 個特徵點的預訓練模型。
# 加載特徵點預測器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
d.識別特徵點:使用人臉檢測器找到圖片中的人臉,然後用特徵點預測器來識別臉部的特徵點。
import cv2
# 讀取圖片
image = cv2.imread("your_image.jpg")
# 檢測人臉
faces = detector(image, 1)
for face in faces:
# 獲取臉部特徵點
landmarks = predictor(image, face)
# 這裡可以根據 landmarks 來獲取眼睛周圍的特徵點座標
二.算法介紹
- 眼睛長寬比(EAR)的計算方法
- EAR是基於眼睛的幾何特性,透過特定的幾點計算得到一個數值,以此來判斷眼睛是否閉合。EAR計算公式如下:
- $EAR=\frac{{∣∣p2−p6∣∣+∣∣p3−p5∣∣}}{2×∣∣p1−p4∣∣}$
- 這裡,$p1$到$p6$代表眼睛周圍的六個特徵點。$p2$到$p6$是眼瞼的點,而$p1$和$p4$是眼角的點。公式中的||p2 – p6||和||p3 – p5||計算的是眼瞼之間的距離,而2 × ||p1 – p4||則是計算眼睛開口的寬度的兩倍。
三.計算EAR sample
- 睜眼:Left EAR: 0.37, Right EAR: 0.36, Average EAR: 0.36
- 閉眼:Left EAR: 0.15, Right EAR: 0.15, Average EAR: 0.15
四.完整範例程式碼
import cv2
import dlib
import numpy as np
def eye_aspect_ratio(eye_points):
# 根據眼睛的6個特徵點計算EAR
A = np.linalg.norm(eye_points[1] - eye_points[5])
B = np.linalg.norm(eye_points[2] - eye_points[4])
C = np.linalg.norm(eye_points[0] - eye_points[3])
ear = (A + B) / (2.0 * C)
return ear
# 加載人臉檢測和特徵點檢測器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
# 讀取圖像
image_path = "your_image_path.jpg" # 替換成您的圖片路徑
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 檢測圖像中的人臉
faces = detector(gray)
for face in faces:
# 獲取臉部特徵點
landmarks = predictor(gray, face)
# 獲取左眼和右眼的特徵點
left_eye_points = np.array([(landmarks.part(n).x, landmarks.part(n).y) for n in range(36, 42)])
right_eye_points = np.array([(landmarks.part(n).x, landmarks.part(n).y) for n in range(42, 48)])
# 計算EAR
left_ear = eye_aspect_ratio(left_eye_points)
right_ear = eye_aspect_ratio(right_eye_points)
ear = (left_ear + right_ear) / 2.0
# 在圖像上標記左眼和右眼的特徵點
for point in left_eye_points:
cv2.circle(img, tuple(point), 1, (0, 255, 0), -1)
for point in right_eye_points:
cv2.circle(img, tuple(point), 1, (0, 255, 0), -1)
print(f"Left EAR: {left_ear:.2f}, Right EAR: {right_ear:.2f}, Average EAR: {ear:.2f}")
# 顯示結果圖像
cv2.imshow("Eye Aspect Ratio and Landmarks", img)
cv2.waitKey(0)
cv2.destroyAllWindows()