OpenCV 辨识不同人脸
这篇教学会介绍使用 OpenCV 内建的 LBPH 人脸训练功能 ( cv2.face.LBPHFaceRecognizer_create()),搭配人脸特征模型,训练判断不同人脸的模型文件,完成后就能透过摄影机的图像,辨识出不同的人脸,标记出对应的名字。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
安装 opencv_contrib_python
要使用 cv2.face.LBPHFaceRecognizer_create(),必须先安装 opencv_contrib_python,输入下列指令进行安装,opencv_contrib_python 提供 opencv 更多的操作方法。
如果使用 Anaconda Jupyter 搭配命令提示字元或终端机安装,虽然可以顺利安装,但程序执行后可能会出现“module 'cv2' has no attribute 'face'”提示,有两种解决方法:
- 第一、改成在 Jupyter 里使用 !pip 直接安装。
- 第二,移除 opencv-python 和 opencv_contrib_python,再次重新安装。
pip install opencv_contrib_python
使用人脸图片,训练模型
如果要辨识不同的人脸,必须先“训练”不同人脸的模型,透过 cv2.face.LBPHFaceRecognizer_create() 方法,将收集好的人脸图片 ( 同样的人,不同角度的照片 20~30 张 ),以每个 id 为一个人的单位进行图像训练,保留相关特征值,届时只要比对特征值,就能得到人脸辨识的信心指数。
首先准备一些蔡英文的照片和川普的照片 ( 都是使用 Goolge 图片搜索取得 )
接着撰写下方的程序,除了训练蔡英文和川普的照片,也搭配一组使用摄影镜头记录自己的人脸图像,经过训练后产生 yml 模型文件储存。
import cv2
import numpy as np
detector = cv2.CascadeClassifier('xml/haarcascade_frontalface_default.xml') # 載入人臉追蹤模型
recog = cv2.face.LBPHFaceRecognizer_create() # 啟用訓練人臉模型方法
faces = [] # 儲存人臉位置大小的串列
ids = [] # 記錄該人臉 id 的串列
for i in range(1,31):
img = cv2.imread(f'face01/{i}.jpg') # 依序開啟每一張蔡英文的照片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 色彩轉換成黑白
img_np = np.array(gray,'uint8') # 轉換成指定編碼的 numpy 陣列
face = detector.detectMultiScale(gray) # 擷取人臉區域
for(x,y,w,h) in face:
faces.append(img_np[y:y+h,x:x+w]) # 記錄蔡英文人臉的位置和大小內像素的數值
ids.append(1) # 記錄蔡英文人臉對應的 id,只能是整數,都是 1 表示蔡英文的 id 為 1
for i in range(1,16):
img = cv2.imread(f'face02/{i}.jpg') # 依序開啟每一張川普的照片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 色彩轉換成黑白
img_np = np.array(gray,'uint8') # 轉換成指定編碼的 numpy 陣列
face = detector.detectMultiScale(gray) # 擷取人臉區域
for(x,y,w,h) in face:
faces.append(img_np[y:y+h,x:x+w]) # 記錄川普人臉的位置和大小內像素的數值
ids.append(2) # 記錄川普人臉對應的 id,只能是整數,都是 2 表示川普的 id 為 2
print('training...') # 提示開始訓練
recog.train(faces,np.array(ids)) # 開始訓練
recog.save('face.yml') # 訓練完成儲存為 face.yml
print('ok!')
根据模型,辨识不同人脸
已经训练好 yml 模型档后,就可以开始进行辨识,当辨识到人脸,会回传 id 与该 id 的信心指数 confidence,信心指数数值越小表示越准确,借由 id 与信心指数就能判断出现在画面中的人脸,并进一步标记对应的名字,下方的程序码会标记出蔡英文、川普以及 oxxostudio 三个人脸,如果辨识的人脸不属于这三个人,则会标记 ??? 的文字。
import cv2
recognizer = cv2.face.LBPHFaceRecognizer_create() # 啟用訓練人臉模型方法
recognizer.read('face.yml') # 讀取人臉模型檔
cascade_path = "xml/haarcascade_frontalface_default.xml" # 載入人臉追蹤模型
face_cascade = cv2.CascadeClassifier(cascade_path) # 啟用人臉追蹤
cap = cv2.VideoCapture(0) # 開啟攝影機
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img = cv2.resize(img,(540,300)) # 縮小尺寸,加快辨識效率
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 轉換成黑白
faces = face_cascade.detectMultiScale(gray) # 追蹤人臉 ( 目的在於標記出外框 )
# 建立姓名和 id 的對照表
name = {
'1':'Tsai',
'2':'Trump',
'3':'oxxostudio'
}
# 依序判斷每張臉屬於哪個 id
for(x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) # 標記人臉外框
idnum,confidence = recognizer.predict(gray[y:y+h,x:x+w]) # 取出 id 號碼以及信心指數 confidence
if confidence < 60:
text = name[str(idnum)] # 如果信心指數小於 60,取得對應的名字
else:
text = '???' # 不然名字就是 ???
# 在人臉外框旁加上名字
cv2.putText(img, text, (x,y-5),cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2, cv2.LINE_AA)
cv2.imshow('oxxostudio', img)
if cv2.waitKey(5) == ord('q'):
break # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注