|
| 1 | +# -------------------------------------------------------- |
| 2 | +# Fast R-CNN |
| 3 | +# Copyright (c) 2015 Microsoft |
| 4 | +# Licensed under The MIT License [see LICENSE for details] |
| 5 | +# Written by Ross Girshick |
| 6 | +# -------------------------------------------------------- |
| 7 | + |
| 8 | +# written by allenjbqin |
| 9 | +# 2019.05.15 |
| 10 | +import os |
| 11 | +import numpy as np |
| 12 | +import ctypes |
| 13 | +from ctypes import * |
| 14 | + |
| 15 | +so_file_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'librbox.so') |
| 16 | +so = ctypes.cdll.LoadLibrary |
| 17 | +librbox = so(so_file_path) |
| 18 | + |
| 19 | +overlap = librbox.Overlap |
| 20 | +overlap.argtypes = (POINTER(c_double), POINTER(c_double)) |
| 21 | +overlap.restype = c_double |
| 22 | + |
| 23 | + |
| 24 | +def py_cpu_nms(dets, thresh): |
| 25 | + """Pure Python NMS baseline.""" |
| 26 | + x1 = dets[:, 0] |
| 27 | + y1 = dets[:, 1] |
| 28 | + x2 = dets[:, 2] |
| 29 | + y2 = dets[:, 3] |
| 30 | + scores = dets[:, 4] |
| 31 | + |
| 32 | + areas = (x2 - x1 + 1) * (y2 - y1 + 1) |
| 33 | + order = scores.argsort()[::-1] |
| 34 | + |
| 35 | + keep = [] |
| 36 | + while order.size > 0: |
| 37 | + i = order[0] |
| 38 | + keep.append(i) |
| 39 | + xx1 = np.maximum(x1[i], x1[order[1:]]) |
| 40 | + yy1 = np.maximum(y1[i], y1[order[1:]]) |
| 41 | + xx2 = np.minimum(x2[i], x2[order[1:]]) |
| 42 | + yy2 = np.minimum(y2[i], y2[order[1:]]) |
| 43 | + |
| 44 | + w = np.maximum(0.0, xx2 - xx1 + 1) |
| 45 | + h = np.maximum(0.0, yy2 - yy1 + 1) |
| 46 | + inter = w * h |
| 47 | + ovr = inter / (areas[i] + areas[order[1:]] - inter) |
| 48 | + |
| 49 | + inds = np.where(ovr <= thresh)[0] |
| 50 | + order = order[inds + 1] |
| 51 | + |
| 52 | + return keep |
| 53 | + |
| 54 | +def angle_soft_nms(all_dets, sigma=0.5, Nt=0.1, threshold=0.001, method=0): |
| 55 | + """Pure Python NMS baseline.""" |
| 56 | + # dets = np.concatenate((all_dets[:, 0:4], all_dets[:, -1:]), axis=1) |
| 57 | + # scores = all_dets[:, 4] |
| 58 | + # cx,cy,w,h,angle,score |
| 59 | + # all_dets[:,4] = (all_dets[:,4]-0.5)*180.0 |
| 60 | + all_dets[:,4] = all_dets[:,4] / np.pi *180.0 |
| 61 | + boxes = all_dets |
| 62 | + # scores = all_dets[:, -1] |
| 63 | + N = all_dets.shape[0] |
| 64 | + if N >0 and len(boxes[0] == 7): |
| 65 | + is_scale = True |
| 66 | + else: |
| 67 | + is_scale = False |
| 68 | + |
| 69 | + # # ## a simple example |
| 70 | + # a = np.array([10,10,10,20,0]) |
| 71 | + # b = np.array([10,10,10,20,0.75]) |
| 72 | + # cd_a = (c_double * 5)() |
| 73 | + # cd_b = (c_double * 5)() |
| 74 | + # cd_a[0] = c_double(a[0]) |
| 75 | + # cd_a[1] = c_double(a[1]) |
| 76 | + # cd_a[2] = c_double(a[2]) |
| 77 | + # cd_a[3] = c_double(a[3]) |
| 78 | + # cd_a[4] = c_double(a[4]) |
| 79 | + # cd_b[0] = c_double(b[0]) |
| 80 | + # cd_b[1] = c_double(b[1]) |
| 81 | + # cd_b[2] = c_double(b[2]) |
| 82 | + # cd_b[3] = c_double(b[3]) |
| 83 | + # cd_b[4] = c_double(b[4]) |
| 84 | + # ov = overlap(cd_a, cd_b) |
| 85 | + for i in range(N): |
| 86 | + maxscore = boxes[i, 5] |
| 87 | + maxpos = i |
| 88 | + # 将第i个bbox存在temp |
| 89 | + tcx = boxes[i, 0] |
| 90 | + tcy = boxes[i, 1] |
| 91 | + tw = boxes[i, 2] |
| 92 | + th = boxes[i, 3] |
| 93 | + tangle = boxes[i, 4] |
| 94 | + ts= boxes[i, 5] |
| 95 | + if is_scale: |
| 96 | + scale= boxes[i, 6] |
| 97 | + |
| 98 | + pos = i + 1 |
| 99 | + # get max box |
| 100 | + while pos < N: |
| 101 | + if maxscore < boxes[pos, 5]: |
| 102 | + maxscore = boxes[pos, 5] |
| 103 | + maxpos = pos |
| 104 | + pos = pos + 1 |
| 105 | + |
| 106 | + # add max box as a detection |
| 107 | + boxes[i, 0] = boxes[maxpos, 0] |
| 108 | + boxes[i, 1] = boxes[maxpos, 1] |
| 109 | + boxes[i, 2] = boxes[maxpos, 2] |
| 110 | + boxes[i, 3] = boxes[maxpos, 3] |
| 111 | + boxes[i, 4] = boxes[maxpos, 4] |
| 112 | + boxes[i, 5] = boxes[maxpos, 5] |
| 113 | + if is_scale: |
| 114 | + boxes[i, 6] = boxes[maxpos, 6] |
| 115 | + |
| 116 | + # swap ith box with position of max box |
| 117 | + boxes[maxpos, 0] = tcx |
| 118 | + boxes[maxpos, 1] = tcy |
| 119 | + boxes[maxpos, 2] = tw |
| 120 | + boxes[maxpos, 3] = th |
| 121 | + boxes[maxpos, 4] = tangle |
| 122 | + boxes[maxpos, 5] = ts |
| 123 | + if is_scale: |
| 124 | + boxes[maxpos, 6] = scale |
| 125 | + |
| 126 | + # 此时第i个位最大score的,重新将第i个bbox存在temp |
| 127 | + # tcx = boxes[i, 0] |
| 128 | + # tcy = boxes[i, 1] |
| 129 | + # tw = boxes[i, 2] |
| 130 | + # th = boxes[i, 3] |
| 131 | + # tangle = boxes[i, 4] |
| 132 | + # ts= boxes[i, 5] |
| 133 | + |
| 134 | + box1 = (c_double * 5)() |
| 135 | + box2 = (c_double * 5)() |
| 136 | + box1[0] = c_double(boxes[i, 0]) |
| 137 | + box1[1] = c_double(boxes[i, 1]) |
| 138 | + box1[2] = c_double(boxes[i, 2]) |
| 139 | + box1[3] = c_double(boxes[i, 3]) |
| 140 | + box1[4] = c_double(boxes[i, 4]) |
| 141 | + |
| 142 | + pos = i + 1 |
| 143 | + # NMS iterations, note that N changes if detection boxes fall below threshold |
| 144 | + while pos < N: |
| 145 | + box2[0] = c_double(boxes[pos, 0]) |
| 146 | + box2[1] = c_double(boxes[pos, 1]) |
| 147 | + box2[2] = c_double(boxes[pos, 2]) |
| 148 | + box2[3] = c_double(boxes[pos, 3]) |
| 149 | + box2[4] = c_double(boxes[pos, 4]) |
| 150 | + |
| 151 | + ov = overlap(box1, box2) |
| 152 | + if ov > 0: |
| 153 | + if method == 1: # linear |
| 154 | + if ov > Nt: |
| 155 | + weight = 1 - ov |
| 156 | + else: |
| 157 | + weight = 1 |
| 158 | + elif method == 2: # gaussian |
| 159 | + weight = np.exp(-(ov * ov) / sigma) |
| 160 | + else: # original NMS |
| 161 | + if ov > Nt: |
| 162 | + weight = 0 |
| 163 | + else: |
| 164 | + weight = 1 |
| 165 | + |
| 166 | + boxes[pos, 5] = weight * boxes[pos, 5] |
| 167 | + |
| 168 | + # if box score falls below threshold, discard the box by swapping with last box |
| 169 | + # update N |
| 170 | + if boxes[pos, 5] < threshold: |
| 171 | + boxes[pos, 0] = boxes[N - 1, 0] |
| 172 | + boxes[pos, 1] = boxes[N - 1, 1] |
| 173 | + boxes[pos, 2] = boxes[N - 1, 2] |
| 174 | + boxes[pos, 3] = boxes[N - 1, 3] |
| 175 | + boxes[pos, 4] = boxes[N - 1, 4] |
| 176 | + boxes[pos, 5] = boxes[N - 1, 5] |
| 177 | + if is_scale: |
| 178 | + boxes[pos, 6] = boxes[N - 1, 6] |
| 179 | + N = N - 1 |
| 180 | + pos = pos - 1 |
| 181 | + pos = pos + 1 |
| 182 | + keep = [i for i in range(N)] |
| 183 | + # boxes[:, 4] = (boxes[:, 4] / 180.0) + 0.5 |
| 184 | + boxes[:, 4] = boxes[:, 4] / 180.0 * np.pi |
| 185 | + return boxes |
| 186 | + |
| 187 | +def angle_soft_nms_new(all_dets, sigma=0.5, Nt=0.5, threshold=0.03, method=0, all_cls=False, cls_decay=1.5): |
| 188 | + """Pure Python Soft-NMS baseline. |
| 189 | + author: Xingjia Pan |
| 190 | + date: 2019/11/4 |
| 191 | + all_dets: cx,cy,w,h,angle,score for one row |
| 192 | + """ |
| 193 | + all_dets[:,4] = all_dets[:,4] / np.pi *180.0 |
| 194 | + N = all_dets.shape[0] |
| 195 | + for i in range(N): |
| 196 | + order = np.argsort(-all_dets[:, 5]) |
| 197 | + all_dets = all_dets[order, :] |
| 198 | + ## calc distance of center point |
| 199 | + if i == N-1: |
| 200 | + continue |
| 201 | + dist_score = np.linalg.norm(all_dets[i,:2]-all_dets[i+1:, :2],axis=1) |
| 202 | + min_side = np.min(all_dets[i,2:4])+1e-8 |
| 203 | + div_factor = 1./10 if min_side>96 else 1./7 |
| 204 | + dist_score = dist_score/(div_factor * min_side) |
| 205 | + dist_score = np.clip(dist_score, 0.0, 1.0) |
| 206 | + dist_score = dist_score**2 |
| 207 | + box1 = (c_double * 5)() |
| 208 | + box1[0] = c_double(all_dets[i, 0]) |
| 209 | + box1[1] = c_double(all_dets[i, 1]) |
| 210 | + box1[2] = c_double(all_dets[i, 2]) |
| 211 | + box1[3] = c_double(all_dets[i, 3]) |
| 212 | + box1[4] = c_double(all_dets[i, 4]) |
| 213 | + j = i + 1 |
| 214 | + # NMS iterations, note that N changes if detection boxes fall below threshold |
| 215 | + while j < N: |
| 216 | + box2 = (c_double * 5)() |
| 217 | + box2[0] = c_double(all_dets[j, 0]) |
| 218 | + box2[1] = c_double(all_dets[j, 1]) |
| 219 | + box2[2] = c_double(all_dets[j, 2]) |
| 220 | + box2[3] = c_double(all_dets[j, 3]) |
| 221 | + box2[4] = c_double(all_dets[j, 4]) |
| 222 | + ov = overlap(box1, box2) |
| 223 | + weight = 1.0 |
| 224 | + if ov > 0: |
| 225 | + if method == 1: # linear |
| 226 | + if ov > Nt: |
| 227 | + weight = 1 - ov |
| 228 | + else: |
| 229 | + weight = 1 |
| 230 | + elif method == 2: # gaussian |
| 231 | + weight = np.exp(-(ov * ov) / sigma) |
| 232 | + else: # original NMS |
| 233 | + if ov > Nt: |
| 234 | + weight = 0 |
| 235 | + else: |
| 236 | + weight = 1 |
| 237 | + if all_cls: |
| 238 | + if all_dets[i,6] != all_dets[j, 6]: |
| 239 | + dist_score[j-i-1] *= cls_decay |
| 240 | + dist_score[j-i-1] = np.minimum(dist_score[j-i-1], 1.0) |
| 241 | + weight *= dist_score[j-i-1] |
| 242 | + all_dets[j, 5] = weight * all_dets[j, 5] |
| 243 | + j = j + 1 |
| 244 | + keep = all_dets[:,5] > threshold |
| 245 | + all_dets[:, 4] = all_dets[:, 4] / 180.0 * np.pi |
| 246 | + return all_dets[keep,:] |
| 247 | + |
| 248 | + |
| 249 | +def py_yt_nms(dets, thresh): |
| 250 | + x1 = dets[:, 0] |
| 251 | + y1 = dets[:, 1] |
| 252 | + |
| 253 | + x2 = dets[:, 2] |
| 254 | + y2 = dets[:, 3] |
| 255 | + scores = dets[:, 4] |
| 256 | + angle = 180.0 * (dets[:, 5] - 0.5) |
| 257 | + |
| 258 | + # sort by confidence |
| 259 | + order = scores.argsort()[::-1] |
| 260 | + |
| 261 | + # list of keep box |
| 262 | + keep = [] |
| 263 | + while order.size > 0: |
| 264 | + i = order[0] |
| 265 | + keep.append(i) |
| 266 | + |
| 267 | + cur_box = [x1[i], y1[i], x2[i], y2[i], angle[i]] |
| 268 | + other_boxes = [] |
| 269 | + for each_box in range(1, len(order)): |
| 270 | + each_other_box = [x1[order[each_box]], y1[order[each_box]], x2[order[each_box]], y2[order[each_box]],angle[order[each_box]]] |
| 271 | + other_boxes.append(each_other_box) |
| 272 | + iou_result_list = [] |
| 273 | + box1 = (c_double * 5)() |
| 274 | + box2 = (c_double * 5)() |
| 275 | + box1[0] = c_double(cur_box[0]) |
| 276 | + box1[1] = c_double(cur_box[1]) |
| 277 | + box1[2] = c_double(cur_box[2]) |
| 278 | + box1[3] = c_double(cur_box[3]) |
| 279 | + box1[4] = c_double(cur_box[4]) |
| 280 | + # call for cpp nms function |
| 281 | + for each_gt_box in other_boxes: |
| 282 | + box2[0] = c_double(each_gt_box[0]) |
| 283 | + box2[1] = c_double(each_gt_box[1]) |
| 284 | + box2[2] = c_double(each_gt_box[2]) |
| 285 | + box2[3] = c_double(each_gt_box[3]) |
| 286 | + box2[4] = c_double(each_gt_box[4]) |
| 287 | + |
| 288 | + # get return iou result |
| 289 | + each_iou = overlap(box1, box2) |
| 290 | + iou_result_list.append(each_iou) |
| 291 | + |
| 292 | + ovr = iou_result_list |
| 293 | + ovr = np.array(ovr) |
| 294 | + |
| 295 | + inds = np.where(ovr <= thresh)[0] |
| 296 | + order = order[inds + 1] |
| 297 | + |
| 298 | + return keep |
| 299 | + |
| 300 | + |
| 301 | +if __name__ == '__main__': |
| 302 | + a = np.array([(0, 0, 30 / 1000, 10 / 1000, .9, 0), |
| 303 | + (0, 0, 30 / 1000, 10 / 1000, .98, 0.25)]) # , (-5, -5, 5, 5, .98, 45), (-5, -5, 6, 6, .99, 30)]) |
| 304 | + # print(py_cpu_nms(a, 0.45)) |
| 305 | + # print(py_poly_nms(a, 0.45)) |
| 306 | + # print(Polygon(a).area) |
0 commit comments