计算NMS以及Map(一)

博客围绕单张图片的NMS计算展开。测试时需进行NMS去除不必要的框以保证输出效果。输入检测网络的数据有特定输出格式,针对单张图片求解NMS。还介绍了BboxEncoder,需将目标检测预测的Bbox坐标转换为绝对坐标,以及ClassEncoder等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算NMS

    在进行测试的时候我们需要进行NMS,把没有必要的框去除掉,以保证我们的输出效果。

    在把数据输入到检测网络中时,输出的为PreBoxes(Shape=(B,A,4)),PreIds(Shape=(B,A,NUMClass)),PreScores(Shape=(B,A,NUMClass)),在此我真对一张图片进行求解NMS。首先我们要明白PreBoxes包含的是所有Decoder以后的Boxes,那么PreScore是每一个Anchor的SoftMax,PreIds为每一个Anchor的真实ID,若不是该类则为-1。如下所示,下面分别是介绍BboxEncoder、ClassEncoder以及NMS(单张图片)。

BboxEncoder:

    目标检测预测的Bbox是Anchor的Offset,因此在输出之前,我们先要进行Encoder,即将坐标转换为绝对坐标。计算公式为

p = nd.split(x, axis=-1, num_outputs=4)
ox = nd.broadcast_add(nd.broadcast_mul(p[0] * 0.1, a[2]), a[0])
oy = nd.broadcast_add(nd.broadcast_mul(p[1] * 0.1, a[3]), a[1])
tw = nd.exp(p[2]*0.2)
th = nd.exp(p[3]*0.2)
ow = nd.broadcast_mul(tw, a[2]) / 2
oh = nd.broadcast_mul(th, a[3]) / 2

ClassEncoder:

import mxnet as mx
#mx.nd.where(mx.nd.array([0,1,2]),mx.nd.array([12,11,13]),mx.nd.array([15,16,17]))
#mx.nd.ones_like(mx.nd.array([0,1,2]))*-1
def ClassEncoder(Data):
    Template=mx.nd.zeros_like(Data.slice_axis(begin=0,end=1,axis=-1))
    Score=Data.slice_axis(begin=1,end=Data.shape[-1],axis=-1)
    ClassIds=[]
    for i in range(Data.shape[-1]-1):
        ClassIds.append(Template+i)
    class_id=mx.nd.concatenate(ClassIds,axis=2)
    mask=Score>0.5
    print(mask)
    print(class_id)
    print(mx.nd.ones_like(class_id)*-1)
    class_id=mx.nd.where(mask,class_id,mx.nd.ones_like(class_id)*-1)
    Score=mx.nd.where(mask,Score,mx.nd.zeros_like(class_id))
    return class_id,Score
Data=mx.nd.random.uniform(shape=(4,5,6))###Data的Shape格式为(B,A,classNum+1)
ClassEncoder(Data)

NMS:

import numpy as np
import mxnet as mx
def bboxes_iou(PreBoxes,GtBoxes):
    assert PreBoxes.shape[1]==4 or GtBoxes.shape[1]==4,print('PreBoxes or GtBoxes shape must be (N,4)')
    TopLeft=np.maximum(PreBoxes[:,None,:2],GtBoxes[:,:2])##N*1*2,与M*2,maximum有广播机制
    DownRight=np.minimum(PreBoxes[:,None,2:],GtBoxes[:,2:])##输出Shape为N*M*4
    Intersection=np.prod(DownRight-TopLeft,axis=2)*(TopLeft<DownRight).all(axis=2)##Shpae为N*M

    AreaPre=np.prod(PreBoxes[:,2:]-PreBoxes[:,:2],axis=1)#Shape为N
    AreaGt=np.prod(GtBoxes[:,2:]-GtBoxes[:,:2],axis=1)#Shape为M

    IOUs=Intersection/(AreaPre[:,None]+AreaGt[:]-Intersection)

    return IOUs
###输入PreBoxes Shape为(B,A,4) A为Anchor数目,PreIDs Shape为(B,A,NumClass),PreScores Shape为(B,A,NumClass)
def NMS(PreBoxes,PreIds,PreScores,NumClass,Thresh):
    PickBoxes=[]
    PickScores=[]
    if isinstance(PreBoxes,mx.nd.NDArray):
        PreBoxes=PreBoxes.asnumpy()
    for i in range(NumClass):
        PickBox=[]
        PickScore=[]
        PreId=PreIds.slice_axis(axis=-1,begin=i,end=i+1)
        PreScore=PreScores.slice_axis(axis=-1,begin=i,end=i+1)
        if isinstance(PreId,mx.nd.NDArray) or isinstance(PreScore,mx.nd.NDArray):
            PreId=PreId.asnumpy()
            PreScore=PreScore.asnumpy()
        IdMask=PreId.flat==i
        PreScore=PreScore.flat[IdMask]
        PreBox=PreBoxes[IdMask]
        #print(PreBox)
        order=PreScore.argsort()[::-1]
        #PreScore=PreScore[order]
        #PreBox=PreBox[order]
        while order.size>0:
            PickBox.append(PreBox[order[0]])
            PickScore.append(PreScore[order[0]])
            IOUS=bboxes_iou(PreBox[order[0]].reshape((1,4)),PreBox[order])
            IOUMask=IOUS<Thresh
            order=order[IOUMask.flat]

        #PickBoxes.append(PickBox)
        PickBoxes.append([PickBox,PickScore])
        PickScores.append(PickScore)
    return PickBoxes,PickScores
PreBoxes=mx.nd.array([[1,1,4,4],[3,2,4,6],[4,4,5,6],[8,6,10,8]])
PreIds=mx.nd.array([[0,1],[0,1],[0,1],[0,1]])
PreScores=mx.nd.array([[0.6,0.4],[0.7,0.3],[0.8,0.2],[0,1]])
NMS(PreBoxes,PreIds,PreScores,2,0.5)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值