当前位置:   article > 正文

Opencv人脸检测应用-识别4个室友_opencv 人脸检测人脸特征文件

opencv 人脸检测人脸特征文件

实验目标:

 

完成一个人脸识别的程序,可以识别你宿舍的几位同学

人脸检测

人脸特征提取与比对 

需要识别的人物:

 输入待识别图像,判断是哪一个舍友

识别效果:人脸检测框定,返回室友的名字:唐悠悠-tyy

参考资料:

  1. https://docs.opencv.org/4.5.4/d0/dd4/tutorial_dnn_face.html https://blog.csdn.net/qq_36563273/article/details/121510440
  2. 人脸检测器: cv2.FaceDetectorYN
  3. 人脸特征提取:cv2.FaceRecognizerSF

实验步骤

模型下载

人脸检测模型下载: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图片大小

  1. import cv2
  2. import time
  3. import numpy as np
  4. # 定义输入和变量,读入四个室友的基准照片
  5. rm1 = cv2.imread('roomates/ggsq.png')
  6. rm2 = cv2.imread('roomates/tyy.png')
  7. rm3 = cv2.imread('roomates/zxx.png')
  8. rm4 = cv2.imread('roomates/hyf.png')
  9. # 读入待识别照片
  10. in_rm = cv2.imread('images/tyy/4.png')
  11. new_shape = (300, 300) # 统一缩放为 300*300
  12. cos_thresh = 0.363 # cos阈值,距离越大越接近
  13. L2_thresh = 1.128 # L2阈值,距离越小越接近
  14. rm1 = cv2.resize(rm1, new_shape)
  15. rm2 = cv2.resize(rm2, new_shape)
  16. rm3 = cv2.resize(rm3, new_shape)
  17. rm4 = cv2.resize(rm4, new_shape)
  18. in_rm = cv2.resize(in_rm, new_shape)

