落水人员检测
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
9.2KB

  1. import os
  2. import urllib
  3. import traceback
  4. import time
  5. import sys
  6. import numpy as np
  7. import cv2
  8. from rknn.api import RKNN
  9. ONNX_MODEL = 'drp.onnx'
  10. RKNN_MODEL = 'drp.rknn'
  11. IMG_PATH = './images'
  12. DATASET = './dataset.txt'
  13. QUANTIZE_ON = True
  14. OBJ_THRESH = 0.25
  15. NMS_THRESH = 0.45
  16. IMG_SIZE = 640
  17. CLASSES = ("Crack","Cossorion","Exposedrebar","Spall","Efflorescence")
  18. def sigmoid(x):
  19. return 1 / (1 + np.exp(-x))
  20. def xywh2xyxy(x):
  21. # Convert [x, y, w, h] to [x1, y1, x2, y2]
  22. y = np.copy(x)
  23. y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
  24. y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
  25. y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
  26. y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
  27. return y
  28. def process(input, mask, anchors):
  29. anchors = [anchors[i] for i in mask]
  30. grid_h, grid_w = map(int, input.shape[0:2])
  31. box_confidence = sigmoid(input[..., 4])
  32. box_confidence = np.expand_dims(box_confidence, axis=-1)
  33. box_class_probs = sigmoid(input[..., 5:])
  34. box_xy = sigmoid(input[..., :2])*2 - 0.5
  35. col = np.tile(np.arange(0, grid_w), grid_w).reshape(-1, grid_w)
  36. row = np.tile(np.arange(0, grid_h).reshape(-1, 1), grid_h)
  37. col = col.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2)
  38. row = row.reshape(grid_h, grid_w, 1, 1).repeat(3, axis=-2)
  39. grid = np.concatenate((col, row), axis=-1)
  40. box_xy += grid
  41. box_xy *= int(IMG_SIZE/grid_h)
  42. box_wh = pow(sigmoid(input[..., 2:4])*2, 2)
  43. box_wh = box_wh * anchors
  44. box = np.concatenate((box_xy, box_wh), axis=-1)
  45. return box, box_confidence, box_class_probs
  46. def filter_boxes(boxes, box_confidences, box_class_probs):
  47. """Filter boxes with box threshold. It's a bit different with origin yolov5 post process!
  48. # Arguments
  49. boxes: ndarray, boxes of objects.
  50. box_confidences: ndarray, confidences of objects.
  51. box_class_probs: ndarray, class_probs of objects.
  52. # Returns
  53. boxes: ndarray, filtered boxes.
  54. classes: ndarray, classes for boxes.
  55. scores: ndarray, scores for boxes.
  56. """
  57. boxes = boxes.reshape(-1, 4)
  58. box_confidences = box_confidences.reshape(-1)
  59. box_class_probs = box_class_probs.reshape(-1, box_class_probs.shape[-1])
  60. _box_pos = np.where(box_confidences >= OBJ_THRESH)
  61. boxes = boxes[_box_pos]
  62. box_confidences = box_confidences[_box_pos]
  63. box_class_probs = box_class_probs[_box_pos]
  64. class_max_score = np.max(box_class_probs, axis=-1)
  65. classes = np.argmax(box_class_probs, axis=-1)
  66. _class_pos = np.where(class_max_score >= OBJ_THRESH)
  67. boxes = boxes[_class_pos]
  68. classes = classes[_class_pos]
  69. scores = (class_max_score* box_confidences)[_class_pos]
  70. return boxes, classes, scores
  71. def nms_boxes(boxes, scores):
  72. """Suppress non-maximal boxes.
  73. # Arguments
  74. boxes: ndarray, boxes of objects.
  75. scores: ndarray, scores of objects.
  76. # Returns
  77. keep: ndarray, index of effective boxes.
  78. """
  79. x = boxes[:, 0]
  80. y = boxes[:, 1]
  81. w = boxes[:, 2] - boxes[:, 0]
  82. h = boxes[:, 3] - boxes[:, 1]
  83. areas = w * h
  84. order = scores.argsort()[::-1]
  85. keep = []
  86. while order.size > 0:
  87. i = order[0]
  88. keep.append(i)
  89. xx1 = np.maximum(x[i], x[order[1:]])
  90. yy1 = np.maximum(y[i], y[order[1:]])
  91. xx2 = np.minimum(x[i] + w[i], x[order[1:]] + w[order[1:]])
  92. yy2 = np.minimum(y[i] + h[i], y[order[1:]] + h[order[1:]])
  93. w1 = np.maximum(0.0, xx2 - xx1 + 0.00001)
  94. h1 = np.maximum(0.0, yy2 - yy1 + 0.00001)
  95. inter = w1 * h1
  96. ovr = inter / (areas[i] + areas[order[1:]] - inter)
  97. inds = np.where(ovr <= NMS_THRESH)[0]
  98. order = order[inds + 1]
  99. keep = np.array(keep)
  100. return keep
  101. def yolov5_post_process(input_data):
  102. masks = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
  103. anchors = [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
  104. [59, 119], [116, 90], [156, 198], [373, 326]]
  105. boxes, classes, scores = [], [], []
  106. for input, mask in zip(input_data, masks):
  107. b, c, s = process(input, mask, anchors)
  108. b, c, s = filter_boxes(b, c, s)
  109. boxes.append(b)
  110. classes.append(c)
  111. scores.append(s)
  112. boxes = np.concatenate(boxes)
  113. boxes = xywh2xyxy(boxes)
  114. classes = np.concatenate(classes)
  115. scores = np.concatenate(scores)
  116. nboxes, nclasses, nscores = [], [], []
  117. for c in set(classes):
  118. inds = np.where(classes == c)
  119. b = boxes[inds]
  120. c = classes[inds]
  121. s = scores[inds]
  122. keep = nms_boxes(b, s)
  123. nboxes.append(b[keep])
  124. nclasses.append(c[keep])
  125. nscores.append(s[keep])
  126. if not nclasses and not nscores:
  127. return None, None, None
  128. boxes = np.concatenate(nboxes)
  129. classes = np.concatenate(nclasses)
  130. scores = np.concatenate(nscores)
  131. return boxes, classes, scores
  132. def draw(image, boxes, scores, classes):
  133. """Draw the boxes on the image.
  134. # Argument:
  135. image: original image.
  136. boxes: ndarray, boxes of objects.
  137. classes: ndarray, classes of objects.
  138. scores: ndarray, scores of objects.
  139. all_classes: all classes name.
  140. """
  141. for box, score, cl in zip(boxes, scores, classes):
  142. top, left, right, bottom = box
  143. print('class: {}, score: {}'.format(CLASSES[cl], score))
  144. print('box coordinate left,top,right,down: [{}, {}, {}, {}]'.format(top, left, right, bottom))
  145. top = int(top)
  146. left = int(left)
  147. right = int(right)
  148. bottom = int(bottom)
  149. cv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 2)
  150. cv2.putText(image, '{0} {1:.2f}'.format(CLASSES[cl], score),
  151. (top, left - 6),
  152. cv2.FONT_HERSHEY_SIMPLEX,
  153. 0.6, (0, 0, 255), 2)
  154. def letterbox(im, new_shape=(640, 640), color=(0, 0, 0)):
  155. # Resize and pad image while meeting stride-multiple constraints
  156. shape = im.shape[:2] # current shape [height, width]
  157. if isinstance(new_shape, int):
  158. new_shape = (new_shape, new_shape)
  159. # Scale ratio (new / old)
  160. r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
  161. # Compute padding
  162. ratio = r, r # width, height ratios
  163. new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
  164. dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
  165. dw /= 2 # divide padding into 2 sides
  166. dh /= 2
  167. if shape[::-1] != new_unpad: # resize
  168. im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
  169. top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
  170. left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
  171. im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
  172. return im, ratio, (dw, dh)
  173. if __name__ == '__main__':
  174. # Create RKNN object
  175. rknn = RKNN(verbose=True)
  176. # pre-process config
  177. print('--> Config model')
  178. rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]])
  179. print('done')
  180. # Load ONNX model
  181. print('--> Loading model')
  182. ret = rknn.load_onnx(model=ONNX_MODEL)
  183. if ret != 0:
  184. print('Load model failed!')
  185. exit(ret)
  186. print('done')
  187. # Build model
  188. print('--> Building model')
  189. ret = rknn.build(do_quantization=False, dataset=DATASET)
  190. if ret != 0:
  191. print('Build model failed!')
  192. exit(ret)
  193. print('done')
  194. # Export RKNN model
  195. print('--> Export rknn model')
  196. ret = rknn.export_rknn(RKNN_MODEL)
  197. if ret != 0:
  198. print('Export rknn model failed!')
  199. exit(ret)
  200. print('done')
  201. # Init runtime environment
  202. print('--> Init runtime environment')
  203. ret = rknn.init_runtime()
  204. # ret = rknn.init_runtime('rk3566')
  205. if ret != 0:
  206. print('Init runtime environment failed!')
  207. exit(ret)
  208. print('done')
  209. folders = os.listdir(IMG_PATH)
  210. for i in range(len(folders)):
  211. path1 = IMG_PATH+ '/' + folders[i]
  212. # Set inputs
  213. img = cv2.imread(path1)
  214. # img, ratio, (dw, dh) = letterbox(img, new_shape=(IMG_SIZE, IMG_SIZE))
  215. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  216. img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
  217. # Inference
  218. print('--> Running model')
  219. outputs = rknn.inference(inputs=[img])
  220. # np.save('./onnx_yolov5_0.npy', outputs[0])
  221. # np.save('./onnx_yolov5_1.npy', outputs[1])
  222. # np.save('./onnx_yolov5_2.npy', outputs[2])
  223. # print('done')
  224. # post process
  225. input0_data = outputs[0]
  226. input1_data = outputs[1]
  227. input2_data = outputs[2]
  228. input0_data = input0_data.reshape([3, -1]+list(input0_data.shape[-2:]))
  229. input1_data = input1_data.reshape([3, -1]+list(input1_data.shape[-2:]))
  230. input2_data = input2_data.reshape([3, -1]+list(input2_data.shape[-2:]))
  231. input_data = list()
  232. input_data.append(np.transpose(input0_data, (2, 3, 0, 1)))
  233. input_data.append(np.transpose(input1_data, (2, 3, 0, 1)))
  234. input_data.append(np.transpose(input2_data, (2, 3, 0, 1)))
  235. boxes, classes, scores = yolov5_post_process(input_data)
  236. img_1 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
  237. if boxes is not None:
  238. draw(img_1, boxes, scores, classes)
  239. cv2.imwrite('result'+str(i)+'.jpg', img_1)
  240. rknn.release()