7970浏览
查看: 7970|回复: 0

[教程] 【Mind+Python】人脸识别之识别自己的脸

[复制链接]
本帖最后由 云天 于 2021-8-8 21:14 编辑

一、OpenCV人脸识别之一:数据收集和预处理

程序的功能就是打开电脑摄像头,采集自己100张人脸图片

【Mind+Python】人脸识别之识别自己的脸图1
  1. import cv2
  2. def getTrainingData(window_name, camera_id, path_name, max_num): # path_name是图片存储目录,max_num是需要捕捉的图片数量
  3.     cv2.namedWindow(window_name) # 创建窗口
  4.     cap = cv2.VideoCapture(camera_id) # 打开摄像头
  5.     classifier = cv2.CascadeClassifier('haarshare/haarcascade_frontalface_alt2.xml') # 加载分类器
  6.     color = (0,255,0) # 人脸矩形框的颜色
  7.     num = 0 # 记录存储的图片数量
  8.     while cap.isOpened():
  9.         ok, frame = cap.read()
  10.         if not ok:
  11.             break
  12.         gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化
  13.         faceRects=classifier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32,32))
  14.         if len(faceRects) > 0:
  15.             for faceRect in faceRects:
  16.                 x,y,w,h = faceRect
  17.                 # 捕捉到的图片的名字,这里用到了格式化字符串的输出
  18.                 image_name = '%s%d.jpg' % (path_name, num) # 注意这里图片名一定要加上扩展名,否则后面imwrite的时候会报错:could not find a writer for the specified extension in function cv::imwrite_ 参考:https://stackoverflow.com/questions/9868963/cvimwrite-could-not-find-a-writer-for-the-specified-extension
  19.                 image = frame[y:y+h, x:x+w] # 将当前帧含人脸部分保存为图片,注意这里存的还是彩色图片,前面检测时灰度化是为了降低计算量;这里访问的是从y位开始到y+h-1位
  20.                 cv2.imwrite(image_name, image)
  21.                 num += 1
  22.                 # 超过指定最大保存数量则退出循环
  23.                 if num > max_num:
  24.                     break
  25.                 cv2.rectangle(frame, (x,y), (x+w,y+h), color, 2) # 画出矩形框
  26.                 font = cv2.FONT_HERSHEY_SIMPLEX # 获取内置字体
  27.                 cv2.putText(frame, ('%d'%num), (x+30, y+30), font, 1, (255,0,255), 4) # 调用函数,对人脸坐标位置,添加一个(x+30,y+30)的矩形框用于显示当前捕捉到了多少人脸图片
  28.         if num > max_num:
  29.             break
  30.         cv2.imshow(window_name, frame)
  31.         c = cv2.waitKey(10)
  32.         if c & 0xFF == ord('q'):
  33.             break
  34.     cap.release()#释放摄像头并销毁所有窗口
  35.     cv2.destroyAllWindows()
  36.     print('Finished.')
  37. #主函数
  38. if __name__ =='__main__':
  39.     print ('catching your face and writting into disk...')
  40.     getTrainingData('getTrainData',0,'training_data/',100) # 注意这里的training_data_xx 文件夹就在程序工作目录下
复制代码


