计算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)*(TopLeft0:
PickBox.append(PreBox[order[0]])
PickScore.append(PreScore[order[0]])
IOUS=bboxes_iou(PreBox[order[0]].reshape((1,4)),PreBox[order])
IOUMask=IOUS