def run(self, netout): anchors = [ 0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, 9.77052, 9.16828 ] nms_threshold = 0.2 """Convert Yolo network output to bounding box # Args netout : 4d-array, shape of (grid_h, grid_w, num of boxes per grid, 5 + n_classes) YOLO neural network output array # Returns boxes : array, shape of (N, 4) coordinate scale is normalized [0, 1] probs : array, shape of (N, nb_classes) """ grid_h, grid_w, nb_box = netout.shape[:3] boxes = [] # decode the output by the network netout[..., 4] = _sigmoid(netout[..., 4]) netout[..., 5:] = netout[..., 4][..., np.newaxis] * _softmax( netout[..., 5:]) netout[..., 5:] *= netout[..., 5:] > self._threshold for row in range(grid_h): for col in range(grid_w): for b in range(nb_box): # from 4th element onwards are confidence and class classes classes = netout[row, col, b, 5:] if np.sum(classes) > 0: # first 4 elements are x, y, w, and h x, y, w, h = netout[row, col, b, :4] x = (col + _sigmoid(x) ) / grid_w # center position, unit: image width y = (row + _sigmoid(y) ) / grid_h # center position, unit: image height w = anchors[2 * b + 0] * np.exp( w) / grid_w # unit: image width h = anchors[2 * b + 1] * np.exp( h) / grid_h # unit: image height confidence = netout[row, col, b, 4] box = BoundBox(x, y, w, h, confidence, classes) boxes.append(box) boxes = nms_boxes(boxes, len(classes), nms_threshold, self._threshold) boxes, probs = boxes_to_array(boxes) return boxes, probs
def decode_netout(netout, anchors, obj_thresh, net_h, net_w): grid_h, grid_w = netout.shape[:2] nb_box = 3 netout = netout.reshape((grid_h, grid_w, nb_box, -1)) nb_class = netout.shape[-1] - 5 boxes = [] netout[..., :2] = _sigmoid(netout[..., :2]) netout[..., 4:] = _sigmoid(netout[..., 4:]) netout[..., 5:] = netout[..., 4][..., np.newaxis] * netout[..., 5:] netout[..., 5:] *= netout[..., 5:] > obj_thresh for i in range(grid_h * grid_w): row = i // grid_w col = i % grid_w for b in range(nb_box): # 4th element is objectness score objectness = netout[row, col, b, 4] if (objectness <= obj_thresh): continue # first 4 elements are x, y, w, and h x, y, w, h = netout[row, col, b, :4] x = (col + x) / grid_w # center position, unit: image width y = (row + y) / grid_h # center position, unit: image height w = anchors[2 * b + 0] * np.exp(w) / net_w # unit: image width h = anchors[2 * b + 1] * np.exp(h) / net_h # unit: image height # last elements are class probabilities classes = netout[row, col, b, 5:] box = BoundBox(x - w / 2, y - h / 2, x + w / 2, y + h / 2, objectness, classes) boxes.append(box) return boxes
def NMS(final_probs, final_bbox): boxes = list() indices = set() #np.intp_t pred_length,class_length,class_loop,index,index2 pred_length = final_bbox.shape[0] class_length = final_probs.shape[1] for class_loop in range(class_length): for index in range(pred_length): if final_probs[index, class_loop] == 0: continue for index2 in range(index + 1, pred_length): if final_probs[index2, class_loop] == 0: continue if index == index2: continue if box_iou_c(final_bbox[index, 0], final_bbox[index, 1], final_bbox[index, 2], final_bbox[index, 3], final_bbox[index2, 0], final_bbox[index2, 1], final_bbox[index2, 2], final_bbox[index2, 3]) >= 0.4: if final_probs[index2, class_loop] > final_probs[index, class_loop]: final_probs[index, class_loop] = 0 break final_probs[index2, class_loop] = 0 if index not in indices: bb = BoundBox(class_length) bb.x = final_bbox[index, 0] bb.y = final_bbox[index, 1] bb.w = final_bbox[index, 2] bb.h = final_bbox[index, 3] bb.c = final_bbox[index, 4] bb.probs = np.asarray(final_probs[index, :]) boxes.append(bb) indices.add(index) return boxes
def decode_netout(netout, anchors, obj_thresh, net_size, nb_box=3): n_rows, n_cols = netout.shape[:2] netout = netout.reshape((n_rows, n_cols, nb_box, -1)) boxes = [] for row in range(n_rows): for col in range(n_cols): for b in range(nb_box): x, y, w, h = _decode_coords(netout, row, col, b, anchors) objectness, classes = _activate_probs(netout[row, col, b, 4], netout[row, col, b, 5:], obj_thresh) x /= n_cols y /= n_rows w /= net_size h /= net_size if objectness > obj_thresh: box = BoundBox(x, y, w, h, objectness, classes) boxes.append(box) return boxes
def postprocess(meta, net_out, imgcv, annotate=False): ''' citation: https://github.com/thtrieu/darkflow/blob/99f9a95468f9bd858d610530524f83612bf635eb/net/yolov2/test.py meta: meta data net_out:output from the CNN imgcv: original image array annotate: anntoate bounding box to the image or not ''' # meta meta = meta H, W, _ = meta['out_size'] threshold = meta['thresh'] C, B = meta['classes'], meta['num'] anchors = meta['anchors'] net_out = net_out.reshape([H, W, B, -1]) boxes = list() for row in range(H): for col in range(W): for b in range(B): bx = BoundBox(C) bx.x, bx.y, bx.w, bx.h, bx.c = net_out[row, col, b, :5] bx.c = expit(bx.c) bx.x = (col + expit(bx.x)) / W bx.y = (row + expit(bx.y)) / H bx.w = math.exp(bx.w) * anchors[2 * b + 0] / W bx.h = math.exp(bx.h) * anchors[2 * b + 1] / H classes = net_out[row, col, b, 5:] bx.probs = _softmax(classes) * bx.c bx.probs *= bx.probs > threshold boxes.append(bx) # non max suppress boxes for c in range(C): for i in range(len(boxes)): boxes[i].class_num = c boxes = sorted(boxes, key=prob_compare, reverse=True) for i in range(len(boxes)): boxi = boxes[i] if boxi.probs[c] == 0: continue for j in range(i + 1, len(boxes)): boxj = boxes[j] if box_iou(boxi, boxj) >= .4: boxes[j].probs[c] = 0. colors = meta['colors'] labels = meta['labels'] h, w, _ = imgcv.shape outboxes = [] for b in boxes: max_indx = np.argmax(b.probs) max_prob = b.probs[max_indx] label = labels[max_indx] # print(max_prob) if max_prob > threshold: left = int(round((b.x - b.w / 2.) * w)) right = int(round((b.x + b.w / 2.) * w)) top = int(round((b.y - b.h / 2.) * h)) bot = int(round((b.y + b.h / 2.) * h)) if left < 0: left = 0 if right > w - 1: right = w - 1 if top < 0: top = 0 if bot > h - 1: bot = h - 1 x_box = left y_box = top w_box = right - left h_box = bot - top #print({"x":x_box,"y":y_box,"w":w_box,"h":h_box,"conf":max_prob}) outboxes.append({ "x": x_box, "y": y_box, "w": w_box, "h": h_box, "conf": float(max_prob) }) if annotate: thick = int((h + w) / 300) mess = '%03.3f' % max_prob cv2.rectangle(imgcv, (left, top), (right, bot), colors[max_indx], thick) cv2.putText(imgcv, mess, (left + thick * 4, top + thick * 6), 0, 1e-3 * h, colors[max_indx], thick // 3) return outboxes, imgcv