IoU和NMS的实现

23 篇文章 0 订阅
21 篇文章 0 订阅

这里写的是python实现,主要是为了demonstrate思想,后期有空会加上cython和cuda实现。

Intersection over Union (IoU) Overlap:

我们需要一些衡量两个框接近程度的方法。
一个比较常用的方法是IoU,如下图
在这里插入图片描述

IOU实现

简单版 从one to one 到 one to many 到 many to many

def iou_one2one(box1,box2):
    left=np.max(box1[:,0], box2[:,0])
    right=np.min(box1[:,2],box2[:,2])
    top=np.max(box1[:,1], box2[:,1])
    bottom=np.min(box1[:,3],box2[:,3])
    inter=max(0, right-left)*max(0,bottom-top)
    union=(box1[:,2]-box1[:,0])*(box1[:,3]-box1[:,1])+(box2[:,2]-box2[:,0])*(box2[:,3]-box2[:,1])-inter 
    return inter/union
    
def iou_one2many(box1, boxes,):
	box1=np.reshape(box1,[-1,5])
	boxes=np.reshape(boxes,[-1,5])
	left=np.maximum(box1[:,0], boxes[:,0])
    right=np.minimum(box1[:,2],boxes[:,2])
    top=np.maximum(box1[:,1], boxes[:,1])
    bottom=np.minimum(box1[:,3],boxes[:,3])
    inter=np.maximum(0, right-left)*np.maximum(0,bottom-top)
    union=(box1[:,2]-box1[:,0])*(box1[:,3]-box1[:,1])+(boxes[:,2]-boxes[:,0])*(boxes[:,3]-boxes[:,1])-inter 
    return inter/union
def iou_many2many(boxes1, boxes2):
	res=[]
	for box in boxes:
		res.append(iou_one2many(box,boxes2))
	return np,array(res)

复杂版直接many to many

def compute_overlap(a, b):
    #a [N,4]
    #b [M,4]
    iw = np.minimum(np.expand_dims(a[:, 2], axis=-1), b[:, 2]) - np.maximum(np.expand_dims(a[:, 0], axis=-1), b[:, 0])
    ih = np.minimum(np.expand_dims(a[:, 3], axis=-1), b[:, 3]) - np.maximum(np.expand_dims(a[:, 1], axis=-1), b[:, 1])
    # 假设a的数目是N,b的数目是M
    # (N,)和(M,)不能broadcast,需要将其中一个转化成矩阵
    # np.expand_dims((N,),axis=-1)将(N,)变成(N,1) 这里也可以写axis=1
    #注意两个矩阵(N,1)和(M,1)也是不能进行broadcast的,只能是矩阵和向量
    # np.minimum((N,1),(M,)) 得到 (N M) 的矩阵 代表a和b逐一比较的结果
    # 取x和y中较小的值 来计算intersection
    # iw和ih分别是intersection的宽和高 iw和ih的shape都是(N,M), 代表每个anchor和groundTruth之间的intersection
    iw = np.maximum(iw, 0)
    ih = np.maximum(ih, 0) #不允许iw或者ih小于0
    #union = np.expand_dims((a[:, 2] - a[:, 0] + 1) *(a[:, 3] - a[:, 1] + 1), axis=1) + area - iw * ih
    area_b = (b[:, 2] - b[:, 0] ) * (b[:, 3] - b[:, 1] )
    area_a = (a[:, 2] - a[:, 0] ) *(a[:, 3] - a[:, 1] )
    union=np.expand_dims(area_a,axis=-1)+area_b- iw * ih
    #矩阵和向量之间才能进行broadcast,所以先expand
    # 并集的计算 S_a+S_b-interection_ab
    union = np.maximum(union, np.finfo(float).eps)
    intersection = iw * ih
    print(intersection,union)
    return intersection / union # (N,M)

Non-Maximum Suppression (NMS)

NMS方法的逻辑是先根据预测出的前景分数从高到低排序box,从分数最高的box开始遍历,与这个box的overlap大于某个threshold的box就会被去掉,例如下图我们以score=0.8的box为基准,overlap_threshold=0.2,那么与score=0.8的box的overlap大于0.2的框,都会被丢弃。如果框X与score=0.8的框的overlap小于0.2,那么我们会认为框X属于另一个物体,不用抑制。
在这里插入图片描述

NMS实现

简单版

def nms(boxes, nms_thres=0.3):
	idx=np.argsort(boxes[:,-1])[::-1] # 这个函数没有reverse,只能手动
	keep = []
	while idx.size>0:
		i = idx[0]
		keep.append(i)
		iou=iou_one2many(boxes[i], boxes[idx[1:]])
		idx = idx[iou < nms_thres]
	return keep

复杂版

def cpu_nms(boxes, iou_thres=0.5):
    x1,y1,x2,y2= boxes[:, 0],boxes[:,1],boxes[:,2],boxes[:,3]
    scores = boxes[:, 4]
    areas = (x2 - x1) * (y2 - y1)
    keep = []
    order = scores.argsort()[::-1] # high score to low score index
    while order.size > 0:
        i = order[0]
        keep.append(i)
        # x1[i]是向量,x1[order[1:]]是矩阵
        w=np.minimum(x2[i],x2[order[1:]])-np.maximum(x1[i],x1[order[1:]]) 
        w=np.maximum(0.0,w)
        h=np.minimum(y2[i],y2[order[1:]])-np.maximum(y1[i],y1[order[1:]])
        h=np.maximum(0.0,h)
        inter = w * h
        union=areas[i] + areas[order[1:]] - inter
        ovr = inter / union 
        inds = np.where(ovr <= iou_thres)[0]
        #直接跳到满足iou小于threshold的index
        order = order[inds + 1]

    return keep

boxes=np.array([[0,0,1,1,0.5],[0,0,2,2,0.6],[0,0,2,2,0.7],[0,0,3,3,0.8],[0,0,4,4,0.85]])
print(cpu_nms(boxes,0.2))

下面是执行的结果
python tmp.py
4 [9. 4. 4. 1.] [16. 16. 16. 16.] [0.5625 0.25   0.25   0.0625]
0 [] [] []
[4, 0]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值