123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import numpy as np
- import cv2
- from PIL import Image
- from keras import backend as K
- import tensorflow as tf
- def return_seal_part(image_seal_list, num=3):
- image_part_list = []
- for image_part, image_seal, position in image_seal_list:
- if image_seal is None:
- image_part_list.append(image_part)
- continue
- y_min, y_max, x_min, x_max = position
- image_part[y_min:y_max, x_min:x_max, :] = image_seal
- image_part_list.append(image_part)
- # 先将宽的部分拼接
- image_width_list = []
- for i in range(0, len(image_part_list), num):
- image_width = np.concatenate([image_part_list[i], image_part_list[i + 1], image_part_list[i + 2]], axis=1)
- image_width_list.append(image_width)
- # 高的部分拼接
- image_return = np.concatenate([x for x in image_width_list], axis=0)
- print("image_return.shape", image_return.shape)
- cv2.namedWindow("image_return", 0)
- cv2.resizeWindow("image_return", 1000, 800)
- cv2.imshow("image_return", image_return)
- cv2.waitKey(0)
- return image_return
- def yolo_head(feats, anchors, num_classes, input_shape, calc_loss=False):
- """Convert final layer features to bounding box parameters."""
- num_anchors = len(anchors)
- # feats = K.constant(feats)
- # Reshape to batch, height, width, num_anchors, box_params.
- anchors_tensor = K.reshape(K.constant(anchors), [1, 1, 1, num_anchors, 2])
- grid_shape = K.shape(feats)[1:3] # height, width
- grid_y = K.tile(K.reshape(K.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]),
- [1, grid_shape[1], 1, 1])
- grid_x = K.tile(K.reshape(K.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]),
- [grid_shape[0], 1, 1, 1])
- grid = K.concatenate([grid_x, grid_y])
- grid = K.cast(grid, K.dtype(feats))
- feats = K.reshape(
- feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5])
- # Adjust predictions to each spatial grid point and anchor size.
- box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[::-1], K.dtype(feats))
- box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[::-1], K.dtype(feats))
- box_confidence = K.sigmoid(feats[..., 4:5])
- box_class_probs = K.sigmoid(feats[..., 5:])
- if calc_loss:
- return grid, feats, box_xy, box_wh
- return box_xy, box_wh, box_confidence, box_class_probs
- def yolo_eval(outputs,
- anchors,
- num_classes,
- max_boxes=10,
- score_threshold=.1,
- iou_threshold=.1):
- """Evaluate YOLO model on given input and return filtered boxes."""
- # num_layers = len(anchors) // 3
- # yolo_outputs = outputs[:num_layers]
- # image_shape = outputs[num_layers]
- yolo_outputs = outputs[0]
- print("yolo_outputs", yolo_outputs[0])
- num_layers = len(yolo_outputs)
- image_shape = outputs[1]
- print("num_layers", num_layers)
- print("image_shape", image_shape.shape)
- anchor_mask = [[6, 7, 8], [3, 4, 5], [0, 1, 2]] if num_layers == 3 else [[3, 4, 5], [1, 2, 3]] # default setting
- input_shape = K.shape(yolo_outputs[0])[1:3] * 32
- boxes = []
- box_scores = []
- for l in range(num_layers):
- _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
- anchors[anchor_mask[l]],
- num_classes, input_shape, image_shape)
- boxes.append(_boxes)
- box_scores.append(_box_scores)
- boxes = K.concatenate(boxes, axis=0)
- box_scores = K.concatenate(box_scores, axis=0)
- mask = box_scores >= score_threshold
- max_boxes_tensor = K.constant(max_boxes, dtype='int32')
- boxes_ = []
- scores_ = []
- classes_ = []
- for c in range(num_classes):
- # TODO: use keras backend instead of tf.
- class_boxes = tf.boolean_mask(boxes, mask[:, c])
- class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])
- nms_index = tf.image.non_max_suppression(
- class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)
- class_boxes = K.gather(class_boxes, nms_index)
- class_box_scores = K.gather(class_box_scores, nms_index)
- classes = K.ones_like(class_box_scores, 'int32') * c
- boxes_.append(class_boxes)
- scores_.append(class_box_scores)
- classes_.append(classes)
- boxes_ = K.concatenate(boxes_, axis=0)
- scores_ = K.concatenate(scores_, axis=0)
- classes_ = K.concatenate(classes_, axis=0)
- return boxes_, scores_, classes_
- def letterbox_image(image, size):
- '''resize image with unchanged aspect ratio using padding'''
- iw, ih = image.size
- w, h = size
- scale = min(w/iw, h/ih)
- nw = int(iw*scale)
- nh = int(ih*scale)
- image = image.resize((nw,nh), Image.BICUBIC)
- new_image = Image.new('RGB', size, (128,128,128))
- new_image.paste(image, ((w-nw)//2, (h-nh)//2))
- return new_image
- def yolo_eval_new(yolo_outputs,
- anchors,
- num_classes,
- image_shape,
- max_boxes=20,
- score_threshold=.6,
- iou_threshold=.5):
- """Evaluate YOLO model on given input and return filtered boxes."""
- num_layers = len(yolo_outputs)
- anchor_mask = [[6,7,8], [3,4,5], [0,1,2]] if num_layers==3 else [[3,4,5], [1,2,3]] # default setting
- input_shape = K.shape(yolo_outputs[0])[1:3] * 32
- boxes = []
- box_scores = []
- for l in range(num_layers):
- _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
- anchors[anchor_mask[l]], num_classes, input_shape, image_shape)
- boxes.append(_boxes)
- box_scores.append(_box_scores)
- boxes = K.concatenate(boxes, axis=0)
- box_scores = K.concatenate(box_scores, axis=0)
- mask = box_scores >= score_threshold
- max_boxes_tensor = K.constant(max_boxes, dtype='int32')
- boxes_ = []
- scores_ = []
- classes_ = []
- for c in range(num_classes):
- # TODO: use keras backend instead of tf.
- class_boxes = tf.boolean_mask(boxes, mask[:, c])
- class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])
- nms_index = tf.image.non_max_suppression(
- class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)
- class_boxes = K.gather(class_boxes, nms_index)
- class_box_scores = K.gather(class_box_scores, nms_index)
- classes = K.ones_like(class_box_scores, 'int32') * c
- boxes_.append(class_boxes)
- scores_.append(class_box_scores)
- classes_.append(classes)
- boxes_ = K.concatenate(boxes_, axis=0)
- scores_ = K.concatenate(scores_, axis=0)
- classes_ = K.concatenate(classes_, axis=0)
- return boxes_, scores_, classes_
- def yolo_boxes_and_scores(feats, anchors, num_classes, input_shape, image_shape):
- """Process Conv layer output"""
- box_xy, box_wh, box_confidence, box_class_probs = yolo_head(feats,
- anchors, num_classes, input_shape)
- boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape)
- boxes = K.reshape(boxes, [-1, 4])
- box_scores = box_confidence * box_class_probs
- box_scores = K.reshape(box_scores, [-1, num_classes])
- return boxes, box_scores
- def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape):
- """Get corrected boxes"""
- box_yx = box_xy[..., ::-1]
- box_hw = box_wh[..., ::-1]
- input_shape = K.cast(input_shape, K.dtype(box_yx))
- image_shape = K.cast(image_shape, K.dtype(box_yx))
- new_shape = K.round(image_shape * K.min(input_shape/image_shape))
- offset = (input_shape-new_shape)/2./input_shape
- scale = input_shape/new_shape
- box_yx = (box_yx - offset) * scale
- box_hw *= scale
- box_mins = box_yx - (box_hw / 2.)
- box_maxes = box_yx + (box_hw / 2.)
- boxes = K.concatenate([
- box_mins[..., 0:1], # y_min
- box_mins[..., 1:2], # x_min
- box_maxes[..., 0:1], # y_max
- box_maxes[..., 1:2] # x_max
- ])
- # Scale boxes back to original image shape.
- boxes *= K.concatenate([image_shape, image_shape])
- return boxes
|