2022年 11月 16日

基于Python+Opencv识别性别年龄(摄像头实现,可换成图片)

环境要求:Python环境+Opencv有DNN的版本

模型文件:链接:https://pan.baidu.com/s/1W4ar8L8FiJ41IYcZQkf4mA 
提取码:jp06 

代码:

  1. import cv2 as cv
  2. import time
  3. # 检测人脸并绘制人脸bounding box
  4. def getFaceBox(net, frame, conf_threshold=0.7):
  5. frameOpencvDnn = frame.copy()
  6. frameHeight = frameOpencvDnn.shape[0] # 高就是矩阵有多少行
  7. frameWidth = frameOpencvDnn.shape[1] # 宽就是矩阵有多少列
  8. blob = cv.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)
  9. # blobFromImage(image[, scalefactor[, size[, mean[, swapRB[, crop[, ddepth]]]]]]) -> retval 返回值 # swapRB是交换第一个和最后一个通道 返回按NCHW尺寸顺序排列的4 Mat值
  10. net.setInput(blob)
  11. detections = net.forward() # 网络进行前向传播,检测人脸
  12. bboxes = []
  13. for i in range(detections.shape[2]):
  14. confidence = detections[0, 0, i, 2]
  15. if confidence > conf_threshold:
  16. x1 = int(detections[0, 0, i, 3] * frameWidth)
  17. y1 = int(detections[0, 0, i, 4] * frameHeight)
  18. x2 = int(detections[0, 0, i, 5] * frameWidth)
  19. y2 = int(detections[0, 0, i, 6] * frameHeight)
  20. bboxes.append([x1, y1, x2, y2]) # bounding box 的坐标
  21. cv.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight / 150)),
  22. 8) # rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img
  23. return frameOpencvDnn, bboxes
  24. # 网络模型 和 预训练模型
  25. faceProto = "age_gender/opencv_face_detector.pbtxt"
  26. faceModel = "age_gender/opencv_face_detector_uint8.pb"
  27. ageProto = "age_gender/age_deploy.prototxt"
  28. ageModel = "age_gender/age_net.caffemodel"
  29. genderProto = "age_gender/gender_deploy.prototxt"
  30. genderModel = "age_gender/gender_net.caffemodel"
  31. # 模型均值
  32. MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
  33. ageList = ['(0-2)', '(4-6)', '(8-12)', '(15-20)', '(25-32)', '(38-43)', '(48-53)', '(60-100)']
  34. genderList = ['Male', 'Female']
  35. # 加载网络
  36. ageNet = cv.dnn.readNet(ageModel, ageProto)
  37. genderNet = cv.dnn.readNet(genderModel, genderProto)
  38. # 人脸检测的网络和模型
  39. faceNet = cv.dnn.readNet(faceModel, faceProto)
  40. # 打开一个视频文件或一张图片或一个摄像头
  41. cap = cv.VideoCapture(0)
  42. padding = 20
  43. while cv.waitKey(1) < 0:
  44. # Read frame
  45. t = time.time()
  46. hasFrame, frame = cap.read()
  47. frame = cv.flip(frame, 1)
  48. if not hasFrame:
  49. cv.waitKey()
  50. break
  51. frameFace, bboxes = getFaceBox(faceNet, frame)
  52. if not bboxes:
  53. print("No face Detected, Checking next frame")
  54. continue
  55. for bbox in bboxes:
  56. # print(bbox) # 取出box框住的脸部进行检测,返回的是脸部图片
  57. face = frame[max(0, bbox[1] - padding):min(bbox[3] + padding, frame.shape[0] - 1),
  58. max(0, bbox[0] - padding):min(bbox[2] + padding, frame.shape[1] - 1)]
  59. print("=======", type(face), face.shape) # <class 'numpy.ndarray'> (166, 154, 3)
  60. #
  61. blob = cv.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
  62. print("======", type(blob), blob.shape) # <class 'numpy.ndarray'> (1, 3, 227, 227)
  63. genderNet.setInput(blob) # blob输入网络进行性别的检测
  64. genderPreds = genderNet.forward() # 性别检测进行前向传播
  65. print("++++++", type(genderPreds), genderPreds.shape, genderPreds) # <class 'numpy.ndarray'> (1, 2) [[9.9999917e-01 8.6268375e-07]] 变化的值
  66. gender = genderList[genderPreds[0].argmax()] # 分类 返回性别类型
  67. # print("Gender Output : {}".format(genderPreds))
  68. print("Gender : {}, conf = {:.3f}".format(gender, genderPreds[0].max()))
  69. ageNet.setInput(blob)
  70. agePreds = ageNet.forward()
  71. age = ageList[agePreds[0].argmax()]
  72. print(agePreds[0].argmax()) # 3
  73. print("*********", agePreds[0]) # [4.5557402e-07 1.9009208e-06 2.8783199e-04 9.9841607e-01 1.5261240e-04 1.0924522e-03 1.3928890e-05 3.4708322e-05]
  74. print("Age Output : {}".format(agePreds))
  75. print("Age : {}, conf = {:.3f}".format(age, agePreds[0].max()))
  76. label = "{},{}".format(gender, age)
  77. cv.putText(frameFace, label, (bbox[0], bbox[1] - 10), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2,
  78. cv.LINE_AA) # putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) -> img
  79. cv.imshow("Age Gender Demo", frameFace)
  80. print("time : {:.3f} ms".format(time.time() - t))