YoloV3 Anchor生成正负样本 | 你好陌生人
Tell
Anything can I help you ?
Menu
The menu of my blog
log out
log out

YoloV3 Anchor生成正负样本

关于手撸YoloV3代码的可以看一下b站一个up主:深度学习麋了鹿
这里主要讲的是YoloV3中正负样本的生成以及我个人的理解。

1.正负样本生成的原理

1.1正样本的选择

首先先计算$gt$的中心落在哪个$grid$上,总共有3个特征层以及3个$anchor$总共生成9个先验框,选出与$gt$的$IOU$最大的那个先验框做为正样本。

1.2负样本的选择

计算各个先验框和所有的目标$gt$之间的$IOU$,如果某先验框和图像中所有物体最大的IOU都小于阈值(一般0.5),那么就认为该先验框不含目标,记作负样本,其置信度应当为0

1.3其他样本

对于剩下$IOU$大于阈值但不是与$gt$的$IOU$最大的那部分,这句话可能有点绕,可以这样简单理解,这个班上只要第一名作为学习的榜样,分数低于60分的大家作为反面教材,剩下大于60分但又不是第一名的那些人大家就不用管他了。

2.代码部分的讲解

这里贴一下麋鹿的手撸代码这部分就是$label$的生成,我个人也是按照他的视频讲解来写的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  labels={}
w,h=img.size
case=416/w
for feature_size,_antors in antors.items():
labels[feature_size]=np.zeros(shape=(feature_size,feature_size,3,5+CLASS_NUM))

for box in boxes:
cls,cx,cy,w,h=box
cx, cy,w,h=cx*case,cy*case,w*case,h*case
_x,x_index=math.modf(cx*feature_size/DATA_WIDTH)
_y,y_index=math.modf(cx*feature_size/DATA_HEIGHT)
for i,antor in enumerate(_antors):
area=w*h
iou=min(area,ANTORS_AREA[feature_size][i])/max(area,ANTORS_AREA[feature_size][i])
p_w, p_h = w / antor[0], h / antor[1]
labels[feature_size][int(y_index),int(x_index),i]=np.array([iou,_x,_y,np.log(p_w),np.log(p_h),*one_hot(CLASS_NUM,int(cls))])
1
2
w,h=img.size
case=416/w

这部分主要将中心点和宽高转移到对应尺寸上,比如当你图像的$size$是$(3.,3)$的时候你的中心点是$(2,2)$,当你reisze成$(9,9)$的时候,你的中心点应该转换成$(5,5)$

1
labels[feature_size]=np.zeros(shape=(feature_size,feature_size,3,5+CLASS_NUM))

个人理解首先每个$grid$里面都应该对应一个宽高中心的置信度类别,所以最后的一个维度是:5+CLASS_NUM,然后3对应的是RGB三个通道,feature_size就是对应我们将图像分成几个部分。

1
2
_x,x_index=math.modf(cx*feature_size/DATA_WIDTH)
_y,y_index=math.modf(cx*feature_size/DATA_HEIGHT)

这个部分是将中心点转换到对应的grid中并且获得他的偏移量拿下面这个例子来说,假设图像的size是39*39的$gt$的中心为$(20,20)$那么此时中心点坐标其实转换到了$(1,1)$再加上$(7,7)$的偏移。

1
iou=min(area,ANTORS_AREA[feature_size][i])/max(area,ANTORS_AREA[feature_size][i])

他这里的$IOU$的计算有点问题,我之后会一期关于各种IOU的讲解。

1
p_w, p_h = w / antor[0], h / antor[1]

这里的主要计算的是$gt$的宽高和$anchor$宽高的比值,注意这里损失函数的时候宽高做了$\log$处理是为了防止过宽或者过高影响网络。

1
labels[feature_size][int(y_index),int(x_index),i]=np.array([iou,_x,_y,np.log(p_w),np.log(p_h),*one_hot(CLASS_NUM,int(cls))])

这部分主要是吧刚刚算出来正样本加入进去用之前得到的$x,y$的中心格位置,或者你这边直接归一化也可以。

这里讲一句对于正负样本不均匀的理解,举个例子就像小时候父母告诉我们做这个不好,做那个不好,实际上需要怎么做的好有时候他们并不会告诉我,导致我们只知道这样做是不好的,但是不知道怎么往好的方面发展。