|
| 1 | +#! /usr/bin/python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +import tensorflow as tf |
| 5 | +import colorsys, random, cv2 |
| 6 | +import numpy as np |
| 7 | + |
| 8 | + |
| 9 | +def decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]): |
| 10 | + batch_size = tf.shape(conv_output)[0] |
| 11 | + conv_output = tf.reshape(conv_output, (batch_size, output_size, output_size, 3, 5 + NUM_CLASS)) |
| 12 | + |
| 13 | + conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), axis=-1) |
| 14 | + |
| 15 | + xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) |
| 16 | + xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2] |
| 17 | + xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [batch_size, 1, 1, 3, 1]) |
| 18 | + |
| 19 | + xy_grid = tf.cast(xy_grid, tf.float32) |
| 20 | + |
| 21 | + pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ |
| 22 | + STRIDES[i] |
| 23 | + pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i]) |
| 24 | + pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) |
| 25 | + |
| 26 | + pred_conf = tf.sigmoid(conv_raw_conf) |
| 27 | + pred_prob = tf.sigmoid(conv_raw_prob) |
| 28 | + |
| 29 | + pred_prob = pred_conf * pred_prob |
| 30 | + pred_prob = tf.reshape(pred_prob, (batch_size, -1, NUM_CLASS)) |
| 31 | + pred_xywh = tf.reshape(pred_xywh, (batch_size, -1, 4)) |
| 32 | + |
| 33 | + return pred_xywh, pred_prob |
| 34 | + |
| 35 | + |
| 36 | +def decode(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE=[1, 1, 1]): |
| 37 | + return decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=i, XYSCALE=XYSCALE) |
| 38 | + |
| 39 | + |
| 40 | +def filter_boxes(box_xywh, scores, score_threshold=0.4, input_shape=tf.constant([416, 416])): |
| 41 | + scores_max = tf.math.reduce_max(scores, axis=-1) |
| 42 | + |
| 43 | + mask = scores_max >= score_threshold |
| 44 | + class_boxes = tf.boolean_mask(box_xywh, mask) |
| 45 | + pred_conf = tf.boolean_mask(scores, mask) |
| 46 | + class_boxes = tf.reshape(class_boxes, [tf.shape(scores)[0], -1, tf.shape(class_boxes)[-1]]) |
| 47 | + pred_conf = tf.reshape(pred_conf, [tf.shape(scores)[0], -1, tf.shape(pred_conf)[-1]]) |
| 48 | + |
| 49 | + box_xy, box_wh = tf.split(class_boxes, (2, 2), axis=-1) |
| 50 | + |
| 51 | + input_shape = tf.cast(input_shape, dtype=tf.float32) |
| 52 | + box_yx = box_xy[..., ::-1] |
| 53 | + box_hw = box_wh[..., ::-1] |
| 54 | + |
| 55 | + box_mins = (box_yx - (box_hw / 2.)) / input_shape |
| 56 | + box_maxes = (box_yx + (box_hw / 2.)) / input_shape |
| 57 | + boxes = tf.concat( |
| 58 | + [ |
| 59 | + box_mins[..., 0:1], # y_min |
| 60 | + box_mins[..., 1:2], # x_min |
| 61 | + box_maxes[..., 0:1], # y_max |
| 62 | + box_maxes[..., 1:2] # x_max |
| 63 | + ], |
| 64 | + axis=-1 |
| 65 | + ) |
| 66 | + # return tf.concat([boxes, pred_conf], axis=-1) |
| 67 | + return (boxes, pred_conf) |
| 68 | + |
| 69 | + |
| 70 | +def read_class_names(class_file_name): |
| 71 | + names = {} |
| 72 | + with open(class_file_name, 'r') as data: |
| 73 | + for ID, name in enumerate(data): |
| 74 | + names[ID] = name.strip('\n') |
| 75 | + return names |
| 76 | + |
| 77 | + |
| 78 | +def draw_bbox(image, bboxes, show_label=True): |
| 79 | + classes = read_class_names('model/coco.names') |
| 80 | + num_classes = len(classes) |
| 81 | + image_h, image_w, _ = image.shape |
| 82 | + hsv_tuples = [(1.0 * x / num_classes, 1., 1.) for x in range(num_classes)] |
| 83 | + colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) |
| 84 | + colors = list(map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) |
| 85 | + |
| 86 | + random.seed(0) |
| 87 | + random.shuffle(colors) |
| 88 | + random.seed(None) |
| 89 | + |
| 90 | + out_boxes, out_scores, out_classes, num_boxes = bboxes |
| 91 | + for i in range(num_boxes[0]): |
| 92 | + if int(out_classes[0][i]) < 0 or int(out_classes[0][i]) > num_classes: continue |
| 93 | + coor = out_boxes[0][i] |
| 94 | + coor[0] = int(coor[0] * image_h) |
| 95 | + coor[2] = int(coor[2] * image_h) |
| 96 | + coor[1] = int(coor[1] * image_w) |
| 97 | + coor[3] = int(coor[3] * image_w) |
| 98 | + |
| 99 | + fontScale = 0.5 |
| 100 | + score = out_scores[0][i] |
| 101 | + class_ind = int(out_classes[0][i]) |
| 102 | + bbox_color = colors[class_ind] |
| 103 | + bbox_thick = int(0.6 * (image_h + image_w) / 600) |
| 104 | + c1, c2 = (coor[1], coor[0]), (coor[3], coor[2]) |
| 105 | + cv2.rectangle(image, c1, c2, bbox_color, bbox_thick) |
| 106 | + |
| 107 | + if show_label: |
| 108 | + bbox_mess = '%s: %.2f' % (classes[class_ind], score) |
| 109 | + t_size = cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2)[0] |
| 110 | + c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3) |
| 111 | + cv2.rectangle(image, c1, (np.float32(c3[0]), np.float32(c3[1])), bbox_color, -1) #filled |
| 112 | + |
| 113 | + cv2.putText( |
| 114 | + image, bbox_mess, (c1[0], np.float32(c1[1] - 2)), cv2.FONT_HERSHEY_SIMPLEX, fontScale, (0, 0, 0), |
| 115 | + bbox_thick // 2, lineType=cv2.LINE_AA |
| 116 | + ) |
| 117 | + return image |
| 118 | + |
| 119 | + |
| 120 | +def get_anchors(anchors_path, tiny=False): |
| 121 | + anchors = np.array(anchors_path) |
| 122 | + if tiny: |
| 123 | + return anchors.reshape(2, 3, 2) |
| 124 | + else: |
| 125 | + return anchors.reshape(3, 3, 2) |
| 126 | + |
| 127 | + |
| 128 | +def decode_train(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]): |
| 129 | + conv_output = tf.reshape(conv_output, (tf.shape(conv_output)[0], output_size, output_size, 3, 5 + NUM_CLASS)) |
| 130 | + |
| 131 | + conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), axis=-1) |
| 132 | + |
| 133 | + xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size)) |
| 134 | + xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2] |
| 135 | + xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [tf.shape(conv_output)[0], 1, 1, 3, 1]) |
| 136 | + |
| 137 | + xy_grid = tf.cast(xy_grid, tf.float32) |
| 138 | + |
| 139 | + pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \ |
| 140 | + STRIDES[i] |
| 141 | + pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i]) |
| 142 | + pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1) |
| 143 | + |
| 144 | + pred_conf = tf.sigmoid(conv_raw_conf) |
| 145 | + pred_prob = tf.sigmoid(conv_raw_prob) |
| 146 | + |
| 147 | + return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1) |
| 148 | + |
| 149 | + |
| 150 | +# def weights_sorted(): |
| 151 | +# # download weights |
| 152 | +# maybe_download_and_extract( |
| 153 | +# 'yolov4.npz', |
| 154 | +# model_path, |
| 155 | +# 'https://github.com/', |
| 156 | +# ) # ls -al |
| 157 | +# weights = [] |
| 158 | +# track_weights = [] |
| 159 | +# weights_dict = {} |
| 160 | +# |
| 161 | +# npz = np.load(model_path, allow_pickle=True) |
| 162 | +# # get weight list |
| 163 | +# for val in sorted(npz.items()): |
| 164 | +# logging.info(" Loading weights %s in %s" % (str(val[1].shape), val[0])) |
| 165 | +# try: |
| 166 | +# weights.append(int(val[0].split('/')[0].split('-')[-1])) |
| 167 | +# track_weights.append(val[0]) |
| 168 | +# except: |
| 169 | +# pass |
| 170 | +# zip_weights = zip(weights, track_weights) |
| 171 | +# zip_weights = sorted(zip_weights) |
| 172 | +# for value, key in zip_weights: |
| 173 | +# print(key) |
0 commit comments