先定义一个用来展示识别到的图片的可视化函数,后面调用会显示人脸检测方框和检测到的室友名字

  1. def visualize(input, faces, fps, name, thickness=2):
  2. if faces[1] is not None:
  3. for idx, face in enumerate(faces[1]):
  4. print(
  5. 'Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(
  6. idx, face[0], face[1], face[2], face[3], face[-1]))
  7. coords = face[:-1].astype(np.int32)
  8. cv2.rectangle(input, (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (0, 255, 0),
  9. thickness)
  10. cv2.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
  11. cv2.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
  12. cv2.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
  13. cv2.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
  14. cv2.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
  15. cv2.putText(input, 'FPS: {0:.2f},Roomate:{1}'.format(fps, name), (1, 16), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

初始化模型,使用模型:

  1. # 初始化模型,使用上面下载好的模型文件
  2. faceDetector = cv2.FaceDetectorYN.create('face_detection_yunet_2022mar.onnx', '', new_shape)
  3. faceRecognizer = cv2.FaceRecognizerSF.create('face_recognizer_fast.onnx', '')
  4. # 检测、对齐、提取特征:
  5. # detect输出的是一个二维元祖,其中第二维是一个二维数组: n*15,n为人脸数,
  6. # 15为人脸的xywh和5个关键点(右眼瞳孔、左眼、鼻尖、右嘴角、左嘴角)的xy坐标及置信度
  7. faces1 = faceDetector.detect(rm1)
  8. aligned_face1 = faceRecognizer.alignCrop(rm1, faces1[1][0]) # 对齐后的图片
  9. feature1 = faceRecognizer.feature(aligned_face1) # 128维特征
  10. faces2 = faceDetector.detect(rm2)
  11. aligned_face2 = faceRecognizer.alignCrop(rm2, faces2[1][0])
  12. feature2 = faceRecognizer.feature(aligned_face2)
  13. faces3 = faceDetector.detect(rm3)
  14. aligned_face3 = faceRecognizer.alignCrop(rm3, faces3[1][0])
  15. feature3 = faceRecognizer.feature(aligned_face3)
  16. faces4 = faceDetector.detect(rm4)
  17. aligned_face4 = faceRecognizer.alignCrop(rm4, faces4[1][0])
  18. feature4 = faceRecognizer.feature(aligned_face4)
  19. # 检测读入待识别的图片,假如该图片里面没有人,就抛出没有人的错误
  20. in_faces = faceDetector.detect(in_rm)
  21. assert in_faces[1] is not None, 'Cannot find a face in input picture'
  22. in_aligned_face = faceRecognizer.alignCrop(in_rm, in_faces[1][0])
  23. in_feature = faceRecognizer.feature(in_aligned_face);

计算待识别的图片中的人和4个室友基准图片的匹配程度,取匹配程度最大的结果,若该结果与原舍友图片的相似程度达到一定的阈值,则判断该图片就是这个舍友,否则说明待识别的图片不属于4个舍友中的任何一个,可能是其他人

  1. # 人脸匹配值打分:
  2. cos_score1 = faceRecognizer.match(feature1, in_feature, 0)
  3. cos_score2 = faceRecognizer.match(feature2, in_feature, 0)
  4. cos_score3 = faceRecognizer.match(feature3, in_feature, 0)
  5. cos_score4 = faceRecognizer.match(feature4, in_feature, 0)
  6. # 得分列表索引对应室友名字索引
  7. rmlist = ['ggsq', 'tyy', 'zxx', 'hyf']
  8. score_list = [cos_score1, cos_score2, cos_score3, cos_score4]
  9. # 输出结果:
  10. print('cos_score_list: ', score_list)
  11. in_score = max(score_list)
  12. # 如果当前最有可能的室友得分大于识别阈值,则判断该图片存在室友,注意只能识别一个室友
  13. if in_score > cos_thresh:
  14. rm_dect = rmlist[score_list.index(max(score_list))]
  15. print('识别到室友: ', rm_dect)
  16. visualize(in_rm, in_faces, tm.getFPS(),rm_dect)
  17. cv2.imshow('in_roomates', in_rm)
  18. else:
  19. print('当前图片未识别到室友')
  20. visualize(in_rm, in_faces, tm.getFPS(),"None")
  21. cv2.imshow('in_roomates', in_rm)
  22. cv2.waitKey(0)

效果演示:

输入4室友之一的图片

 输入其他人的图片:

输入没有人的图片:

 

 

 

完整代码如下:

  1. import cv2
  2. import time
  3. import numpy as np
  4. def visualize(input, faces, fps, name, thickness=2):
  5. if faces[1] is not None:
  6. for idx, face in enumerate(faces[1]):
  7. print(
  8. 'Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(
  9. idx, face[0], face[1], face[2], face[3], face[-1]))
  10. coords = face[:-1].astype(np.int32)
  11. cv2.rectangle(input, (coords[0], coords[1]), (coords[0] + coords[2], coords[1] + coords[3]), (0, 255, 0),
  12. thickness)
  13. cv2.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
  14. cv2.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
  15. cv2.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
  16. cv2.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
  17. cv2.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
  18. cv2.putText(input, 'FPS: {0:.2f},Roomate:{1}'.format(fps, name), (1, 16), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
  19. # 计时器
  20. tm = cv2.TickMeter()
  21. # 定义输入和变量
  22. rm1 = cv2.imread('roomates/ggsq.png')
  23. rm2 = cv2.imread('roomates/tyy.png')
  24. rm3 = cv2.imread('roomates/zxx.png')
  25. rm4 = cv2.imread('roomates/hyf.png')
  26. in_rm = cv2.imread('images/tyy/4.png')
  27. new_shape = (300, 300) # 统一缩放为 300*300
  28. cos_thresh = 0.363 # cos阈值,距离越大越接近
  29. L2_thresh = 1.128 # L2阈值,距离越小越接近
  30. rm1 = cv2.resize(rm1, new_shape)
  31. rm2 = cv2.resize(rm2, new_shape)
  32. rm3 = cv2.resize(rm3, new_shape)
  33. rm4 = cv2.resize(rm4, new_shape)
  34. in_rm = cv2.resize(in_rm, new_shape)
  35. # 初始化模型:
  36. faceDetector = cv2.FaceDetectorYN.create('face_detection_yunet_2022mar.onnx', '', new_shape)
  37. faceRecognizer = cv2.FaceRecognizerSF.create('face_recognizer_fast.onnx', '')
  38. tm.start()
  39. # 检测、对齐、提取特征:
  40. # detect输出的是一个二维元祖,其中第二维是一个二维数组: n*15,n为人脸数,
  41. # 15为人脸的xywh和5个关键点(右眼瞳孔、左眼、鼻尖、右嘴角、左嘴角)的xy坐标及置信度
  42. faces1 = faceDetector.detect(rm1)
  43. aligned_face1 = faceRecognizer.alignCrop(rm1, faces1[1][0]) # 对齐后的图片
  44. feature1 = faceRecognizer.feature(aligned_face1) # 128维特征
  45. faces2 = faceDetector.detect(rm2)
  46. aligned_face2 = faceRecognizer.alignCrop(rm2, faces2[1][0])
  47. feature2 = faceRecognizer.feature(aligned_face2)
  48. faces3 = faceDetector.detect(rm3)
  49. aligned_face3 = faceRecognizer.alignCrop(rm3, faces3[1][0])
  50. feature3 = faceRecognizer.feature(aligned_face3)
  51. faces4 = faceDetector.detect(rm4)
  52. aligned_face4 = faceRecognizer.alignCrop(rm4, faces4[1][0])
  53. feature4 = faceRecognizer.feature(aligned_face4)
  54. in_faces = faceDetector.detect(in_rm)
  55. assert in_faces[1] is not None, 'Cannot find a face in input picture'
  56. in_aligned_face = faceRecognizer.alignCrop(in_rm, in_faces[1][0])
  57. in_feature = faceRecognizer.feature(in_aligned_face);
  58. tm.stop()
  59. # 人脸匹配值打分:
  60. cos_score1 = faceRecognizer.match(feature1, in_feature, 0)
  61. cos_score2 = faceRecognizer.match(feature2, in_feature, 0)
  62. cos_score3 = faceRecognizer.match(feature3, in_feature, 0)
  63. cos_score4 = faceRecognizer.match(feature4, in_feature, 0)
  64. # 得分列表索引对应室友名字索引
  65. rmlist = ['ggsq', 'tyy', 'zxx', 'hyf']
  66. score_list = [cos_score1, cos_score2, cos_score3, cos_score4]
  67. # 输出结果:
  68. print('cos_score_list: ', score_list)
  69. in_score = max(score_list)
  70. # 如果当前最有可能的室友得分大于识别阈值,则判断该图片存在室友,注意只能识别一个室友
  71. if in_score > cos_thresh:
  72. rm_dect = rmlist[score_list.index(max(score_list))]
  73. print('识别到室友: ', rm_dect)
  74. visualize(in_rm, in_faces, tm.getFPS(),rm_dect)
  75. cv2.imshow('in_roomates', in_rm)
  76. else:
  77. print('当前图片未识别到室友')
  78. visualize(in_rm, in_faces, tm.getFPS(),"None")
  79. cv2.imshow('in_roomates', in_rm)
  80. cv2.waitKey(0)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/116173
推荐阅读
相关标签
  

闽ICP备14008679号