二、模型训练
  1. #import OpenCV module
  2. import cv2
  3. #import os module for reading training data directories and paths
  4. import os
  5. #import numpy to convert python lists to numpy arrays as
  6. #it is needed by OpenCV face recognizers
  7. import numpy as np
  8. #使用OpenCV用来检测脸部的函数
  9. def detect_face(img):
  10.     #将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像
  11.     gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  12.    
  13.     #加载OpenCV人脸检测器,我正在使用的是快速的LBP
  14.     #还有一个更准确但缓慢的Haar分类器
  15.     face_cascade = cv2.CascadeClassifier('haarshare/lbpcascade_frontalface.xml')
  16.     #让我们检测多尺度(一些图像可能比其他图像更接近相机)图像
  17.     #结果是一张脸的列表
  18.     faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5);
  19.    
  20.     #如果未检测到面部,则返回原始图像
  21.     if (len(faces) == 0):
  22.         return None, None
  23.    
  24.     #假设只有一张脸,
  25.     #提取面部区域
  26.     (x, y, w, h) = faces[0]
  27.    
  28.     #只返回图像的正面部分
  29.     return gray[y:y+w, x:x+h], faces[0]
  30. #该功能将读取所有人的训练图像,从每个图像检测人脸
  31. #并将返回两个完全相同大小的列表,一个列表
  32. # 每张脸的脸部和另一列标签
  33. def prepare_training_data(data_folder_path):
  34.    
  35.     #------STEP-1--------
  36.     #获取数据文件夹中的目录(每个主题的一个目录)
  37.     dirs = os.listdir(data_folder_path)
  38.    
  39.     #列表来保存所有主题的面孔
  40.     faces = []
  41.     #列表以保存所有主题的标签
  42.     labels = []
  43.    
  44.     #让我们浏览每个目录并阅读其中的图像
  45.     for dir_name in dirs:
  46.         
  47.         #我们的主题目录以字母's'开头
  48.         #如果有的话,忽略任何不相关的目录
  49.         if not dir_name.startswith("s"):
  50.             continue;
  51.             
  52.         #------STEP-2--------
  53.         #从dir_name中提取主题的标签号
  54.         #目录名称格式= slabel
  55.         #,所以从dir_name中删除字母''会给我们标签
  56.         label = int(dir_name.replace("s", ""))
  57.         
  58.         #建立包含当前主题主题图像的目录路径
  59.         #sample subject_dir_path = "training-data/s1"
  60.         subject_dir_path = data_folder_path + "/" + dir_name
  61.         
  62.         #获取给定主题目录内的图像名称
  63.         subject_images_names = os.listdir(subject_dir_path)
  64.         
  65.         #------STEP-3--------
  66.         #浏览每个图片的名称,阅读图片,
  67.         #检测脸部并将脸部添加到脸部列表
  68.         for image_name in subject_images_names:
  69.             
  70.             #忽略.DS_Store之类的系统文件
  71.             if image_name.startswith("."):
  72.                 continue;
  73.             
  74.             #建立图像路径
  75.             #sample image path = training-data/s1/1.pgm
  76.             image_path = subject_dir_path + "/" + image_name
  77.             #阅读图像
  78.             image = cv2.imread(image_path)
  79.             
  80.             #显示图像窗口以显示图像
  81.             cv2.imshow("Training on image...", image)
  82.             cv2.waitKey(100)
  83.             
  84.             #侦测脸部
  85.             face, rect = detect_face(image)
  86.             
  87.             #------STEP-4--------
  88.             #为了本教程的目的
  89.             #我们将忽略未检测到的脸部
  90.             if face is not None:
  91.                 #将脸添加到脸部列表
  92.                 faces.append(face)
  93.                 #为这张脸添加标签
  94.                 labels.append(label)
  95.             
  96.     cv2.destroyAllWindows()
  97.     cv2.waitKey(1)
  98.     cv2.destroyAllWindows()
  99.    
  100.     return faces, labels
  101.     #让我们先准备好我们的训练数据
  102. #数据将在两个相同大小的列表中
  103. #一个列表将包含所有的面孔
  104. #数据将在两个相同大小的列表中
  105. print("Preparing data...")
  106. faces, labels = prepare_training_data("training_data")
  107. print("Data prepared")
  108. #打印总面和标签
  109. print("Total faces: ", len(faces))
  110. print("Total labels: ", len(labels))
  111. print("Preparing train....")
  112. face_recognizer = cv2.face.LBPHFaceRecognizer_create()
  113. face_recognizer.train(faces, np.array(labels))
  114. face_recognizer.write('trainer.yml')
  115. print("faces trained. Exiting Program")
复制代码
生成trainer.yml人脸模型。

【识别人脸】
简单说下流程:
  • 打开摄像头。
  • 加载人脸检测器,加载人脸模型。
  • 人脸检测
  • 把检测到的人脸与人脸模型里面的对比,找出这是谁的脸。
  • 如果人脸是自己的,显示自己的名字。
