Mediapipe 人臉偵測 Face Detection ( 舊版 )
這篇教學會使用 MediaPipe 的人臉偵測模型 ( Face Detection ) 偵測人臉,再透過 OpenCV 讀取攝影鏡頭影像進行偵測,最後也會介紹如何取得五官座標資訊,使用繪製形狀的方式,即時在攝影畫面加上卡通的眼睛。
MidoaPipe 在 2023 年進行了比較大的改版和更新,雖然舊版的程式「可能」還可以運行,但建議使用新版,參考:Mediapipe 人臉偵測 Face Detection ( 2023 年版 )
快速導覽:
因為程式使用 Jupyter 搭配 Tensorflow 進行開發,所以請先閱讀「使用 Anaconda」和「使用 MediaPipe」,安裝對應的套件,如果不要使用 Juputer,也可參考「使用 Python 虛擬環境」,建立虛擬環境進行實作。
使用 MediaPipe,偵測人臉
下方的程式碼延伸「讀取並播放影片」文章的範例,搭配 mediapipe 偵測人臉的方法,透過攝影鏡頭獲取影像後,使用白色外框正方形標記人臉,使用紅色小圓點標記五官位置。
import cv2
import mediapipe as mp # 載入 mediapipe 函式庫
cap = cv2.VideoCapture(0)
mp_face_detection = mp.solutions.face_detection # 建立偵測方法
mp_drawing = mp.solutions.drawing_utils # 建立繪圖方法
with mp_face_detection.FaceDetection( # 開始偵測人臉
model_selection=0, min_detection_confidence=0.5) as face_detection:
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 將 BGR 顏色轉換成 RGB
results = face_detection.process(img2) # 偵測人臉
if results.detections:
for detection in results.detections:
mp_drawing.draw_detection(img, detection) # 標記人臉
cv2.imshow('oxxostudio', img)
if cv2.waitKey(5) == ord('q'):
break # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()
取得五官座標,繪製形狀
延伸上方的程式碼,在 detection 的 for 迴圈裡,可以取得每個紅色小點的座標,由於座標的意義為該位置在水平或垂直方向的「比例」,所以要額外乘以長寬尺寸才會是正確的座標值,取得座標值後,就能利用 OpenCV 繪製形狀的方式繪製形狀,下面的程式碼,會將人臉的兩個眼睛,加上卡通的眼睛效果。
import cv2
import mediapipe as mp
cap = cv2.VideoCapture(0)
mp_face_detection = mp.solutions.face_detection
mp_drawing = mp.solutions.drawing_utils
with mp_face_detection.FaceDetection(
model_selection=0, min_detection_confidence=0.5) as face_detection:
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
size = img.shape # 取得攝影機影像尺寸
w = size[1] # 取得畫面寬度
h = size[0] # 取得畫面高度
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = face_detection.process(img2)
if results.detections:
for detection in results.detections:
mp_drawing.draw_detection(img, detection)
s = detection.location_data.relative_bounding_box # 取得人臉尺寸
eye = int(s.width*w*0.1) # 計算眼睛大小 ( 人臉尺寸*0.1 )
a = detection.location_data.relative_keypoints[0] # 取得左眼座標
b = detection.location_data.relative_keypoints[1] # 取得右眼座標
ax, ay = int(a.x*w), int(a.y*h) # 計算左眼真正的座標
bx, by = int(b.x*w), int(b.y*h) # 計算右眼真正的座標
cv2.circle(img,(ax,ay),(eye+10),(255,255,255),-1) # 畫左眼白色大圓 ( 白眼球 )
cv2.circle(img,(bx,by),(eye+10),(255,255,255),-1) # 畫右眼白色大圓 ( 白眼球 )
cv2.circle(img,(ax,ay),eye,(0,0,0),-1) # 畫左眼黑色大圓 ( 黑眼球 )
cv2.circle(img,(bx,by),eye,(0,0,0),-1) # 畫右眼黑色大圓 ( 黑眼球 )
cv2.circle(img,(ax-8,ay-8),(eye-15),(255,255,255),-1) # 畫左眼白色小圓 ( 反光 )
cv2.circle(img,(bx-8,by-8),(eye-15),(255,255,255),-1) # 畫右眼白色小圓 ( 反光 )
cv2.imshow('oxxostudio', img)
if cv2.waitKey(5) == ord('q'):
break # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()
參考資料
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~