赞
踩
完成一个人脸识别的程序,可以识别你宿舍的几位同学
人脸特征提取与比对
需要识别的人物:
输入待识别图像,判断是哪一个舍友
识别效果:人脸检测框定,返回室友的名字:唐悠悠-tyy
人脸检测模型下载:https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet
人脸识别模型下载:
https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface
参考官方代码https://github.com/opencv/opencv/blob/4.x/samples/dnn/face_detect.py
基准图片:
其他图片:
用于后面预测识别的舍友图片:
引入包,读入图片,resize图片大小
- import cv2
- import time
- import numpy as np
-
- # 定义输入和变量,读入四个室友的基准照片
- rm1 = cv2.imread('roomates/ggsq.png')
- rm2 = cv2.imread('roomates/tyy.png')
- rm3 = cv2.imread('roomates/zxx.png')
- rm4 = cv2.imread('roomates/hyf.png')
- # 读入待识别照片
- in_rm = cv2.imread('images/tyy/4.png')
-
- new_shape = (300, 300) # 统一缩放为 300*300
- cos_thresh = 0.363 # cos阈值,距离越大越接近
- L2_thresh = 1.128 # L2阈值,距离越小越接近
- rm1 = cv2.resize(rm1, new_shape)
- rm2 = cv2.resize(rm2, new_shape)
- rm3 = cv2.resize(rm3, new_shape)
- rm4 = cv2.resize(rm4, new_shape)
-
- in_rm = cv2.resize(in_rm, new_shape)
先定义一个用来展示识别到的图片的可视化函数,后面调用会显示人脸检测方框和检测到的室友名字
- def visualize(input, faces, fps, name, thickness=2):
- if faces[1] is not None:
- for idx, face in enumerate(faces[1]):
- print(
- 'Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(
- idx, face[0], face[1], face[2], face[3], face[-1]))
-
- coords = face[:-1].astype(np.int32)
- cv2.rectangle(input, (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (0, 255, 0),
- thickness)
- cv2.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
- cv2.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
- cv2.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
- cv2.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
- cv2.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
- cv2.putText(input, 'FPS: {0:.2f},Roomate:{1}'.format(fps, name), (1, 16), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
初始化模型,使用模型:
- # 初始化模型,使用上面下载好的模型文件
- faceDetector = cv2.FaceDetectorYN.create('face_detection_yunet_2022mar.onnx', '', new_shape)
- faceRecognizer = cv2.FaceRecognizerSF.create('face_recognizer_fast.onnx', '')
-
- # 检测、对齐、提取特征:
- # detect输出的是一个二维元祖,其中第二维是一个二维数组: n*15,n为人脸数,
- # 15为人脸的xywh和5个关键点(右眼瞳孔、左眼、鼻尖、右嘴角、左嘴角)的xy坐标及置信度
- faces1 = faceDetector.detect(rm1)
- aligned_face1 = faceRecognizer.alignCrop(rm1, faces1[1][0]) # 对齐后的图片
- feature1 = faceRecognizer.feature(aligned_face1) # 128维特征
-
- faces2 = faceDetector.detect(rm2)
- aligned_face2 = faceRecognizer.alignCrop(rm2, faces2[1][0])
- feature2 = faceRecognizer.feature(aligned_face2)
-
- faces3 = faceDetector.detect(rm3)
- aligned_face3 = faceRecognizer.alignCrop(rm3, faces3[1][0])
- feature3 = faceRecognizer.feature(aligned_face3)
-
- faces4 = faceDetector.detect(rm4)
- aligned_face4 = faceRecognizer.alignCrop(rm4, faces4[1][0])
- feature4 = faceRecognizer.feature(aligned_face4)
-
- # 检测读入待识别的图片,假如该图片里面没有人,就抛出没有人的错误
- in_faces = faceDetector.detect(in_rm)
- assert in_faces[1] is not None, 'Cannot find a face in input picture'
- in_aligned_face = faceRecognizer.alignCrop(in_rm, in_faces[1][0])
- in_feature = faceRecognizer.feature(in_aligned_face);
计算待识别的图片中的人和4个室友基准图片的匹配程度,取匹配程度最大的结果,若该结果与原舍友图片的相似程度达到一定的阈值,则判断该图片就是这个舍友,否则说明待识别的图片不属于4个舍友中的任何一个,可能是其他人
- # 人脸匹配值打分:
- cos_score1 = faceRecognizer.match(feature1, in_feature, 0)
- cos_score2 = faceRecognizer.match(feature2, in_feature, 0)
- cos_score3 = faceRecognizer.match(feature3, in_feature, 0)
- cos_score4 = faceRecognizer.match(feature4, in_feature, 0)
-
- # 得分列表索引对应室友名字索引
- rmlist = ['ggsq', 'tyy', 'zxx', 'hyf']
- score_list = [cos_score1, cos_score2, cos_score3, cos_score4]
- # 输出结果:
- print('cos_score_list: ', score_list)
- in_score = max(score_list)
- # 如果当前最有可能的室友得分大于识别阈值,则判断该图片存在室友,注意只能识别一个室友
- if in_score > cos_thresh:
- rm_dect = rmlist[score_list.index(max(score_list))]
- print('识别到室友: ', rm_dect)
- visualize(in_rm, in_faces, tm.getFPS(),rm_dect)
- cv2.imshow('in_roomates', in_rm)
- else:
- print('当前图片未识别到室友')
- visualize(in_rm, in_faces, tm.getFPS(),"None")
- cv2.imshow('in_roomates', in_rm)
-
- cv2.waitKey(0)
输入4室友之一的图片
输入其他人的图片:
输入没有人的图片:
完整代码如下:
- import cv2
- import time
- import numpy as np
-
-
- def visualize(input, faces, fps, name, thickness=2):
- if faces[1] is not None:
- for idx, face in enumerate(faces[1]):
- print(
- 'Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(
- idx, face[0], face[1], face[2], face[3], face[-1]))
-
- coords = face[:-1].astype(np.int32)
- cv2.rectangle(input, (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (0, 255, 0),
- thickness)
- cv2.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
- cv2.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
- cv2.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
- cv2.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
- cv2.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
- cv2.putText(input, 'FPS: {0:.2f},Roomate:{1}'.format(fps, name), (1, 16), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
-
-
- # 计时器
- tm = cv2.TickMeter()
-
- # 定义输入和变量
- rm1 = cv2.imread('roomates/ggsq.png')
- rm2 = cv2.imread('roomates/tyy.png')
- rm3 = cv2.imread('roomates/zxx.png')
- rm4 = cv2.imread('roomates/hyf.png')
-
- in_rm = cv2.imread('images/tyy/4.png')
-
- new_shape = (300, 300) # 统一缩放为 300*300
- cos_thresh = 0.363 # cos阈值,距离越大越接近
- L2_thresh = 1.128 # L2阈值,距离越小越接近
- rm1 = cv2.resize(rm1, new_shape)
- rm2 = cv2.resize(rm2, new_shape)
- rm3 = cv2.resize(rm3, new_shape)
- rm4 = cv2.resize(rm4, new_shape)
-
- in_rm = cv2.resize(in_rm, new_shape)
-
- # 初始化模型:
- faceDetector = cv2.FaceDetectorYN.create('face_detection_yunet_2022mar.onnx', '', new_shape)
- faceRecognizer = cv2.FaceRecognizerSF.create('face_recognizer_fast.onnx', '')
-
- tm.start()
-
- # 检测、对齐、提取特征:
- # detect输出的是一个二维元祖,其中第二维是一个二维数组: n*15,n为人脸数,
- # 15为人脸的xywh和5个关键点(右眼瞳孔、左眼、鼻尖、右嘴角、左嘴角)的xy坐标及置信度
- faces1 = faceDetector.detect(rm1)
- aligned_face1 = faceRecognizer.alignCrop(rm1, faces1[1][0]) # 对齐后的图片
- feature1 = faceRecognizer.feature(aligned_face1) # 128维特征
-
- faces2 = faceDetector.detect(rm2)
- aligned_face2 = faceRecognizer.alignCrop(rm2, faces2[1][0])
- feature2 = faceRecognizer.feature(aligned_face2)
-
- faces3 = faceDetector.detect(rm3)
- aligned_face3 = faceRecognizer.alignCrop(rm3, faces3[1][0])
- feature3 = faceRecognizer.feature(aligned_face3)
-
- faces4 = faceDetector.detect(rm4)
- aligned_face4 = faceRecognizer.alignCrop(rm4, faces4[1][0])
- feature4 = faceRecognizer.feature(aligned_face4)
-
- in_faces = faceDetector.detect(in_rm)
- assert in_faces[1] is not None, 'Cannot find a face in input picture'
- in_aligned_face = faceRecognizer.alignCrop(in_rm, in_faces[1][0])
- in_feature = faceRecognizer.feature(in_aligned_face);
-
- tm.stop()
-
-
- # 人脸匹配值打分:
- cos_score1 = faceRecognizer.match(feature1, in_feature, 0)
- cos_score2 = faceRecognizer.match(feature2, in_feature, 0)
- cos_score3 = faceRecognizer.match(feature3, in_feature, 0)
- cos_score4 = faceRecognizer.match(feature4, in_feature, 0)
-
- # 得分列表索引对应室友名字索引
- rmlist = ['ggsq', 'tyy', 'zxx', 'hyf']
- score_list = [cos_score1, cos_score2, cos_score3, cos_score4]
- # 输出结果:
- print('cos_score_list: ', score_list)
- in_score = max(score_list)
- # 如果当前最有可能的室友得分大于识别阈值,则判断该图片存在室友,注意只能识别一个室友
- if in_score > cos_thresh:
- rm_dect = rmlist[score_list.index(max(score_list))]
- print('识别到室友: ', rm_dect)
- visualize(in_rm, in_faces, tm.getFPS(),rm_dect)
- cv2.imshow('in_roomates', in_rm)
- else:
- print('当前图片未识别到室友')
- visualize(in_rm, in_faces, tm.getFPS(),"None")
- cv2.imshow('in_roomates', in_rm)
-
- cv2.waitKey(0)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。