def encode(self, gt_data, overlap_threshold=0.5, debug=False): ''' gt_data의 예시: image 하나당 [x1,y1, x2,y2, x3,y3, x4,y4, 6_one_hot_class]의 데이터가 box갯수만큼 있음 [[0.56833333 0.20300752 0.97666667 0.33333333 0.97 0.47619048 0.55833333 0.34586466 0. 0. 0. 0. 0. 1. ] [0.11666667 0.45864662 0.14166667 0.45614035 0.14 0.49874687 0.115 0.50125313 0. 1. 0. 0. 0. 0. ] [0.88333333 0.47869674 0.91166667 0.48120301 0.91 0.50626566 0.88166667 0.5037594 0. 1. 0. 0. 0. 0. ] [0.03166667 0.30075188 0.42666667 0.160401 0.44666667 0.30075188 0.03666667 0.46867168 0. 1. 0. 0. 0. 0. ] [0.15833333 0.39598997 0.42 0.40601504 0.415 0.48120301 0.15333333 0.47368421 0. 1. 0. 0. 0. 0. ] [0.58166667 0.41854637 0.85833333 0.4235589 0.86 0.4962406 0.58166667 0.49373434 0. 1. 0. 0. 0. 0. ] [0.63 0.57894737 0.68333333 0.60150376 0.67666667 0.64160401 0.62333333 0.61904762 0. 1. 0. 0. 0. 0. ] [0.46 0.71428571 0.555 0.71428571 0.555 0.74937343 0.46 0.74937343 0. 0. 0. 0. 0. 1. ]] 위에서 정의한 prior box들의 정보를 가지고 prior box와 gt_data를 match시켜서 shape = [priormap갯수(엄청큼), 4+8+5+confidence_of_class] 인 넘파이배열을 return한다. confidence class에서는 4+8+5의 정보가 gt_data와의 iou가 0.5를 넘는게 없다면 background class로 분류된다. ''' ''' array([[0.09446537, 0.64231986, 0.6947241 , 0.80873207, 0.66108891, 1.05911375, 0.05824286, 0.92018245, 0. , 0. , 0. , 0. , 0. , 1. ]]) error찾기 ''' # image에 box가 없을경우 if gt_data.shape[0] == 0: print('gt_data', type(gt_data), gt_data.shape) eps = 1e-15 #수정 한상준13 num_classes = 6 num_priors = self.priors.shape[0] gt_polygons = np.copy(gt_data[:, :8]) # normalized quadrilaterals gt_rboxes = np.array( [polygon_to_rbox3(np.reshape(p, (-1, 2))) for p in gt_data[:, :8]]) # minimum horizontal bounding rectangles gt_xmin = np.min(gt_data[:, 0:8:2], axis=1) #shape : [nb_boxes] gt_ymin = np.min(gt_data[:, 1:8:2], axis=1) gt_xmax = np.max(gt_data[:, 0:8:2], axis=1) gt_ymax = np.max(gt_data[:, 1:8:2], axis=1) gt_boxes = self.gt_boxes = np.array( [gt_xmin, gt_ymin, gt_xmax, gt_ymax]).T # shape : [nb_boxes, 4] # normalized xmin, ymin, xmax, ymax gt_one_hot = gt_data[:, 8:] # shape : [nb_boxes, 6] gt_iou = np.array([iou(b, self.priors_norm) for b in gt_boxes]).T # shape of self.priors_norm : [Nums_priors, min_xy + max_xy+ variance] # b = [4], self.priors_norm = [Nums_priors, 4+4] # shape of gt_iou : [[Nums_priors] for b in gt_boxes].transpose = [nb_boxes, Nums_priors].transpose = [Num_priors, nb_boxes] # assigne gt to priors max_idxs = np.argmax(gt_iou, axis=1) # shape : [Num_priors] max_val = gt_iou[np.arange(num_priors), max_idxs] # shape: [Num_priors] prior_mask = max_val > overlap_threshold #IOU값의 maximum이 0.5가 넘는 prior들만 True값을 줌 match_indices = max_idxs[ prior_mask] # shape : [Num_priors - False_priors] self.match_indices = dict( zip(list(np.ix_(prior_mask)[0]), list(match_indices))) # {prior_1 : max_idx, prior_3 : max_idx, prior_4 : max_idx, prior_7 : max_idx, ...} # prior labels confidence = np.zeros((num_priors, num_classes)) confidence[:, 0] = 1 # 일단 모든 prior들을 background 로 정의 confidence[prior_mask] = gt_one_hot[ match_indices] # mask가 True인것(iou>0.5)만 one_hot_class를 새로 매겨줌 gt_xy = (gt_boxes[:, 2:4] + gt_boxes[:, 0:2]) / 2. #shape : [nb_boxes,2] gt_wh = gt_boxes[:, 2:4] - gt_boxes[:, 0:2] #shape : [nb_boxes,2] gt_xy = gt_xy[ match_indices] #shape : [True_priors,2] , True_priors = Num_priors - False_priors gt_wh = gt_wh[match_indices] #shape : [True_priors,2] gt_polygons = gt_polygons[match_indices] #shape : [True_priors,8] gt_rboxes = gt_rboxes[match_indices] #shape : [True_priors,5] priors_xy = self.priors_xy[ prior_mask] / self.image_size # = self.priors_xy_norm[prior_mask] priors_wh = self.priors_wh[ prior_mask] / self.image_size # = self.priors_wh_norm[prior_mask] variances_xy = self.priors_variances[prior_mask, 0:2] variances_wh = self.priors_variances[prior_mask, 2:4] # compute local offsets for # gt_x = prior_x + prior_w * x_label # x_label = x_label / 0.1 # gt_w = exp(w_label) * prior_w # w_label = w_label / 0.2 offsets = np.zeros((num_priors, 4)) offsets[prior_mask, 0:2] = (gt_xy - priors_xy) / priors_wh offsets[prior_mask, 2:4] = np.log(gt_wh / priors_wh) #수정 한상준13 offsets[prior_mask, 0:2] /= variances_xy offsets[prior_mask, 2:4] /= variances_wh # compute local offsets for quadrilaterals # gt_x1 = prior_x1 + prior_w * x1_label # x1_label = x1_label / 0.1 offsets_quads = np.zeros((num_priors, 8)) priors_xy_minmax = np.hstack( [priors_xy - priors_wh / 2, priors_xy + priors_wh / 2]) ref = priors_xy_minmax[:, (0, 1, 2, 1, 2, 3, 0, 3)] # corner points offsets_quads[prior_mask, :] = (gt_polygons - ref) / np.tile( priors_wh, (1, 4)) / np.tile(variances_xy, (1, 4)) # compute local offsets for rotated bounding boxes # gt_x1 = prior_x1 + prior_w * x1_label # x1_label = x1_label / 0.1 # gt_h = exp(h_label) * prior_h # h_label = h_label / 0.2 offsets_rboxs = np.zeros((num_priors, 5)) offsets_rboxs[prior_mask, 0:2] = (gt_rboxes[:, 0:2] - priors_xy) / priors_wh / variances_xy offsets_rboxs[prior_mask, 2:4] = (gt_rboxes[:, 2:4] - priors_xy) / priors_wh / variances_xy offsets_rboxs[prior_mask, 4] = np.log( gt_rboxes[:, 4] / priors_wh[:, 1]) / variances_wh[:, 1] #수정 한상준13 return np.concatenate( [offsets, offsets_quads, offsets_rboxs, confidence], axis=1)
def encode(self, gt_data, overlap_threshold=0.5, debug=False): # calculation is done with normalized sizes # TODO: empty ground truth if gt_data.shape[0] == 0: print('gt_data', type(gt_data), gt_data.shape) num_classes = 2 num_priors = self.priors.shape[0] gt_polygons = np.copy(gt_data[:, :8]) # normalized quadrilaterals gt_rboxes = np.array( [polygon_to_rbox3(np.reshape(p, (-1, 2))) for p in gt_data[:, :8]]) # minimum horizontal bounding rectangles gt_xmin = np.min(gt_data[:, 0:8:2], axis=1) gt_ymin = np.min(gt_data[:, 1:8:2], axis=1) gt_xmax = np.max(gt_data[:, 0:8:2], axis=1) gt_ymax = np.max(gt_data[:, 1:8:2], axis=1) gt_boxes = self.gt_boxes = np.array( [gt_xmin, gt_ymin, gt_xmax, gt_ymax]).T # normalized xmin, ymin, xmax, ymax gt_class_idx = np.asarray(gt_data[:, -1] + 0.5, dtype=np.int) gt_one_hot = np.zeros([len(gt_class_idx), num_classes]) gt_one_hot[range(len(gt_one_hot)), gt_class_idx] = 1 # one_hot classes including background gt_iou = np.array([iou(b, self.priors_norm) for b in gt_boxes]).T # assigne gt to priors max_idxs = np.argmax(gt_iou, axis=1) max_val = gt_iou[np.arange(num_priors), max_idxs] prior_mask = max_val > overlap_threshold match_indices = max_idxs[prior_mask] self.match_indices = dict( zip(list(np.ix_(prior_mask)[0]), list(match_indices))) # prior labels confidence = np.zeros((num_priors, num_classes)) confidence[:, 0] = 1 confidence[prior_mask] = gt_one_hot[match_indices] gt_xy = (gt_boxes[:, 2:4] + gt_boxes[:, 0:2]) / 2. gt_wh = gt_boxes[:, 2:4] - gt_boxes[:, 0:2] gt_xy = gt_xy[match_indices] gt_wh = gt_wh[match_indices] gt_polygons = gt_polygons[match_indices] gt_rboxes = gt_rboxes[match_indices] priors_xy = self.priors_xy[prior_mask] / self.image_size priors_wh = self.priors_wh[prior_mask] / self.image_size variances_xy = self.priors_variances[prior_mask, 0:2] variances_wh = self.priors_variances[prior_mask, 2:4] # compute local offsets for offsets = np.zeros((num_priors, 4)) offsets[prior_mask, 0:2] = (gt_xy - priors_xy) / priors_wh offsets[prior_mask, 2:4] = np.log(gt_wh / priors_wh) offsets[prior_mask, 0:2] /= variances_xy offsets[prior_mask, 2:4] /= variances_wh # compute local offsets for quadrilaterals offsets_quads = np.zeros((num_priors, 8)) priors_xy_minmax = np.hstack( [priors_xy - priors_wh / 2, priors_xy + priors_wh / 2]) #ref = np.tile(priors_xy, (1,4)) ref = priors_xy_minmax[:, (0, 1, 2, 1, 2, 3, 0, 3)] # corner points offsets_quads[prior_mask, :] = (gt_polygons - ref) / np.tile( priors_wh, (1, 4)) / np.tile(variances_xy, (1, 4)) # compute local offsets for rotated bounding boxes offsets_rboxs = np.zeros((num_priors, 5)) offsets_rboxs[prior_mask, 0:2] = (gt_rboxes[:, 0:2] - priors_xy) / priors_wh / variances_xy offsets_rboxs[prior_mask, 2:4] = (gt_rboxes[:, 2:4] - priors_xy) / priors_wh / variances_xy offsets_rboxs[prior_mask, 4] = np.log( gt_rboxes[:, 4] / priors_wh[:, 1]) / variances_wh[:, 1] return np.concatenate( [offsets, offsets_quads, offsets_rboxs, confidence], axis=1)