目录
前言
学习了图像识别,都没有具体的做出一个项目。现在的人脸识别很火,于是就做了一个基于opencv的人脸识别
第一章 OpenCV介绍
OpenCV基本函数使用--Python_牧子川的博客-CSDN博客
第二章 功能描述
以下的功能都实现了,但是有些功能会在源码进行解释
2.1 对已有的数据进行检测
当训练器已经包含了本人的面部信息时,在进行识别时能准确的识别出来,并显示出来
2.2 陌生人检测并发出警告
当有陌生人靠近并停留了10s钟以上时,就会发出警报
2.3 保存陌生人的视频
当有陌生人靠经并停留10秒中以上时,将该陌生人的信息进行保存未视频
2.4 输入图片进行检测
可以对输入的人脸的图片进行检测
2.5 现场录用信息
可以以及录用人脸信息,并保存当前的人脸信息
第三章 功能实现
3.1 截取人脸图片
第一步 打开摄像头
import cv2
cap = cv2.VideoCapture(0)
while cap.isOpened():
_, frame = cap.read()
cv2.imshow("img", frame)
key = cv2.waitKey(1)
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
cap.release()与cv2.destroyAllWindows()只能放在while循环体外。
第二步 截取图片
使用的是人脸分类器
classfier = cv2.CascadeClassifier(r'G:\Opencv 4.5.3\opencv\build\etc\lbpcascades\lbpcascade_frontalface_improved.xml')
detectMultiScale函数。它可以检测出图片中所有的人脸,并将人脸用vector保存各个人脸的坐标、大小(用矩形表示),是一个一维数组[x, y, w, h]分别代表着上左,上右,下左,下右的坐标
faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=20, flags=4)
detectMultiScale函数参数介绍
1、grey:是输入图像
2、scaleFactor:这个是每次缩小图像的比例,默认是1.1 ,我这里选用1.2
3、minNeighbors=15:它表明如果有15个框都重叠一起了,那这里肯定是脸部,当minNeighbors越大时,能适当提高精度
4、minSize():匹配物体的最小范围 maxSize():匹配物体的最大范围
5、 flags = 0:可以取如下这些值:
CASCADE_DO_CANNY_PRUNING = 1, 利用canny边缘检测来排除一些边缘很少或者很多的图像区域
CASCADE_SCALE_IMAGE = 2, 正常比例检测
CASCADE_FIND_BIGGEST_OBJECT = 4, 只检测最大的物体
第三步 保存图片
cv2.imwrite(img_name, image)
cv2.rectangle(frame, (x - 20, y - 20), (x + w + 20, y + h + 20), rect_color, 2)
# 显示当前捕捉到了多少人脸图片了
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, 'num:%d' % num, (x + 30, y + 30), font, 1, (255, 0, 255), 4)
num += 1
if num > 200: # 如果超过指定最大保存数量退出循环
break
保存图像
cv2.imwrite(file,img,num)保存一个图像
file:保存的文件名
img:要保存的图像。
num:可选,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别。默认为3.
3.2 对图片进行处理
对图片进行训练时,实际上训练的时图片的像素点,所以我们要得到图片的像素
第一步 得到像素点
# 使用LBP分类器,还有一种更精确但速度较慢的Haar分类器
face_cascade = cv2.CascadeClassifier(r'G:\Opencv 4.5.3\opencv\build\etc\lbpcascades\lbpcascade_frontalface.xml') # todo
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)
(x, y, w, h) = faces[0]
return gray[y:y + w, x:x + h], faces[0]
第二步 得到图片相对应的标签和像素
label = int(dir_name.replace("s", ""))
face, rect = detect_face(image)
# 忽略为检测到的人脸
if face is not None:
faces.append(face)
labels.append(label)
return faces, labels
3.3 进行训练
opencv中的face有专门的训练方式,对每个参考图像计算LBPH,得到一个向量。每个人脸都是整个向量集中的一个点。
cv2.face_FaceRecognizer.train(src,labels)
● src:训练图像,用来学习的人脸图像。
● labels:标签,人脸图像所对应的标签。
def train(face_recognizer):
"""训练数据"""
print("数据准备")
faces, labels = prepare_training_data(r"./train_data")
print("准备完成")
print("Total faces: ", len(faces))
print("Total labels: ", len(labels))
print("开始训练")
# 训练人脸识别器
face_recognizer.train(faces, np.array(labels))
# 保存训练好的模型
face_recognizer.save(r"./models/train1.yml")
print("训练完成")
3.4 进行预测
cv2.face_FaceRecognizer.predict()
使用我们的人脸识别器预测图像 predict()入口参数必须为单通道灰度图像
对当前人脸图像进行判断,从人脸库中寻找与当前图像距离最近的人脸图像,与某个人脸图像最近,就将当前图像标注为其对应的标签。如果待测图像与所有人脸图像的距离都大于函数cv2.face.LBPHFaceRecognizer_create()中参数threshold所指定的距离值,则认为没有找到对应的结果,即无法识别当前人脸。返回的是一个元组,第一个是识别某一类,第二类是一个置信度,即有多少可能
# 加载训练好的模型
face_recognizer.read(r'./models/train1.yml')
addr = input("请输入图片地址:")
test_img = cv2.imread(addr)
# 复制图像,因为我们不想更改原始图像
test_img = test_img.copy()
face, rect = detect_face(test_img)
label = face_recognizer.predict(face)
label_text = subjects[label[0]]
draw_rectangle(test_img, rect)
draw_text(test_img, label_text, rect[0], rect[1] - 5)
cv2.imshow("predict", test_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.5 实时预测
就是在框出人脸图像的同时对这个图片进行预测,即把截取图片和预测同时进行
face_recognizer.read(r'./models/train.yml')
cap = cv2.VideoCapture(0)
# 循环检测识别人脸
while True:
_, frame = cap.read()
face, rect = detect_face(frame)
try:
label = face_recognizer.predict(face)
except Exception as e:
print("错误信息为:", e)
traceback.print_exc()
print('traceback.format_exc():\n%s'%traceback.format_exc())
cv2.imshow('camera', frame)
else:
print(label)
if label[1] > 80:
draw_rectangle(frame, rect)
draw_text(frame, subjects[0], rect[0], rect[1] - 5)
else:
label_text = subjects[label[0]]
draw_rectangle(frame, rect)
draw_text(frame, label_text, rect[0], rect[1] - 5)
cv2.imshow('camera', frame)
# 等待10毫秒看是否有按键输入
k = cv2.waitKey(10)
# 如果输入q则退出循环
if k & 0xFF == ord('q'):
break
# 释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
第四章 出现的问题
难点一:无法打开本机自带摄像头
解决方法:cap = cv2.VideoCapture(0)调用本机摄像头
难点二:在进行人脸识别时,只要人稍微一动,就会识别失败
解决方法:在读入图片时,可以先延时一小段时间在进行读入图片,这样在识别到第一帧图片时会等一会在去识别另一帧图片,只要时间间隔短,则不会出现这种情况
难点三:训练好模型后进行检测总是会出错,不能正确检测出本人
解决方法:这个原因为数据集不够,人脸的特征没有完全被学到;环境因素的影响会导致模型识别错误,可以通过增加人脸数据集的方式再次进行训练,增加噪声