post_process.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import numpy as np
  2. import cv2
  3. from PIL import Image
  4. from keras import backend as K
  5. import tensorflow as tf
  6. def return_seal_part(image_seal_list, num=3):
  7. image_part_list = []
  8. for image_part, image_seal, position in image_seal_list:
  9. if image_seal is None:
  10. image_part_list.append(image_part)
  11. continue
  12. y_min, y_max, x_min, x_max = position
  13. image_part[y_min:y_max, x_min:x_max, :] = image_seal
  14. image_part_list.append(image_part)
  15. # 先将宽的部分拼接
  16. image_width_list = []
  17. for i in range(0, len(image_part_list), num):
  18. image_width = np.concatenate([image_part_list[i], image_part_list[i + 1], image_part_list[i + 2]], axis=1)
  19. image_width_list.append(image_width)
  20. # 高的部分拼接
  21. image_return = np.concatenate([x for x in image_width_list], axis=0)
  22. print("image_return.shape", image_return.shape)
  23. cv2.namedWindow("image_return", 0)
  24. cv2.resizeWindow("image_return", 1000, 800)
  25. cv2.imshow("image_return", image_return)
  26. cv2.waitKey(0)
  27. return image_return
  28. def yolo_head(feats, anchors, num_classes, input_shape, calc_loss=False):
  29. """Convert final layer features to bounding box parameters."""
  30. num_anchors = len(anchors)
  31. # feats = K.constant(feats)
  32. # Reshape to batch, height, width, num_anchors, box_params.
  33. anchors_tensor = K.reshape(K.constant(anchors), [1, 1, 1, num_anchors, 2])
  34. grid_shape = K.shape(feats)[1:3] # height, width
  35. grid_y = K.tile(K.reshape(K.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]),
  36. [1, grid_shape[1], 1, 1])
  37. grid_x = K.tile(K.reshape(K.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]),
  38. [grid_shape[0], 1, 1, 1])
  39. grid = K.concatenate([grid_x, grid_y])
  40. grid = K.cast(grid, K.dtype(feats))
  41. feats = K.reshape(
  42. feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5])
  43. # Adjust predictions to each spatial grid point and anchor size.
  44. box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[::-1], K.dtype(feats))
  45. box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[::-1], K.dtype(feats))
  46. box_confidence = K.sigmoid(feats[..., 4:5])
  47. box_class_probs = K.sigmoid(feats[..., 5:])
  48. if calc_loss:
  49. return grid, feats, box_xy, box_wh
  50. return box_xy, box_wh, box_confidence, box_class_probs
  51. def yolo_eval(outputs,
  52. anchors,
  53. num_classes,
  54. max_boxes=10,
  55. score_threshold=.1,
  56. iou_threshold=.1):
  57. """Evaluate YOLO model on given input and return filtered boxes."""
  58. # num_layers = len(anchors) // 3
  59. # yolo_outputs = outputs[:num_layers]
  60. # image_shape = outputs[num_layers]
  61. yolo_outputs = outputs[0]
  62. print("yolo_outputs", yolo_outputs[0])
  63. num_layers = len(yolo_outputs)
  64. image_shape = outputs[1]
  65. print("num_layers", num_layers)
  66. print("image_shape", image_shape.shape)
  67. anchor_mask = [[6, 7, 8], [3, 4, 5], [0, 1, 2]] if num_layers == 3 else [[3, 4, 5], [1, 2, 3]] # default setting
  68. input_shape = K.shape(yolo_outputs[0])[1:3] * 32
  69. boxes = []
  70. box_scores = []
  71. for l in range(num_layers):
  72. _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
  73. anchors[anchor_mask[l]],
  74. num_classes, input_shape, image_shape)
  75. boxes.append(_boxes)
  76. box_scores.append(_box_scores)
  77. boxes = K.concatenate(boxes, axis=0)
  78. box_scores = K.concatenate(box_scores, axis=0)
  79. mask = box_scores >= score_threshold
  80. max_boxes_tensor = K.constant(max_boxes, dtype='int32')
  81. boxes_ = []
  82. scores_ = []
  83. classes_ = []
  84. for c in range(num_classes):
  85. # TODO: use keras backend instead of tf.
  86. class_boxes = tf.boolean_mask(boxes, mask[:, c])
  87. class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])
  88. nms_index = tf.image.non_max_suppression(
  89. class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)
  90. class_boxes = K.gather(class_boxes, nms_index)
  91. class_box_scores = K.gather(class_box_scores, nms_index)
  92. classes = K.ones_like(class_box_scores, 'int32') * c
  93. boxes_.append(class_boxes)
  94. scores_.append(class_box_scores)
  95. classes_.append(classes)
  96. boxes_ = K.concatenate(boxes_, axis=0)
  97. scores_ = K.concatenate(scores_, axis=0)
  98. classes_ = K.concatenate(classes_, axis=0)
  99. return boxes_, scores_, classes_
  100. def letterbox_image(image, size):
  101. '''resize image with unchanged aspect ratio using padding'''
  102. iw, ih = image.size
  103. w, h = size
  104. scale = min(w/iw, h/ih)
  105. nw = int(iw*scale)
  106. nh = int(ih*scale)
  107. image = image.resize((nw,nh), Image.BICUBIC)
  108. new_image = Image.new('RGB', size, (128,128,128))
  109. new_image.paste(image, ((w-nw)//2, (h-nh)//2))
  110. return new_image
  111. def yolo_eval_new(yolo_outputs,
  112. anchors,
  113. num_classes,
  114. image_shape,
  115. max_boxes=20,
  116. score_threshold=.6,
  117. iou_threshold=.5):
  118. """Evaluate YOLO model on given input and return filtered boxes."""
  119. num_layers = len(yolo_outputs)
  120. anchor_mask = [[6,7,8], [3,4,5], [0,1,2]] if num_layers==3 else [[3,4,5], [1,2,3]] # default setting
  121. input_shape = K.shape(yolo_outputs[0])[1:3] * 32
  122. boxes = []
  123. box_scores = []
  124. for l in range(num_layers):
  125. _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
  126. anchors[anchor_mask[l]], num_classes, input_shape, image_shape)
  127. boxes.append(_boxes)
  128. box_scores.append(_box_scores)
  129. boxes = K.concatenate(boxes, axis=0)
  130. box_scores = K.concatenate(box_scores, axis=0)
  131. mask = box_scores >= score_threshold
  132. max_boxes_tensor = K.constant(max_boxes, dtype='int32')
  133. boxes_ = []
  134. scores_ = []
  135. classes_ = []
  136. for c in range(num_classes):
  137. # TODO: use keras backend instead of tf.
  138. class_boxes = tf.boolean_mask(boxes, mask[:, c])
  139. class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])
  140. nms_index = tf.image.non_max_suppression(
  141. class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)
  142. class_boxes = K.gather(class_boxes, nms_index)
  143. class_box_scores = K.gather(class_box_scores, nms_index)
  144. classes = K.ones_like(class_box_scores, 'int32') * c
  145. boxes_.append(class_boxes)
  146. scores_.append(class_box_scores)
  147. classes_.append(classes)
  148. boxes_ = K.concatenate(boxes_, axis=0)
  149. scores_ = K.concatenate(scores_, axis=0)
  150. classes_ = K.concatenate(classes_, axis=0)
  151. return boxes_, scores_, classes_
  152. def yolo_boxes_and_scores(feats, anchors, num_classes, input_shape, image_shape):
  153. """Process Conv layer output"""
  154. box_xy, box_wh, box_confidence, box_class_probs = yolo_head(feats,
  155. anchors, num_classes, input_shape)
  156. boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape)
  157. boxes = K.reshape(boxes, [-1, 4])
  158. box_scores = box_confidence * box_class_probs
  159. box_scores = K.reshape(box_scores, [-1, num_classes])
  160. return boxes, box_scores
  161. def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape):
  162. """Get corrected boxes"""
  163. box_yx = box_xy[..., ::-1]
  164. box_hw = box_wh[..., ::-1]
  165. input_shape = K.cast(input_shape, K.dtype(box_yx))
  166. image_shape = K.cast(image_shape, K.dtype(box_yx))
  167. new_shape = K.round(image_shape * K.min(input_shape/image_shape))
  168. offset = (input_shape-new_shape)/2./input_shape
  169. scale = input_shape/new_shape
  170. box_yx = (box_yx - offset) * scale
  171. box_hw *= scale
  172. box_mins = box_yx - (box_hw / 2.)
  173. box_maxes = box_yx + (box_hw / 2.)
  174. boxes = K.concatenate([
  175. box_mins[..., 0:1], # y_min
  176. box_mins[..., 1:2], # x_min
  177. box_maxes[..., 0:1], # y_max
  178. box_maxes[..., 1:2] # x_max
  179. ])
  180. # Scale boxes back to original image shape.
  181. boxes *= K.concatenate([image_shape, image_shape])
  182. return boxes