【Mind+Python】人脸识别之识别自己的脸图2


  1. import cv2
  2. import os
  3. import time
  4. recognizer = cv2.face.LBPHFaceRecognizer_create()
  5. recognizer.read('trainer.yml')
  6. cascadePath = "haarshare/lbpcascade_frontalface.xml"
  7. faceCascade = cv2.CascadeClassifier(cascadePath)
  8. font = cv2.FONT_HERSHEY_SIMPLEX
  9. idnum = 0
  10. names = ['', 'sl','sxs','taobi']
  11. cam = cv2.VideoCapture(0)
  12. minW = 0.1*cam.get(3)
  13. minH = 0.1*cam.get(4)
  14. while True:
  15.     ret, img = cam.read()
  16.     gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  17.     faces = faceCascade.detectMultiScale(
  18.         gray,
  19.         scaleFactor=1.2,
  20.         minNeighbors=5,
  21.         minSize=(int(minW), int(minH))
  22.     )
  23.     for (x, y, w, h) in faces:
  24.         cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
  25.         idnum, confidence = recognizer.predict(gray[y:y+h, x:x+w])
  26.         if confidence < 100:
  27.             idnum = names[idnum]
  28.             confidence = "{0}%".format(round(100 - confidence))
  29.         else:
  30.             idnum = "unknown"
  31.             confidence = "{0}%".format(round(100 - confidence))
  32.         cv2.putText(img, str(idnum), (x+5, y-5), font, 1, (0, 0, 255), 1)
  33.         cv2.putText(img, str(confidence), (x+5, y+h-5), font, 1, (0, 0, 0), 1)
  34.     cv2.imshow('camera', img)
  35.     k = cv2.waitKey(10)
  36.     if k == 27:
  37.         break
  38. cam.release()
  39. cv2.destroyAllWindows()
  40. # def draw_rectangle(img, rect):
  41. #     (x, y, w, h) = rect
  42. #     cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
  43.    
  44. # #function to draw text on give image starting from
  45. # #passed (x, y) coordinates.
  46. # def draw_text(img, text, x, y):
  47. #     cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
  48. # def detect_face(img):
  49. #     #convert the test image to gray image as opencv face detector expects gray images
  50. #     gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  51. #     cascadePath = 'opencv-files/lbpcascade_frontalface.xml'
  52. #     face_cascade = cv2.CascadeClassifier(cascadePath)
  53. #     #load OpenCV face detector, I am using LBP which is fast
  54. #     #there is also a more accurate but slow Haar classifier
  55. #     #face_cascade = cv2.CascadeClassifier('opencv-files/haarcascade_frontalface_alt.xml')
  56. #     #let's detect multiscale (some images may be closer to camera than others) images
  57. #     #result is a list of faces
  58. #     faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5);
  59. #     #if no faces are detected then return original img
  60. #     print(len(faces))
  61. #     if (len(faces) == 0):
  62. #         return None, None
  63.    
  64. #     #under the assumption that there will be only one face,
  65. #     #extract the face area
  66. #     (x, y, w, h) = faces[0]
  67.    
  68. #     #return only the face part of the image
  69. #     return gray[y:y+w, x:x+h], faces[0]
  70. # face_recognizer = cv2.face.LBPHFaceRecognizer_create()
  71. # face_recognizer.read('trainer.yml')
  72. # names = ['', 'Bob','xxx','Taotaotao']
  73. # print("Predicting images...")
  74. # #load test images
  75. # test_img = cv2.imread("1.jpg")
  76. # #perform a prediction
  77. # img = test_img.copy()
  78. # start=time.clock()
  79. # face, rect = detect_face(img)
  80. # label, confidence = face_recognizer.predict(face)
  81. # label_text = names[label]
  82. # end=time.clock()
  83. # draw_rectangle(img, rect)
  84. # draw_text(img, label_text, rect[0], rect[1]-5)
  85. # print("Prediction complete time %s"%(end-start))
  86. # #display both images
  87. # cv2.imshow("0000", cv2.resize(img, (400, 500)))
  88. # cv2.waitKey(3600)
  89. # cv2.destroyAllWindows()
复制代码




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail