读取模型

net= cv2.dnn.readNetFromONNX(model_path)

从文件中加载模型

参数说明

model_path:模型文件路径

返回值

对应模型网络的对象

数据预处理

cv2.dnn.blobFromImage(img, scalefactor, size, mean)

输入数据预处理

参数说明

img:待处理图像
scalefactor:用来和图像相乘的比例因子
size:缩放尺寸
mean:用来和图像相减的均值

返回值

用于模型输入的blob对象

设置输入数据

net.setInput(blob)

准备模型网络的输入数据

参数说明

blob:输入blob对象

返回值

执行预测

net.forward(output_list)

执行模型推理,并根据输入数组返回对应的网络层

参数说明

output_list:需要返回的网络层

返回值

指定需要返回的网络层

使用示例:打开摄像头,检测画面中的人脸

  1. # coding=utf-8
  2. import os
  3. import time
  4. from math import ceil
  5. import cv2
  6. import numpy as np
  7. Key_Esc = 27
  8. image_mean = np.array([127, 127, 127])
  9. image_std = 128.0
  10. iou_threshold = 0.3
  11. center_variance = 0.1
  12. size_variance = 0.2
  13. min_boxes = [[10.0, 16.0, 24.0], [32.0, 48.0],
  14. [64.0, 96.0], [128.0, 192.0, 256.0]]
  15. strides = [8.0, 16.0, 32.0, 64.0]
  16. def define_img_size(image_size):
  17. shrinkage_list = []
  18. feature_map_w_h_list = []
  19. for size in image_size:
  20. feature_map = [int(ceil(size / stride)) for stride in strides]
  21. feature_map_w_h_list.append(feature_map)
  22. for i in range(0, len(image_size)):
  23. shrinkage_list.append(strides)
  24. priors = generate_priors(feature_map_w_h_list,
  25. shrinkage_list, image_size, min_boxes)
  26. return priors
  27. def generate_priors(feature_map_list, shrinkage_list, image_size, min_boxes):
  28. priors = []
  29. for index in range(0, len(feature_map_list[0])):
  30. scale_w = image_size[0] / shrinkage_list[0][index]
  31. scale_h = image_size[1] / shrinkage_list[1][index]
  32. for j in range(0, feature_map_list[1][index]):
  33. for i in range(0, feature_map_list[0][index]):
  34. x_center = (i + 0.5) / scale_w
  35. y_center = (j + 0.5) / scale_h
  36. for min_box in min_boxes[index]:
  37. w = min_box / image_size[0]
  38. h = min_box / image_size[1]
  39. priors.append([
  40. x_center,
  41. y_center,
  42. w,
  43. h
  44. ])
  45. print("priors nums:{}".format(len(priors)))
  46. return np.clip(priors, 0.0, 1.0)
  47. def hard_nms(box_scores, iou_threshold, top_k=-1, candidate_size=200):
  48. scores = box_scores[:, -1]
  49. boxes = box_scores[:, :-1]
  50. picked = []
  51. indexes = np.argsort(scores)
  52. indexes = indexes[-candidate_size:]
  53. while len(indexes) > 0:
  54. current = indexes[-1]
  55. picked.append(current)
  56. if 0 < top_k == len(picked) or len(indexes) == 1:
  57. break
  58. current_box = boxes[current, :]
  59. indexes = indexes[:-1]
  60. rest_boxes = boxes[indexes, :]
  61. iou = iou_of(
  62. rest_boxes,
  63. np.expand_dims(current_box, axis=0),
  64. )
  65. indexes = indexes[iou <= iou_threshold]
  66. return box_scores[picked, :]
  67. def area_of(left_top, right_bottom):
  68. hw = np.clip(right_bottom - left_top, 0.0, None)
  69. return hw[..., 0] * hw[..., 1]
  70. def iou_of(boxes0, boxes1, eps=1e-5):
  71. overlap_left_top = np.maximum(boxes0[..., :2], boxes1[..., :2])
  72. overlap_right_bottom = np.minimum(boxes0[..., 2:], boxes1[..., 2:])
  73. overlap_area = area_of(overlap_left_top, overlap_right_bottom)
  74. area0 = area_of(boxes0[..., :2], boxes0[..., 2:])
  75. area1 = area_of(boxes1[..., :2], boxes1[..., 2:])
  76. return overlap_area / (area0 + area1 - overlap_area + eps)
  77. def predict(width, height, confidences, boxes, prob_threshold, iou_threshold=0.3, top_k=-1):
  78. boxes = boxes[0]
  79. confidences = confidences[0]
  80. picked_box_probs = []
  81. picked_labels = []
  82. for class_index in range(1, confidences.shape[1]):
  83. probs = confidences[:, class_index]
  84. mask = probs > prob_threshold
  85. probs = probs[mask]
  86. if probs.shape[0] == 0:
  87. continue
  88. subset_boxes = boxes[mask, :]
  89. box_probs = np.concatenate(
  90. [subset_boxes, probs.reshape(-1, 1)], axis=1)
  91. box_probs = hard_nms(box_probs,
  92. iou_threshold=iou_threshold,
  93. top_k=top_k,
  94. )
  95. picked_box_probs.append(box_probs)
  96. picked_labels.extend([class_index] * box_probs.shape[0])
  97. if not picked_box_probs:
  98. return np.array([]), np.array([]), np.array([])
  99. picked_box_probs = np.concatenate(picked_box_probs)
  100. picked_box_probs[:, 0] *= width
  101. picked_box_probs[:, 1] *= height
  102. picked_box_probs[:, 2] *= width
  103. picked_box_probs[:, 3] *= height
  104. return picked_box_probs[:, :4].astype(np.int32), np.array(picked_labels), picked_box_probs[:, 4]
  105. def convert_locations_to_boxes(locations, priors, center_variance,
  106. size_variance):
  107. if len(priors.shape) + 1 == len(locations.shape):
  108. priors = np.expand_dims(priors, 0)
  109. return np.concatenate([
  110. locations[..., :2] * center_variance *
  111. priors[..., 2:] + priors[..., :2],
  112. np.exp(locations[..., 2:] * size_variance) * priors[..., 2:]
  113. ], axis=len(locations.shape) - 1)
  114. def center_form_to_corner_form(locations):
  115. return np.concatenate([locations[..., :2] - locations[..., 2:] / 2,
  116. locations[..., :2] + locations[..., 2:] / 2], len(locations.shape) - 1)
  117. class UltraFaceInference:
  118. def __init__(self):
  119. # 模型路径
  120. model_path = os.path.expanduser(
  121. '~') + '/Lepi_Data/ros/ultra_face_inference/models/onnx/version-RFB-320_simplified.onnx'
  122. # opencv dnn 模块加载onnx模型
  123. self.net = cv2.dnn.readNetFromONNX(model_path) # onnx version
  124. # net = cv2.dnn.readNetFromCaffe(args.caffe_prototxt_path, args.caffe_model_path) # caffe model converted from onnx
  125. # 缩放尺寸,实际按照该尺寸进行检测,降低精度加快速度
  126. self.setResize(160, 120)
  127. # 检测阈值
  128. self.threshold = 0.7
  129. # 保存检测结果
  130. self.faceCount = 0
  131. self.faceDetections = []
  132. self.faceData = []
  133. def detect(self, img_ori):
  134. time_time = time.time()
  135. rect = cv2.resize(img_ori, (self.resized_witdh, self.resized_height))
  136. rect = cv2.cvtColor(rect, cv2.COLOR_BGR2RGB)
  137. # 准备输入数据
  138. self.net.setInput(cv2.dnn.blobFromImage(
  139. rect, 1 / image_std, (self.resized_witdh, self.resized_height), 127))
  140. # 执行检测(前向传播)
  141. boxes, scores = self.net.forward(["boxes", "scores"])
  142. boxes = np.expand_dims(np.reshape(boxes, (-1, 4)), axis=0)
  143. scores = np.expand_dims(np.reshape(scores, (-1, 2)), axis=0)
  144. boxes = convert_locations_to_boxes(
  145. boxes, self.priors, center_variance, size_variance)
  146. boxes = center_form_to_corner_form(boxes)
  147. boxes, labels, probs = predict(
  148. img_ori.shape[1], img_ori.shape[0], scores, boxes, self.threshold)
  149. self.faceDetections = self.toFaceDetections(boxes, probs)
  150. self.faceData = self.toFaceData(self.faceDetections)
  151. for i in range(boxes.shape[0]):
  152. box = boxes[i, :]
  153. return boxes, labels, probs
  154. def drawBoxes(self, img_ori, boxes):
  155. # 绘制人脸框
  156. for i in range(boxes.shape[0]):
  157. box = boxes[i, :]
  158. cv2.rectangle(img_ori, (box[0], box[1]),
  159. (box[2], box[3]), (0, 255, 0), 4)
  160. # print("inference time: {} s".format(round(time.time() - time_time, 4)))
  161. return img_ori
  162. def setThreshold(self, threshold):
  163. if threshold > 1:
  164. self.threshold = threshold / 100.0
  165. else:
  166. self.threshold = threshold
  167. def setResize(self, width, height):
  168. self.resized_witdh = width
  169. self.resized_height = height
  170. self.priors = define_img_size(
  171. [self.resized_witdh, self.resized_height])
  172. def toFaceDetections(self, face_locations=[], face_probs=[]):
  173. detections = []
  174. if len(face_probs) > 0 and len(face_probs) == len(face_locations):
  175. for (left, top, right, bottom), prob in zip(face_locations, face_probs):
  176. face_detection = (prob, [
  177. left, top, right, bottom])
  178. detections.append(face_detection)
  179. elif len(face_locations) > 0:
  180. for (left, top, right, bottom) in face_locations:
  181. face_detection = (1, [left, top, right, bottom])
  182. detections.append(face_detection)
  183. return detections
  184. def toFaceData(self, faceDetections=[]):
  185. data = []
  186. for _, face in faceDetections:
  187. x = (face[0]+face[2])/2
  188. y = (face[1]+face[3])/2
  189. w = face[2]-face[0]
  190. h = face[3]-face[1]
  191. data.append([x, y, w, h])
  192. return data
  193. if __name__ == '__main__':
  194. # inference()
  195. detector = UltraFaceInference()
  196. cap = cv2.VideoCapture(0)
  197. while True:
  198. # img_path = os.path.join(imgs_path, file_path)
  199. # img_ori = cv2.imread(img_path)
  200. ret, img_ori = cap.read()
  201. time_time = time.time()
  202. boxes, labels, probs = detector.detect(img_ori)
  203. img_ori = detector.drawBoxes(img_ori, boxes)
  204. print("inference time: {} s".format(round(time.time() - time_time, 4)))
  205. cv2.imshow("ultra_face_inference", np.rot90(
  206. cv2.resize(img_ori, (320, 240))))
  207. c = cv2.waitKey(2)
  208. if c == Key_Esc:
  209. break
  210. cv2.destroyAllWindows()
  211. cap.release()