计算NMS以及Map(一)

    xiaoxiao2023-10-23  174

    计算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)

     

    最新回复(0)