def get_map(pred, gt, f): T = {} P = {} fx, fy = f for bbox in gt: bbox['bbox_matched'] = False pred_probs = np.array([s['prob'] for s in pred]) box_idx_sorted_by_prob = np.argsort(pred_probs)[::-1] for box_idx in box_idx_sorted_by_prob: pred_box = pred[box_idx] pred_class = pred_box['class'] pred_x1 = pred_box['x1'] pred_x2 = pred_box['x2'] pred_y1 = pred_box['y1'] pred_y2 = pred_box['y2'] pred_prob = pred_box['prob'] if pred_class not in P: P[pred_class] = [] T[pred_class] = [] P[pred_class].append(pred_prob) found_match = False for gt_box in gt: gt_class = gt_box['class'] gt_x1 = gt_box['x1']/fx gt_x2 = gt_box['x2']/fx gt_y1 = gt_box['y1']/fy gt_y2 = gt_box['y2']/fy gt_seen = gt_box['bbox_matched'] if gt_class != pred_class: continue if gt_seen: continue iou = data_generators.iou((pred_x1, pred_y1, pred_x2, pred_y2), (gt_x1, gt_y1, gt_x2, gt_y2)) if iou >= 0.5: found_match = True gt_box['bbox_matched'] = True break else: continue T[pred_class].append(int(found_match)) for gt_box in gt: if not gt_box['bbox_matched'] and not gt_box['difficult']: if gt_box['class'] not in P: P[gt_box['class']] = [] T[gt_box['class']] = [] T[gt_box['class']].append(1) P[gt_box['class']].append(0) #import pdb #pdb.set_trace() return T, P
def calc_iou(R, img_data, C, class_mapping): """ 本函数读入图片数据和经过非极大值抑制的rpn预测的坐标数据,对每个提出的predict box进行label的制作 label包括GT 类别, GT坐标 一个box四坐标只能对应一个类别,所以即使一张图里面有很多GT,只能选择iou最大的用于匹配 :param R: :param img_data: :param C: :param class_mapping: :return: """ ## img_data_aug 是哈希表,存放各种和当前图象有关的信息 bboxes = img_data['bboxes'] (width, height) = (img_data['width'], img_data['height']) # get image dimensions for resizing (resized_width, resized_height) = data_generators.get_new_img_size( width, height, C.im_size) ## 有多少标注的ground truth boxes 就有多少gta gta = np.zeros((len(bboxes), 4)) for bbox_num, bbox in enumerate(bboxes): # get the GT box coordinates, and resize to account for image resizing ## 计算调整后且映射到输出图大小上的ground truth boxes gta[bbox_num, 0] = int( round(bbox['x1'] * (resized_width / float(width)) / C.rpn_stride)) gta[bbox_num, 1] = int( round(bbox['x2'] * (resized_width / float(width)) / C.rpn_stride)) gta[bbox_num, 2] = int( round(bbox['y1'] * (resized_height / float(height)) / C.rpn_stride)) gta[bbox_num, 3] = int( round(bbox['y2'] * (resized_height / float(height)) / C.rpn_stride)) x_roi = [] y_class_num = [] y_class_regr_coords = [] y_class_regr_label = [] IoUs = [] # for debugging only ## R 只有 [bbox, prob] 中的 bbox 对应坐标值 ## A: layerkinds*w*h, coor, 这里[0]会小于layerkinds*w*h 因为最多300 for ix in range(R.shape[0]): (x1, y1, x2, y2) = R[ix, :] x1 = int(round(x1)) y1 = int(round(y1)) x2 = int(round(x2)) y2 = int(round(y2)) best_iou = 0.0 best_bbox = -1 for bbox_num in range(len(bboxes)): curr_iou = data_generators.iou([ gta[bbox_num, 0], gta[bbox_num, 2], gta[bbox_num, 1], gta[bbox_num, 3] ], [x1, y1, x2, y2]) if curr_iou > best_iou: best_iou = curr_iou best_bbox = bbox_num ## 选择可以用来最终分类的predict box if best_iou < C.classifier_min_overlap: #if C.classifier_min_overlap <= best_iou < C.classifier_max_overlap: continue else: w = x2 - x1 h = y2 - y1 x_roi.append([x1, y1, w, h]) IoUs.append(best_iou) ## 难例挖掘,与目标有部分重合但不够判断,分类成背景 ## 一张图里面有再多的类 if C.classifier_min_overlap <= best_iou < C.classifier_max_overlap: #if best_iou < C.classifier_min_overlap: # hard negative example cls_name = 'bg' elif C.classifier_max_overlap <= best_iou: cls_name = bboxes[best_bbox]['class'] ## ground truth box的中心点 cxg = (gta[best_bbox, 0] + gta[best_bbox, 1]) / 2.0 cyg = (gta[best_bbox, 2] + gta[best_bbox, 3]) / 2.0 ## predict box的中心值 cx = x1 + w / 2.0 cy = y1 + h / 2.0 tx = (cxg - cx) / float(w) ty = (cyg - cy) / float(h) tw = np.log((gta[best_bbox, 1] - gta[best_bbox, 0]) / float(w)) th = np.log((gta[best_bbox, 3] - gta[best_bbox, 2]) / float(h)) else: print('roi = {}'.format(best_iou)) raise RuntimeError class_num = class_mapping[cls_name] class_label = len(class_mapping) * [0] class_label[class_num] = 1 y_class_num.append(copy.deepcopy(class_label)) ## -1 是因为背景 coords = [0] * 4 * (len(class_mapping) - 1) labels = [0] * 4 * (len(class_mapping) - 1) if cls_name != 'bg': label_pos = 4 * class_num sx, sy, sw, sh = C.classifier_regr_std coords[label_pos:4 + label_pos] = [sx * tx, sy * ty, sw * tw, sh * th] labels[label_pos:4 + label_pos] = [1, 1, 1, 1] y_class_regr_coords.append(copy.deepcopy(coords)) y_class_regr_label.append(copy.deepcopy(labels)) else: y_class_regr_coords.append(copy.deepcopy(coords)) y_class_regr_label.append(copy.deepcopy(labels)) if len(x_roi) == 0: return None, None, None, None ## 感觉像创建label X = np.array(x_roi) Y1 = np.array(y_class_num) ## axis= 1 这样同属于同一个像素的位置的同一个格式anchorbox的label coord 标签在同一行 Y2 = np.concatenate( [np.array(y_class_regr_label), np.array(y_class_regr_coords)], axis=1) return np.expand_dims(X, axis=0), np.expand_dims( Y1, axis=0), np.expand_dims(Y2, axis=0), IoUs
best = False value = 0 for key in bboxes: bbox = np.array(bboxes[key]) new_boxes, new_probs = roi_helpers.non_max_suppression_fast( bbox, np.array(probs[key]), overlap_thresh=0.7) for jk in range(new_boxes.shape[0]): (x1, y1, x2, y2) = new_boxes[jk, :] (real_x1, real_y1, real_x2, real_y2) = get_real_coordinates(ratio, x1, y1, x2, y2) predBox = (real_x1, real_y1, real_x2, real_y2) iou_value = iou(realBox, predBox) if iou_value > iou_threshold: best = True value = iou_value cv2.rectangle( img, (real_x1, real_y1), (real_x2, real_y2), (int(class_to_color[key][0]), int( class_to_color[key][1]), int(class_to_color[key][2])), 2) textLabel = '{}: {}'.format(key, int(100 * new_probs[jk])) all_dets.append((key, 100 * new_probs[jk])) (retval, baseLine) = cv2.getTextSize(textLabel, cv2.FONT_HERSHEY_COMPLEX, 1,
# get the GT box coordinates, and resize to account for image resizing # bbox_gt2pred[bbox_num] = (-1,0) gta[bbox_num, 0] = int(round(bbox['x1'] * (resized_width / float(width)))) gta[bbox_num, 1] = int(round(bbox['x2'] * (resized_width / float(width)))) gta[bbox_num, 2] = int(round(bbox['y1'] * (resized_height / float(height)))) gta[bbox_num, 3] = int(round(bbox['y2'] * (resized_height / float(height)))) for jk in range(new_bboxes.shape[0]): # bbox_pred2tr[jk] = False ################################################ best_iou = 0.0 best_bbox = 0 best_score = 0 for bbox_num in range(len(true_bboxes)): curr_iou = data_generators.iou([gta[bbox_num, 0], gta[bbox_num, 2], gta[bbox_num, 1], gta[bbox_num, 3]], [new_bboxes[jk,0], new_bboxes[jk,1], new_bboxes[jk,2], new_bboxes[jk,3]]) if curr_iou > base_threshold and curr_iou > best_iou: best_iou = curr_iou best_bbox = bbox_num true_orient = (180/3.14)*np.array([true_bboxes[best_bbox]['roll'],true_bboxes[best_bbox]['pitch'], true_bboxes[best_bbox]['yaw'] ]) pred_orient = (180/3.14)*new_poses[jk] # bp() df_curr = {'filename':[img_data['filepath']],'iou':[best_iou], 'score':[new_probs[jk]],'pred_gender':[new_genders[jk]], \ 'true_gender':[true_bboxes[best_bbox]['sex']],'pred_orient':[pred_orient.astype(int)],'true_orient':[true_orient.astype(int)]} df = df.append(df_curr,ignore_index=True) ################################################################################################################################################################################################ if displayImages:
# Iterate over remaining boxes for jk in range(new_boxes.shape[0]): (x1, y1, x2, y2) = new_boxes[jk, :] (real_x1, real_y1, real_x2, real_y2) = get_real_coordinates(ratio, x1, y1, x2, y2) overlap = False for gt_box in gt_boxes: if real_x1 >= gt_box['x2'] or real_y1 >= gt_box[ 'y2'] or real_x2 <= gt_box[ 'x1'] or real_y2 <= gt_box['y1']: continue else: curr_iou = iou((real_x1, real_y1, real_x2, real_y2), (gt_box['x1'], gt_box['y1'], gt_box['x2'], gt_box['y2'])) overlap = True if gt_box['best_iou'] < curr_iou: gt_box['best_iou'] = curr_iou if gt_box['best_iou_index']: gt_box['overlaps_index'].append( gt_box['best_iou_index']) if curr_iou > iou_threshold_tp: gt_box['best_iou_index'] = jk else: gt_box['overlaps_index'].append(jk) else: gt_box['overlaps_index'].append(jk) # Calculate distance from center point in meters
def calc_iou(R, img_data, C, class_mapping): bboxes = img_data['bboxes'] (width, height) = (img_data['width'], img_data['height']) # get image dimensions for resizing (resized_width, resized_height) = data_generators.get_new_img_size(width, height, C.im_size) gta = np.zeros((len(bboxes), 4)) for bbox_num, bbox in enumerate(bboxes): # get the GT box coordinates, and resize to account for image resizing gta[bbox_num, 0] = int(round(bbox['x1'] * (resized_width / float(width))/C.rpn_stride)) gta[bbox_num, 1] = int(round(bbox['x2'] * (resized_width / float(width))/C.rpn_stride)) gta[bbox_num, 2] = int(round(bbox['y1'] * (resized_height / float(height))/C.rpn_stride)) gta[bbox_num, 3] = int(round(bbox['y2'] * (resized_height / float(height))/C.rpn_stride)) x_roi = [] y_class_num = [] y_class_regr_coords = [] y_class_regr_label = [] for ix in range(R.shape[0]): (x1, y1, x2, y2) = R[ix, :] x1 = int(round(x1)) y1 = int(round(y1)) x2 = int(round(x2)) y2 = int(round(y2)) best_iou = 0.0 best_bbox = -1 for bbox_num in range(len(bboxes)): curr_iou = data_generators.iou([gta[bbox_num, 0], gta[bbox_num, 2], gta[bbox_num, 1], gta[bbox_num, 3]], [x1, y1, x2, y2]) if curr_iou > best_iou: best_iou = curr_iou best_bbox = bbox_num if best_iou < C.classifier_min_overlap: continue else: w = x2 - x1 h = y2 - y1 x_roi.append([x1, y1, w, h]) if C.classifier_min_overlap <= best_iou < C.classifier_max_overlap: # hard negative example cls_name = 'bg' elif C.classifier_max_overlap <= best_iou: cls_name = bboxes[best_bbox]['class'] cxg = (gta[best_bbox, 0] + gta[best_bbox, 1]) / 2.0 cyg = (gta[best_bbox, 2] + gta[best_bbox, 3]) / 2.0 cx = x1 + w / 2.0 cy = y1 + h / 2.0 tx = (cxg - cx) / float(w) ty = (cyg - cy) / float(h) tw = np.log((gta[best_bbox, 1] - gta[best_bbox, 0]) / float(w)) th = np.log((gta[best_bbox, 3] - gta[best_bbox, 2]) / float(h)) else: print('roi = {}'.format(best_iou)) raise RuntimeError class_num = class_mapping[cls_name] class_label = len(class_mapping) * [0] class_label[class_num] = 1 y_class_num.append(copy.deepcopy(class_label)) coords = [0] * 4 * (len(class_mapping) - 1) labels = [0] * 4 * (len(class_mapping) - 1) if cls_name != 'bg': label_pos = 4 * class_num sx, sy, sw, sh = C.classifier_regr_std coords[label_pos:4+label_pos] = [sx*tx, sy*ty, sw*tw, sh*th] labels[label_pos:4+label_pos] = [1, 1, 1, 1] y_class_regr_coords.append(copy.deepcopy(coords)) y_class_regr_label.append(copy.deepcopy(labels)) else: y_class_regr_coords.append(copy.deepcopy(coords)) y_class_regr_label.append(copy.deepcopy(labels)) if len(x_roi) == 0: return None, None, None X = np.array(x_roi) Y1 = np.array(y_class_num) Y2 = np.concatenate([np.array(y_class_regr_label),np.array(y_class_regr_coords)],axis=1) return np.expand_dims(X, axis=0), np.expand_dims(Y1, axis=0), np.expand_dims(Y2, axis=0)
def eval_each_img(pred, gt, f, overlap_thresh=0.5): # all the dict below is by class tp = {} # true positive fp = {} # false positive fn = {} # false negative (undetected ground truth boxes) prob_fp = [] # proba of false positive fx, fy = f for gt_bbox in gt: gt_bbox['bbox_matched'] = False pred_probs = np.array([s['prob'] for s in pred]) box_idx_sorted_by_prob = np.argsort(pred_probs)[::-1] for box_idx in box_idx_sorted_by_prob: pred_box = pred[box_idx] pred_class = pred_box['class'] # init tp, fp, fn: if pred_class not in tp: tp[pred_class] = 0 if pred_class not in fp: fp[pred_class] = 0 if pred_class not in fn: fn[pred_class] = 0 pred_x1 = pred_box['x1'] pred_x2 = pred_box['x2'] pred_y1 = pred_box['y1'] pred_y2 = pred_box['y2'] # find list of ground truth with matched class idx_gt_class_matched = [ i for i in range(len(gt)) if gt[i]['class'] == pred_class ] #print(box_idx) #print(idx_gt_class_matched) # compute IoU with GT_same_class and find the max if len( idx_gt_class_matched ) > 0: # this line is important: only consider ground truth of same class idx_max = -1 cur_max_IoU = -np.inf for idx in idx_gt_class_matched: gt_box = gt[idx] gt_x1 = gt_box['x1'] / fx gt_x2 = gt_box['x2'] / fx gt_y1 = gt_box['y1'] / fy gt_y2 = gt_box['y2'] / fy cur_IoU = data_generators.iou( (pred_x1, pred_y1, pred_x2, pred_y2), (gt_x1, gt_y1, gt_x2, gt_y2)) if cur_max_IoU < cur_IoU: cur_max_IoU = cur_IoU idx_max = idx if cur_max_IoU >= overlap_thresh: if not gt[idx_max][ 'bbox_matched']: # gt not detected previously tp[pred_class] += 1 # true positive gt[idx_max]['bbox_matched'] = True else: fp[pred_class] += 1 prob_fp.append(pred_box['prob']) else: # detect where no ground truth overthere -> FP fp[pred_class] += 1 prob_fp.append(pred_box['prob']) # now deal with the false negative: gt_bbox_not_detected = [ gt_bbox for gt_bbox in gt if not gt_bbox['bbox_matched'] ] for undetected_bb in gt_bbox_not_detected: # for VOC difficult: if 'difficult' in gt_bbox_not_detected: if gt_bbox_not_detected['difficult']: continue bb_class = undetected_bb['class'] # init all to make sure the accumulation match if bb_class not in fn: fn[bb_class] = 0 if bb_class not in tp: tp[bb_class] = 0 if bb_class not in fp: fp[bb_class] = 0 fn[bb_class] += 1 return tp, fp, fn, prob_fp
def get_map(pred, gt, f): T = {} P = {} fx, fy = f tp = {} # true positive fp = {} # false positive num_gt = {} # number of ground truth box for bbox in gt: bbox['bbox_matched'] = False pred_probs = np.array([s['prob'] for s in pred]) box_idx_sorted_by_prob = np.argsort(pred_probs)[::-1] # for each predicted box in highest proba -> lowest proba for box_idx in box_idx_sorted_by_prob: pred_box = pred[box_idx] pred_class = pred_box['class'] # get the class pred_x1 = pred_box['x1'] pred_x2 = pred_box['x2'] pred_y1 = pred_box['y1'] pred_y2 = pred_box['y2'] pred_prob = pred_box['prob'] if pred_class not in P: P[pred_class] = [] T[pred_class] = [] P[pred_class].append(pred_prob) # P is the probability list found_match = False for gt_box in gt: gt_class = gt_box['class'] if gt_class not in num_gt: num_gt[gt_class] = 1 else: num_gt[gt_class] += 1 gt_x1 = gt_box['x1'] / fx gt_x2 = gt_box['x2'] / fx gt_y1 = gt_box['y1'] / fy gt_y2 = gt_box['y2'] / fy gt_seen = gt_box['bbox_matched'] if gt_class != pred_class: continue if gt_seen: continue iou = data_generators.iou((pred_x1, pred_y1, pred_x2, pred_y2), (gt_x1, gt_y1, gt_x2, gt_y2)) if iou >= 0.5: found_match = True gt_box['bbox_matched'] = True break else: continue T[pred_class].append( int(found_match) ) # for each predicted box, T is the true label -> either True or False for gt_box in gt: if not gt_box['bbox_matched']: # and not gt_box['difficult']: if gt_box['class'] not in P: P[gt_box['class']] = [] T[gt_box['class']] = [] T[gt_box['class']].append(1) P[gt_box['class']].append(0) #import pdb #pdb.set_trace() return T, P