参考资料
使用
画框源码
void draw_box(image a, int x1, int y1, int x2, int y2, float r, float g, float b)
{
//normalize_image(a);
int i;
if(x1 < 0) x1 = 0;
if(x1 >= a.w) x1 = a.w-1;
if(x2 < 0) x2 = 0;
if(x2 >= a.w) x2 = a.w-1;
if(y1 < 0) y1 = 0;
if(y1 >= a.h) y1 = a.h-1;
if(y2 < 0) y2 = 0;
if(y2 >= a.h) y2 = a.h-1;
for(i = x1; i <= x2; ++i){
a.data[i + y1*a.w + 0*a.w*a.h] = r;
a.data[i + y2*a.w + 0*a.w*a.h] = r;
a.data[i + y1*a.w + 1*a.w*a.h] = g;
a.data[i + y2*a.w + 1*a.w*a.h] = g;
a.data[i + y1*a.w + 2*a.w*a.h] = b;
a.data[i + y2*a.w + 2*a.w*a.h] = b;
}
for(i = y1; i <= y2; ++i){
a.data[x1 + i*a.w + 0*a.w*a.h] = r;
a.data[x2 + i*a.w + 0*a.w*a.h] = r;
a.data[x1 + i*a.w + 1*a.w*a.h] = g;
a.data[x2 + i*a.w + 1*a.w*a.h] = g;
a.data[x1 + i*a.w + 2*a.w*a.h] = b;
a.data[x2 + i*a.w + 2*a.w*a.h] = b;
}
}
代码在./src/image.c
中,从源码中可以看出,YOLO
预测值为矩阵的左上角坐标和右下角坐标。(并不是,这是经过转换之后,在网络中流动的是anchor box,即(x,y)
在box中心的高度,然后再根据数据结果,进行转换。
YOLOv2 中的Box格式----anchor box
用于准备数据的voc_label.py
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
size
是图像的width
和height
,box
参数为xmin, xmax,yin,ymax
。所以传入的是矩形框左上和右下两个角点的坐标,然后输出值是标准化的图像中心坐标和图像宽度和高度。
实例如下:
2008_000002.xml
<annotation>
<folder>VOC2012</folder>
<filename>2008_000002.jpg</filename>
<source>
<database>The VOC2008 Database</database>
<annotation>PASCAL VOC2008</annotation>
<image>flickr</image>
</source>
<size>
<width>500</width>
<height>375</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>tvmonitor</name>
<pose>Frontal</pose>
<truncated>0</truncated>
<occluded>0</occluded>
<bndbox>
<xmin>34</xmin>
<ymin>11</ymin>
<xmax>448</xmax>
<ymax>293</ymax>
</bndbox>
<difficult>0</difficult>
</object>
</annotation>
经过转换得到的标记文件如下:
19 0.482 0.405333333333 0.828 0.752
其中,第一个数值表示分类标签,后四个值分别表示均一化的x, y, width, height