目录
声明:本程序基于Python的OpenCV模块编程,利用opencv已有的人脸检测器和人脸识别器进行实时人脸识别
1. 调用库函数
import cv2
import numpy as np
- 1
- 2
2. 调用摄像头并设置窗口
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture(0)
cap.set(3, frameWidth) #设置参数,10为亮度
cap.set(4, frameHeight)
cap.set(10,150)
- 1
- 2
- 3
- 4
- 5
- 6
3. 设置图片正负样本数据集的路径
pos_path = './resource/face_detect/video2imagem3/'
neg_path = './resource/face_detect/video2imagec1/'
test_path = './resource/face/'
images = []
labels = []
- 1
- 2
- 3
- 4
- 5
4. 调用人脸检测器
注:人脸识别器在安装opencv库的时候就一块安装了,在opencv的安装路径下可以找到。
faceCascade = cv2.CascadeClassifier("resource/haarcascade_frontalface_default.xml")
- 1
5. 正负样本载入
由于本数据集人脸数据是通过程序处理视频获得的,因此,便于批量导入程序中。
正样本(人脸)与负样本(环境)比例大致为1:3,据说这样比例效果较好;标签为0,1。
导入语句如下:
for i in range(60): # 正样本
images.append(cv2.imread(pos_path+str(2*(i+1))+'.jpg',cv2.IMREAD_GRAYSCALE))
labels.append(0)
for i in range(173): # 负样本
images.append(cv2.imread(neg_path+str(2*(i+1))+'.jpg',cv2.IMREAD_GRAYSCALE))
labels.append(1)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
6.提取人脸区域
这里对于没检测到人脸区域的图片不进行处理,对于人脸区域,将其周围20像素左右部分提取出来
def processing(imageslist):
for j in range(len(imageslist)):
faces = faceCascade.detectMultiScale(imageslist[j], 1.1, 4)
for x,y,w,h in faces:
if x >= 20 and y >= 20: # 未处理没检测到人脸的情况
imageslist[j] = imageslist[j][y-20:y+h+20, x-20:x+w+20]
return imageslist
- 1
- 2
- 3
- 4
- 5
- 6
- 7
7. 建立LBPH人脸识别模型
这里采用LBPH人脸识别模块,因为这种方法不需要图片数据集为统一尺寸,EigenFaces和Fisherfaces模块均需要训练集图片和测试的图片尺寸保持一致。
imagesCopy = images
# 提取图像中人脸的区域
imagesCopy = processing(imagesCopy)
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(imagesCopy, np.array(labels))
- 1
- 2
- 3
- 4
- 5
8. 实时检测
人脸检测中,如果未检测到人脸,则face返回的是空元组,检测到人脸后,提取出人脸区域,采用recognizer.predict进行识别,对于返回值的confidence,小于50认为结果可靠,而大于80则认为差别较大。
while True:
success,img = cap.read()
predict_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceCascade.detectMultiScale(predict_image, 1.1, 4)
# print(face) # 空的元组有可能
if face != ():
for x, y, w, h in face:
if x >= 20 and y >= 20:
faceArea = predict_image[y-20:y+h+20, x-20:x+w+20]
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 1)
label, confidence = recognizer.predict(faceArea)
if confidence <= 80 and label == 0:
cv2.putText(img, "LQL",(x, y-20), cv2.FONT_HERSHEY_COMPLEX, 1,(255,0,0,1))
print("YOU ARE LQL")
else:
cv2.putText(img, "OTHERS", (x, y-20), cv2.FONT_HERSHEY_COMPLEX, 1,(255,0,0),1)
print("OTHERS")
print(confidence)
print(label)
else:
cv2.putText(img, "None", (320, 240), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 255), 1)
print("None")
cv2.imshow("img", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
9. 测试结果
能够基本实现特定人脸识别的功能。
10. 不足之处
- 未将训练部分与检测部分分开,导致每次都要重新训练,消耗一定的时间,目前只做了一种人脸识别;–已解决
- 由于数据是从视频中导出的图片,因此对于训练集中可能存在的未检测到人脸的情况也未作处理;
- 没有将所有的图片尺寸resize为统一尺寸,因此只能用LBPH模块进行人脸识别,不过,在另一方面,用cv2.resize可能会存在画面比例失衡的问题,损失训练效果;
- 另外,对于负样本,只用了背景图片,后续可以试试物体之类的。
总之,目前只是实现了一个简单的实时人脸识别功能,后续有时间再改进。
11. 改进方法
- 下列语句可以对训练好的模型进行保存和读取,因此可以将训练部分与识别部分分隔开
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.save('./resource/face_detect/MyFaceModel.xml')
recognizer.read('./resource/face_detect/MyFaceModel.xml')