Pascal VOC XML 2 YoLo txt format
Published:
0.结论
在将Pascal VOC的Xml格式转为YoLo的txt格式时,计算中心点坐标需要减去1。 具体解释见2.2 追根溯源
1. 问题
在对Pascal VOC xml格式的数据转为yolo的txt格式数据时,可能会看到以下两种代码:
# https://christianbernecker.medium.com/convert-bounding-boxes-from-coco-to-pascal-voc-to-yolo-and-back-660dc6178742
def pascal_voc_to_yolo(x1, y1, x2, y2, image_w, image_h):
return [((x2 + x1)/(2*image_w)), ((y2 + y1)/(2*image_h)), (x2 - x1)/image_w, (y2 - y1)/image_h]
# https://cvmart.net/document 这里的数据预处理
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1 # 有的减去1,有的不减
y = (box[2] + box[3])/2.0 - 1
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)
不难发现,二者的主要区别在于计算中心点时,是否要减去1
2. 探索问题
2.1 自然的想法
假设有一个$28\times 28$的图像,其中存在一个bounding box的信息为: \(x_1=1,x_2=7,y_1=2,y_2=7\)
- 人工计算的话,可知:对于
x
方向,中心点坐标为4,而对于y
方向,中心点坐标为4.5。 - 使用程序计算(未除以图像的高和宽时的中心点):
- 不减1的中心点:x:(1+7)/2.0=4.0; y:(2+7)/2.0=4.5;
- 减去1的中心点:x:(1+7)/2.0-1=3.0; y:(2+7)/2.0-1=3.5;
- 则除以图像的高宽后真正的中心点坐标是:
- 不减1的中心点:(x,y)=(0.14285,0.16071)
- 减去1的中心点:(x,y)=(0.10714,0.125)
- 这样看起来似乎没有什么问题。
2.2 追根溯源
中心点坐标减去1的来源是这里:darknet/scripts/voc_label.py
转换后的yolo的bounding box的
xyhw
值的范围是[0,1]
issue中也有一些讨论:What is the reason for changing code in the scripts/voc_label.py? #341,大意如下:
图像的像素值可以是1~width,也可以是0~width-1,
- 举例来说:假设width=5,
- 若坐标是从1开始,则(1+5)/2-1=2;
- 若坐标是从0开始,则(0+4)/2=2;
- 很明显,基于1的坐标系统,如果不减去1的话会不一致
- 从转换后yolo的bounding box的xyhw的值的范围是[0,1]考虑:
- 对于从1开始的像素,转换后的最小值是(1+1)/2/width,永远不会为0
- 对于从0开始的像素,转换后的最小值是(0+0)/2/width,可以满足[0,1]的范围。
- 以上,减去1是一个正确的选择