今天完成了口罩识别,这个板子太强大了吧。哪怕你戴口罩也是可以识别出来的,上代码:
1、识别代码
import numpy as np
import cv2 as cv
import os
face_detection_model = "../models/yunet.onnx"
face_recognition_model = "../models/face_recognizer_fast.onnx"
images_path = "../images"
faceDetector = cv.FaceDetectorYN.create(face_detection_model, "", input_size=(640, 480)) # 初始化FaceRecognizerYN
recognizer = cv.FaceRecognizerSF.create(face_recognition_model, "") # 初始化FaceRecognizerSF
cosine_similarity_threshold = 0.363
l2_similarity_threshold = 1.128
# 获取图片中的人脸特征,将获取到的人脸特征和ID分别添加到不同的列表中
def Gets_Facial_Features(images_path):
images_feature_list = []
ID_list = []
for image_name in os.listdir(images_path):
ID_list.append(image_name.split('.')[0])
image = cv.imread(images_path + '/' + image_name)
faces1 = faceDetector.detect(image)
# 在人脸检测部分的基础上, 对齐检测到的首个人脸(faces[1][0]), 保存至aligned_face。
aligned_face1 = recognizer.alignCrop(image, faces1[1][0])
# 在上文的基础上, 获取对齐人脸的特征feature。
image_feature = recognizer.feature(aligned_face1)
images_feature_list.append(image_feature)
return ID_list, images_feature_list
if __name__ == '__main__':
capture = cv.VideoCapture(74)
capture.set(3, 640) # 设置摄像头的帧的高为640
capture.set(4, 480) # 设置摄像头的帧的宽为480
ID_list, images_feature_list = Gets_Facial_Features(images_path)
while True:
ret, frame = capture.read()
if ret is not True:
print('摄像头未打开')
break
frame_faces = faceDetector.detect(frame)
if frame_faces[1] is not None:
for idx, face in enumerate(frame_faces[1]):
coords = face[:-1].astype(np.int32)
cv.rectangle(frame, (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (255, 0, 0), thickness=2)
cv.circle(frame, (coords[4], coords[5]), 2, (255, 0, 0), thickness=2)
cv.circle(frame, (coords[6], coords[7]), 2, (0, 0, 255), thickness=2)
cv.circle(frame, (coords[8], coords[9]), 2, (0, 255, 0), thickness=2)
cv.circle(frame, (coords[10], coords[11]), 2, (255, 0, 255), thickness=2)
cv.circle(frame, (coords[12], coords[13]), 2, (0, 255, 255), thickness=2)
aligned_face = recognizer.alignCrop(frame, frame_faces[1][idx])
frame_feature = recognizer.feature(aligned_face)
for index, image_feature in enumerate(images_feature_list):
cosine_score = recognizer.match(frame_feature, image_feature, 0)
l2_score = recognizer.match(frame_feature, image_feature, 1)
if (cosine_score >= cosine_similarity_threshold):
cv.putText(frame, ID_list[index], (coords[0] + 5, coords[1] - 5), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
i = 1
break
elif (l2_score <= l2_similarity_threshold):
cv.putText(frame, ID_list[index], (coords[0] + 5, coords[1] - 5), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
i = 1
break
# else:
# cv.putText(frame, 'unkown', (coords[0] + 5, coords[1] - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5,
# (0, 255, 0), 2)
cv.imshow('RP3588_face_DEMO', frame)
c = cv.waitKey(1)
# 按esc退出视频
if c == 27:
break
else:
cv.putText(frame, 'face is not detected', (1, 16), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv.imshow('photo-collection-demo', frame)
c = cv.waitKey(1)
# 按esc退出视频
if c == 27:
break
2、人脸采集代码
# -*- coding: utf-8 -*-
import cv2
import sys
from PIL import Image
def CatchPICFromVideo(window_name, camera_idx, catch_pic_num, path_name):
cv2.namedWindow(window_name)
# 视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)
# 告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier("./static/haarcascade_frontalface_default.xml")
# 识别出人脸后要画的边框的颜色,RGB格式
color = (0, 255, 0)
num = 0
while cap.isOpened():
ok, frame = cap.read() # 读取一帧数据
if not ok:
break
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 将当前桢图像转换成灰度图像
# 人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
if len(faceRects) > 0: # 大于0则检测到人脸
for faceRect in faceRects: # 单独框出每一张人脸
x, y, w, h = faceRect
# 将当前帧保存为图片
img_name = '%s/%d.jpg' % (path_name, num)
image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
cv2.imwrite(img_name, image)
num += 1
if num > (catch_pic_num): # 如果超过指定最大保存数量退出循环
break
# 画出矩形框
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
# 显示当前捕捉到了多少人脸图片了,这样站在那里被拍摄时心里有个数,不用两眼一抹黑傻等着
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, 'num:%d' % (num), (x + 30, y + 30), font, 1, (255, 0, 255), 4)
# 超过指定最大保存数量结束程序
if num > (catch_pic_num): break
# 显示图像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
# 释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
if len(sys.argv) != 4:
print("Usage:%s camera_id face_num_max path_name\r\n" % (sys.argv[0]))
else:
CatchPICFromVideo("截取人脸", int(sys.argv[1]), int(sys.argv[2]), sys.argv[3])
验证:
1、打开人脸采集程序,检测到人脸后,按空格键,然后输入名字,回车保存,可继续采集,如果采集完毕按esc退出。
2、采集好人脸后,就可以打开人脸识别程序,进行人脸识别。
测脸
侧脸部分遮盖
戴口罩侧脸:
戴口罩、逆光:
【小结】这开发板太强大了,下一步,做一个人脸识别的门禁系统。
参考资料
https://docs.opencv.org/4.x/d0/dd4/tutorial_dnn_face.html
https://zhuanlan.zhihu.com/p/423625566
https://github.com/opencv/opencv/tree/master/samples/dnn
https://github.com/opencv/opencv/tree/master/modules/objdetect
更多回帖