yolov3训练时在cfg和代码里面会有一些数据增强参数,但其中,真正发生作用的只有部分参数。本文结合代码来梳理哪些参数在真正参与数据增强及其运行原理。
cfg里面常用的数据增强参数如下所示:
训练时加载数据的入口函数如下:
其中真正参与数据增强的参数如红框所示。眼尖的读者可能会发现 jitter并没有出现在上面所示的cfg示意图中,的确如此,不过它是来自cfg中另外一部分:
显然,后面3个参数hue, saturation以及exposure来自上面所示的cfg。
这里,有个发现是angle并没有参与数据增强。很多文章都是前篇一律说,训练时会在(-angle,angle)中取一个随机值来旋转训练图片进行训练,但事实真相是,angle并没有被使用,无论设什么值对训练结果没有任何帮助。 进一步分析,为什么darknet作者没有用它,我想,原因是,当图片旋转后,对应的ground truth boxes也要跟着旋转,然而,yolov里面并不支持旋转的标注框,而且标注框旋转后可能出图像边界,从而丢失部分目标。
jitter是用来对图片宽高比例进行一些小的变化
float dw = jitter * orig.w;
float dh = jitter * orig.h;
float new_ar = (orig.w + rand_uniform(-dw, dw)) / (orig.h + rand_uniform(-dh, dh));
hue, saturation以及exposure一起作为random_distort_image(...)参数来对图像亮度、色度进行随机调节。细节请看下面代码的注释。
void random_distort_image(image im, float hue, float saturation, float exposure)
{
float dhue = rand_uniform(-hue, hue);//random values in (-hue, hue)
float dsat = rand_scale(saturation); //random value in (1, saturation)
float dexp = rand_scale(exposure); //random value in (1, exposure)
distort_image(im, dhue, dsat, dexp);
}
void distort_image(image im, float hue, float sat, float val)
{
rgb_to_hsv(im); //convert rgb to hsv firstly
scale_image_channel(im, 1, sat); //sat scale
scale_image_channel(im, 2, val); //value(brightness) scale
int i;
for(i = 0; i < im.w*im.h; ++i){
im.data[i] = im.data[i] + hue; //add hue value
if (im.data[i] > 1) im.data[i] -= 1;
if (im.data[i] < 0) im.data[i] += 1;
}
hsv_to_rgb(im);
constrain_image(im);
}
flip虽然没在配置文件里面,但是代码里面有使用。
int flip = rand()%2;
if(flip) flip_image(sized);
如上分析,cfg里面的angle并没有使用来增强数据,所以需要线下对样本数据来做旋转。 jitter, hue, saturation以及exposure还有flip有在用,但是其数值可以根据自己的场景来进行调整。此外,还可以增加些其它数据增强参数,比如blur等,当然这需要相应的修改darknet框架代码。