yolov3 中box坐标的处理

版权声明:https://blog.csdn.net/z0n1l2 https://blog.csdn.net/z0n1l2/article/details/84076775

yolov2吸收faster rcnn的anchor box机制时遇到训练不稳定的问题,分析认为是bbox坐标回归时没有限制,导致anchor box可能会去预测一个距离很远的object,效率不高,因此yolov2对bbox的坐标进行一系列的处理,令anchor box只会对邻近的object负责。阅读论文和代码时难以理解这个机制,以下是个人的一些分析,不保证正确,欢迎讨论指正。

在这里插入图片描述

公式中 ( t x , t y , t w , t h ) (t_x,t_y,t_w,t_h) 是预测目标,上述公式定义了如何从 ( t x , t y , t w , t h ) (t_x,t_y,t_w,t_h) 到真实坐标 ( b x , b y , b w , b h ) (b_x,b_y,b_w,b_h) 进行转换。需要注意的是 ( t x , t y , t w , t h ) (t_x,t_y,t_w,t_h) ( t x , t y ) (t_x,t_y) 对应的是anchor box的中心点坐标(偏移),而不是通常的左上角。

box get_yolo_box(float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int w, int h, int stride)
{
    box b;
    b.x = (i + x[index + 0*stride]) / lw;
    b.y = (j + x[index + 1*stride]) / lh;
    b.w = exp(x[index + 2*stride]) * biases[2*n]   / w;
    b.h = exp(x[index + 3*stride]) * biases[2*n+1] / h;
    return b;
}

float delta_yolo_box(box truth, float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int w, int h, float *delta, float scale, int stride)
{
    box pred = get_yolo_box(x, biases, n, index, i, j, lw, lh, w, h, stride);
    float iou = box_iou(pred, truth);

    float tx = (truth.x*lw - i);  //输入特征图尺寸
    float ty = (truth.y*lh - j);
    float tw = log(truth.w*w / biases[2*n]); //网络输入图尺寸
    float th = log(truth.h*h / biases[2*n + 1]);

    //scale = 2 - groundtruth.w * groundtruth.h 
    delta[index + 0*stride] = scale * (tx - x[index + 0*stride]); 
    delta[index + 1*stride] = scale * (ty - x[index + 1*stride]);
    delta[index + 2*stride] = scale * (tw - x[index + 2*stride]);
    delta[index + 3*stride] = scale * (th - x[index + 3*stride]);
    return iou;
}

上述两个函数来自yolov3的yolo层代码,其中函数参数float* x来自前一个卷积层的输出,shape = (C,H,W)
其中(H,W)表示特征图的宽高,通道C依次是 ( t x , t y , t w , t h , o b j e c t n e s s , s c o r e   o f   c l a s s i ) (t_x,t_y,t_w,t_h,objectness,score \ of \ class_i) ( t x , t y , t w , t h , o b j e c t n e s s ) (t_x,t_y,t_w,t_h,objectness) 利用sigmoid函数变换到了 [ 0 , 1 ] [0,1] 之间。

先来看函数get_yolo_box()的参数,biases中存储的是预定以的anchor box的宽和高(输入图尺度),(lw,lh)是yolo层输入的特征图尺度,(w,h)是整个网络输入图尺度,get_yolo_box()函数利用了论文截图中的公式,而且把结果分别利用特征图宽高和输入图宽高做了归一化。既然这个机制是用来限制回归,避免预测很远的目标,那么这个预测范围是多大呢?(b.x,by)最小是(i,j),最大是(i+1,x+1),即中心点在特征图上最多一定一个像素(假设输入图下采样n得到特征图,特征图中一个像素对应输入图的n个像素)(b.w,b.h)最大是(2.7 * anchor.w,2.7*anchor.h),最小就是(anchor.w,anchor.h),这是在输入图尺寸下的值。

delta_yolo_box()负责计算 ( t x , t y , t w , t h , o b j e c t n e s s ) (t_x,t_y,t_w,t_h,objectness) 的误差,其参数和get_yolo_box()类似,truth是groundtruth box,也是用输入图宽高归一化后的(中心点,宽高)。但其中的scale很奇怪,根据代码
sclae = 2 - truth.w * truth.h, 其含义还没理解。

猜你喜欢

转载自blog.csdn.net/z0n1l2/article/details/84076775