OpenCV 人脸侦测
这篇教学会介绍使用 OpenCV,搭配官方提供的人脸特征模型,侦测图像中的人脸,并透过绘制形状的方式,使用方框标记侦测到的人脸,实现类似 AI 图像辨识的效果。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
下载人脸特征模型
OpenCV 的官方 Github 提供了许多训练好的特征模型,只需要下载后就能使用,请从下方网址进行下载,下载后将 xml 文件和 Python 的程序档放在同一层目录下。
- OpenCV 官方 Github:https://github.com/opencv/opencv/tree/4.x/data
- 人脸特征模型:haarcascade_frontalface_default.xml
侦测图像中的人脸
OpenCV 里的 CascadeClassifier() 方法 ( 级联分类器 ),可以根据所提供的模型文件,判断某个事件是否属于某种结果,例如侦测人脸,如果图像中符合模型所定义的人脸属性,就会出现这个人脸对应的属性 ( 座标、尺寸...等 )。
使用 CascadeClassifier() 后,会再透过 detectMultiScale() 进行侦测,如果侦测到脸,就会将侦测到的属性输出 ( 串列与字典形式 ),相关用法如下:
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# 設定集聯分類器為人臉的模型 ( haarcascade_frontalface_default.xml )
faces = face_cascade.detectMultiScale(img, scaleFactor, minNeighbors, flags, minSize, maxSize)
# 偵測並取出相關屬性
# img 來源影像,建議使用灰階影像
# scaleFactor 前後兩次掃瞄偵測畫面的比例係數,預設 1.1
# minNeighbors 構成檢測目標的相鄰矩形的最小個數,預設 3
# flags 通常不用設定,若設定 CV_HAAR_DO_CANNY_PRUNING 會使用 Canny 邊緣偵測,排除邊緣過多或過少的區域
# minSize, maxSize 限制目標區域的範圍,通常不用設定
下方的例子执行后,会侦测蒙娜丽莎的人脸,并透过绘制形状的方式,使用方框标记侦测到的人脸,如果有发生侦测到不是人脸的形状 ( 例如钮扣和阴影组合成很像人脸的 ),可以调整 scaleFactor 和 minNeighbors 参数再重新侦测。
import cv2
img = cv2.imread('mona.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 將圖片轉成灰階
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") # 載入人臉模型
faces = face_cascade.detectMultiScale(gray) # 偵測人臉
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 利用 for 迴圈,抓取每個人臉屬性,繪製方框
cv2.imshow('oxxostudio', img)
cv2.waitKey(0) # 按下任意鍵停止
cv2.destroyAllWindows()
如果有多张人脸,也可以顺利侦测并标记 ( 图片为 Fusilamientos de Torrijos y sus compañeros en las playas de Málaga )。
即时侦测影片中的人脸
延伸“读取并播放影片”文章的范例,搭配人脸侦测的方法,就可以即时侦测摄影镜头里的人脸。
import cv2
cap = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
faces = face_cascade.detectMultiScale(gray)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("Cannot receive frame")
break
frame = cv2.resize(frame,(540,320)) # 縮小尺寸,避免尺寸過大導致效能不好
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 將鏡頭影像轉換成灰階
faces = face_cascade.detectMultiScale(gray) # 偵測人臉
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # 標記人臉
cv2.imshow('oxxostudio', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注