openvino_infer.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import cv2
  15. import numpy as np
  16. import argparse
  17. from scipy.special import softmax
  18. from openvino.runtime import Core
  19. def image_preprocess(img_path, re_shape):
  20. img = cv2.imread(img_path)
  21. img = cv2.resize(
  22. img, (re_shape, re_shape), interpolation=cv2.INTER_LANCZOS4)
  23. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  24. img = np.transpose(img, [2, 0, 1]) / 255
  25. img = np.expand_dims(img, 0)
  26. img_mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))
  27. img_std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))
  28. img -= img_mean
  29. img /= img_std
  30. return img.astype(np.float32)
  31. def get_color_map_list(num_classes):
  32. color_map = num_classes * [0, 0, 0]
  33. for i in range(0, num_classes):
  34. j = 0
  35. lab = i
  36. while lab:
  37. color_map[i * 3] |= (((lab >> 0) & 1) << (7 - j))
  38. color_map[i * 3 + 1] |= (((lab >> 1) & 1) << (7 - j))
  39. color_map[i * 3 + 2] |= (((lab >> 2) & 1) << (7 - j))
  40. j += 1
  41. lab >>= 3
  42. color_map = [color_map[i:i + 3] for i in range(0, len(color_map), 3)]
  43. return color_map
  44. def draw_box(srcimg, results, class_label):
  45. label_list = list(
  46. map(lambda x: x.strip(), open(class_label, 'r').readlines()))
  47. for i in range(len(results)):
  48. color_list = get_color_map_list(len(label_list))
  49. clsid2color = {}
  50. classid, conf = int(results[i, 0]), results[i, 1]
  51. xmin, ymin, xmax, ymax = int(results[i, 2]), int(results[i, 3]), int(
  52. results[i, 4]), int(results[i, 5])
  53. if classid not in clsid2color:
  54. clsid2color[classid] = color_list[classid]
  55. color = tuple(clsid2color[classid])
  56. cv2.rectangle(srcimg, (xmin, ymin), (xmax, ymax), color, thickness=2)
  57. print(label_list[classid] + ': ' + str(round(conf, 3)))
  58. cv2.putText(
  59. srcimg,
  60. label_list[classid] + ':' + str(round(conf, 3)), (xmin, ymin - 10),
  61. cv2.FONT_HERSHEY_SIMPLEX,
  62. 0.8, (0, 255, 0),
  63. thickness=2)
  64. return srcimg
  65. def hard_nms(box_scores, iou_threshold, top_k=-1, candidate_size=200):
  66. """
  67. Args:
  68. box_scores (N, 5): boxes in corner-form and probabilities.
  69. iou_threshold: intersection over union threshold.
  70. top_k: keep top_k results. If k <= 0, keep all the results.
  71. candidate_size: only consider the candidates with the highest scores.
  72. Returns:
  73. picked: a list of indexes of the kept boxes
  74. """
  75. scores = box_scores[:, -1]
  76. boxes = box_scores[:, :-1]
  77. picked = []
  78. indexes = np.argsort(scores)
  79. indexes = indexes[-candidate_size:]
  80. while len(indexes) > 0:
  81. current = indexes[-1]
  82. picked.append(current)
  83. if 0 < top_k == len(picked) or len(indexes) == 1:
  84. break
  85. current_box = boxes[current, :]
  86. indexes = indexes[:-1]
  87. rest_boxes = boxes[indexes, :]
  88. iou = iou_of(
  89. rest_boxes,
  90. np.expand_dims(
  91. current_box, axis=0), )
  92. indexes = indexes[iou <= iou_threshold]
  93. return box_scores[picked, :]
  94. def iou_of(boxes0, boxes1, eps=1e-5):
  95. """Return intersection-over-union (Jaccard index) of boxes.
  96. Args:
  97. boxes0 (N, 4): ground truth boxes.
  98. boxes1 (N or 1, 4): predicted boxes.
  99. eps: a small number to avoid 0 as denominator.
  100. Returns:
  101. iou (N): IoU values.
  102. """
  103. overlap_left_top = np.maximum(boxes0[..., :2], boxes1[..., :2])
  104. overlap_right_bottom = np.minimum(boxes0[..., 2:], boxes1[..., 2:])
  105. overlap_area = area_of(overlap_left_top, overlap_right_bottom)
  106. area0 = area_of(boxes0[..., :2], boxes0[..., 2:])
  107. area1 = area_of(boxes1[..., :2], boxes1[..., 2:])
  108. return overlap_area / (area0 + area1 - overlap_area + eps)
  109. def area_of(left_top, right_bottom):
  110. """Compute the areas of rectangles given two corners.
  111. Args:
  112. left_top (N, 2): left top corner.
  113. right_bottom (N, 2): right bottom corner.
  114. Returns:
  115. area (N): return the area.
  116. """
  117. hw = np.clip(right_bottom - left_top, 0.0, None)
  118. return hw[..., 0] * hw[..., 1]
  119. class PicoDetNMS(object):
  120. """
  121. Args:
  122. input_shape (int): network input image size
  123. scale_factor (float): scale factor of ori image
  124. """
  125. def __init__(self,
  126. input_shape,
  127. scale_x,
  128. scale_y,
  129. strides=[8, 16, 32, 64],
  130. score_threshold=0.4,
  131. nms_threshold=0.5,
  132. nms_top_k=1000,
  133. keep_top_k=100):
  134. self.input_shape = input_shape
  135. self.scale_x = scale_x
  136. self.scale_y = scale_y
  137. self.strides = strides
  138. self.score_threshold = score_threshold
  139. self.nms_threshold = nms_threshold
  140. self.nms_top_k = nms_top_k
  141. self.keep_top_k = keep_top_k
  142. def __call__(self, decode_boxes, select_scores):
  143. batch_size = 1
  144. out_boxes_list = []
  145. for batch_id in range(batch_size):
  146. # nms
  147. bboxes = np.concatenate(decode_boxes, axis=0)
  148. confidences = np.concatenate(select_scores, axis=0)
  149. picked_box_probs = []
  150. picked_labels = []
  151. for class_index in range(0, confidences.shape[1]):
  152. probs = confidences[:, class_index]
  153. mask = probs > self.score_threshold
  154. probs = probs[mask]
  155. if probs.shape[0] == 0:
  156. continue
  157. subset_boxes = bboxes[mask, :]
  158. box_probs = np.concatenate(
  159. [subset_boxes, probs.reshape(-1, 1)], axis=1)
  160. box_probs = hard_nms(
  161. box_probs,
  162. iou_threshold=self.nms_threshold,
  163. top_k=self.keep_top_k, )
  164. picked_box_probs.append(box_probs)
  165. picked_labels.extend([class_index] * box_probs.shape[0])
  166. if len(picked_box_probs) == 0:
  167. out_boxes_list.append(np.empty((0, 4)))
  168. else:
  169. picked_box_probs = np.concatenate(picked_box_probs)
  170. # resize output boxes
  171. picked_box_probs[:, 0] *= self.scale_x
  172. picked_box_probs[:, 2] *= self.scale_x
  173. picked_box_probs[:, 1] *= self.scale_y
  174. picked_box_probs[:, 3] *= self.scale_y
  175. # clas score box
  176. out_boxes_list.append(
  177. np.concatenate(
  178. [
  179. np.expand_dims(
  180. np.array(picked_labels),
  181. axis=-1), np.expand_dims(
  182. picked_box_probs[:, 4], axis=-1),
  183. picked_box_probs[:, :4]
  184. ],
  185. axis=1))
  186. out_boxes_list = np.concatenate(out_boxes_list, axis=0)
  187. return out_boxes_list
  188. def detect(img_file, compiled_model, class_label):
  189. output = compiled_model.infer_new_request({0: test_image})
  190. result_ie = list(output.values())
  191. decode_boxes = []
  192. select_scores = []
  193. num_outs = int(len(result_ie) / 2)
  194. for out_idx in range(num_outs):
  195. decode_boxes.append(result_ie[out_idx])
  196. select_scores.append(result_ie[out_idx + num_outs])
  197. image = cv2.imread(img_file, 1)
  198. scale_x = image.shape[1] / test_image.shape[3]
  199. scale_y = image.shape[0] / test_image.shape[2]
  200. nms = PicoDetNMS(test_image.shape[2:], scale_x, scale_y)
  201. np_boxes = nms(decode_boxes, select_scores)
  202. res_image = draw_box(image, np_boxes, class_label)
  203. cv2.imwrite('res.jpg', res_image)
  204. cv2.imshow("res", res_image)
  205. cv2.waitKey()
  206. if __name__ == '__main__':
  207. parser = argparse.ArgumentParser()
  208. parser.add_argument(
  209. '--img_path',
  210. type=str,
  211. default='../../demo_onnxruntime/imgs/bus.jpg',
  212. help="image path")
  213. parser.add_argument(
  214. '--onnx_path',
  215. type=str,
  216. default='out_onnxsim_infer/picodet_s_320_postproccesed_woNMS.onnx',
  217. help="onnx filepath")
  218. parser.add_argument('--in_shape', type=int, default=320, help="input_size")
  219. parser.add_argument(
  220. '--class_label',
  221. type=str,
  222. default='coco_label.txt',
  223. help="class label file")
  224. args = parser.parse_args()
  225. ie = Core()
  226. net = ie.read_model(args.onnx_path)
  227. test_image = image_preprocess(args.img_path, args.in_shape)
  228. compiled_model = ie.compile_model(net, 'CPU')
  229. detect(args.img_path, compiled_model, args.class_label)