zoukankan      html  css  js  c++  java
  • 非极大值抑制NMS

    参考:https://zhuanlan.zhihu.com/p/49481833

    1 NMS操作流程

    NMS用于剔除图像中检出的冗余bbox,标准NMS的具体做法为:

    step-1:将所有检出的output_bbox按cls score划分(如pascal voc分20个类,也即将output_bbox按照其对应的cls score划分为21个集合,1个bg类,只不过bg类就没必要做NMS而已);

    step-2:在每个集合内根据各个bbox的cls score做降序排列,得到一个降序的list_k;

    step-3:从list_k中top1 cls score开始,计算该bbox_x与list中其他bbox_y的IoU,若IoU大于阈值T,则剔除该bbox_y,最终保留bbox_x,从list_k中取出;

    step-4:选择list_k中top2 cls score(步骤3取出top 1 bbox_x后,原list_k中的top 2就相当于现list_k中的top 1了,但如果step-3中剔除的bbox_y刚好是原list_k中的top 2,就依次找top 3即可,理解这么个意思就行),重复step-3中的迭代操作,直至list_k中所有bbox都完成筛选;

    step-5:对每个集合的list_k,重复step-3、4中的迭代操作,直至所有list_k都完成筛选;

    文件cpu_nms.pyx

    # --------------------------------------------------------
    # Fast R-CNN
    # Copyright (c) 2015 Microsoft
    # Licensed under The MIT License [see LICENSE for details]
    # Written by Ross Girshick
    # --------------------------------------------------------
    
    import numpy as np
    cimport numpy as np
    
    cdef inline np.float32_t max(np.float32_t a, np.float32_t b):
        return a if a >= b else b
    
    cdef inline np.float32_t min(np.float32_t a, np.float32_t b):
        return a if a <= b else b
    
    def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh):
        cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0]
        cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1]
        cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2]
        cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3]
        cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4]
    
        cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1)
        cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1]
    
        cdef int ndets = dets.shape[0]
        cdef np.ndarray[np.int_t, ndim=1] suppressed = 
                np.zeros((ndets), dtype=np.int)
    
        # nominal indices
        cdef int _i, _j
        # sorted indices
        cdef int i, j
        # temp variables for box i's (the box currently under consideration)
        cdef np.float32_t ix1, iy1, ix2, iy2, iarea
        # variables for computing overlap with box j (lower scoring box)
        cdef np.float32_t xx1, yy1, xx2, yy2
        cdef np.float32_t w, h
        cdef np.float32_t inter, ovr
    
        keep = []
        for _i in range(ndets):
            i = order[_i]
            if suppressed[i] == 1:
                continue
            keep.append(i)
            ix1 = x1[i]
            iy1 = y1[i]
            ix2 = x2[i]
            iy2 = y2[i]
            iarea = areas[i]
            for _j in range(_i + 1, ndets):
                j = order[_j]
                if suppressed[j] == 1:
                    continue
                xx1 = max(ix1, x1[j])
                yy1 = max(iy1, y1[j])
                xx2 = min(ix2, x2[j])
                yy2 = min(iy2, y2[j])
                w = max(0.0, xx2 - xx1 + 1)
                h = max(0.0, yy2 - yy1 + 1)
                inter = w * h
                ovr = inter / (iarea + areas[j] - inter)
                if ovr >= thresh:
                    suppressed[j] = 1
    
        return keep
    
    def cpu_soft_nms(np.ndarray[float, ndim=2] boxes, float sigma=0.5, float Nt=0.3, float threshold=0.001, unsigned int method=0):
        cdef unsigned int N = boxes.shape[0]
        cdef float iw, ih, box_area
        cdef float ua
        cdef int pos = 0
        cdef float maxscore = 0
        cdef int maxpos = 0
        cdef float x1,x2,y1,y2,tx1,tx2,ty1,ty2,ts,area,weight,ov
    
        for i in range(N):
            maxscore = boxes[i, 4]
            maxpos = i
    
            tx1 = boxes[i,0]
            ty1 = boxes[i,1]
            tx2 = boxes[i,2]
            ty2 = boxes[i,3]
            ts = boxes[i,4]
    
            pos = i + 1
        # get max box
            while pos < N:
                if maxscore < boxes[pos, 4]:
                    maxscore = boxes[pos, 4]
                    maxpos = pos
                pos = pos + 1
    
        # add max box as a detection 
            boxes[i,0] = boxes[maxpos,0]
            boxes[i,1] = boxes[maxpos,1]
            boxes[i,2] = boxes[maxpos,2]
            boxes[i,3] = boxes[maxpos,3]
            boxes[i,4] = boxes[maxpos,4]
    
        # swap ith box with position of max box
            boxes[maxpos,0] = tx1
            boxes[maxpos,1] = ty1
            boxes[maxpos,2] = tx2
            boxes[maxpos,3] = ty2
            boxes[maxpos,4] = ts
    
            tx1 = boxes[i,0]
            ty1 = boxes[i,1]
            tx2 = boxes[i,2]
            ty2 = boxes[i,3]
            ts = boxes[i,4]
    
            pos = i + 1
        # NMS iterations, note that N changes if detection boxes fall below threshold
            while pos < N:
                x1 = boxes[pos, 0]
                y1 = boxes[pos, 1]
                x2 = boxes[pos, 2]
                y2 = boxes[pos, 3]
                s = boxes[pos, 4]
    
                area = (x2 - x1 + 1) * (y2 - y1 + 1)
                iw = (min(tx2, x2) - max(tx1, x1) + 1)
                if iw > 0:
                    ih = (min(ty2, y2) - max(ty1, y1) + 1)
                    if ih > 0:
                        ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih)
                        ov = iw * ih / ua #iou between max box and detection box
    
                        if method == 1: # linear
                            if ov > Nt: 
                                weight = 1 - ov
                            else:
                                weight = 1
                        elif method == 2: # gaussian
                            weight = np.exp(-(ov * ov)/sigma)
                        else: # original NMS
                            if ov > Nt: 
                                weight = 0
                            else:
                                weight = 1
    
                        boxes[pos, 4] = weight*boxes[pos, 4]
                
                # if box score falls below threshold, discard the box by swapping with last box
                # update N
                        if boxes[pos, 4] < threshold:
                            boxes[pos,0] = boxes[N-1, 0]
                            boxes[pos,1] = boxes[N-1, 1]
                            boxes[pos,2] = boxes[N-1, 2]
                            boxes[pos,3] = boxes[N-1, 3]
                            boxes[pos,4] = boxes[N-1, 4]
                            N = N - 1
                            pos = pos - 1
    
                pos = pos + 1
    
        keep = [i for i in range(N)]
        return keep
  • 相关阅读:
    linq.js
    ES6入门
    Visual Studio Code之常备快捷键
    JavaScript——数组
    谈程序员的出路
    优秀博文
    多媒体封装格式详解---MP4
    音视频文件分析工具
    offsetof(s,m)解析
    GCC 提供的原子操作
  • 原文地址:https://www.cnblogs.com/juluwangshier/p/13294010.html
Copyright © 2011-2022 走看看