1. 数据集简介
DroneVehicle 是由天津大学收集并标注的大型无人机航拍车辆数据集。该数据集包含 56,878 幅图像,其中一半为 RGB 图像,另一半为红外图像。我们对五个类别进行了带有方向性边界框的丰富标注:
- Car (汽车): RGB 389,779 个标注,红外 428,086 个
- Truck (卡车): RGB 22,123 个标注,红外 25,960 个
- Bus (公交车): RGB 15,333 个标注,红外 16,590 个
- Van (面包车): RGB 11,935 个标注,红外 12,708 个
- Freight Car (货车): RGB 13,400 个标注,红外 17,173 个
2. 数据预处理
原始图片四周有宽度为 100 像素的白色边框,导致下载的图片尺寸为 840 x 712。为了适配 YOLO 训练要求,我们需要去除白边并将图像尺寸调整为 640 x 512。

处理前后的对比效果如上所示。下面是去除白边的 Python 脚本,逻辑很简单,直接裁剪坐标区域即可:
import numpy as np
import cv2
import os
from tqdm import tqdm
def create_file(output_dir_vi, output_dir_ir):
if not os.path.exists(output_dir_vi):
os.makedirs(output_dir_vi)
if not os.path.exists(output_dir_ir):
os.makedirs(output_dir_ir)
print(f'Created folder: ({output_dir_vi}); ({output_dir_ir})')
def update(input_img_path, output_img_path):
image = cv2.imread(input_img_path)
# 裁剪坐标为 [y0:y1, x0:x1]
cropped = image[100:612, 100:740]
cv2.imwrite(output_img_path, cropped)
dataset_dir_vi = r'valimg'
output_dir_vi = r'valimg2'
dataset_dir_ir = r'valimgr'
output_dir_ir = r'valimgr2'
create_file(output_dir_vi, output_dir_ir)
image_filenames_vi = [(os.path.join(dataset_dir_vi, x), os.path.join(output_dir_vi, x)) for x in os.listdir(dataset_dir_vi)]
image_filenames_ir = [(os.path.join(dataset_dir_ir, x), os.path.join(output_dir_ir, x)) for x in os.listdir(dataset_dir_ir)]
print('Start transforming vision images...')
for path in tqdm(image_filenames_vi):
update(path[0], path[1])
print('Start transforming infrared images...')
for path in tqdm(image_filenames_ir):
update(path[0], path[1])
3. 标签格式转换
3.1 获取 COCO 格式标签
首先从官方仓库下载 DroneVehicle 的 COCO 格式检测框标签文件。

3.2 转为 VOC 格式
这里我使用的是 X-AnyLabeling 作为标注软件进行中间转换。

3.3 转为 YOLO 格式
在转换过程中发现,部分检测框的位置可能会超出图片边缘,导致直接转成 YOLO 时出现负坐标或大于 1 的归一化坐标值,这会严重影响模型训练。因此,在转换时需对这部分检测框进行特殊处理(如截断至边界)。虽然 X-AnyLabeling 支持直接导出 YOLO 格式,但经测试它并未处理大于 1 的坐标值问题。
以下是 xml2txt.py 脚本,核心在于读取真实图片宽高并修正越界坐标:
import xml.etree.ElementTree as ET
import shutil
import os
import imagesize
object = 'datasets'
if os.path.exists("./%s/labels/" % object):
shutil.rmtree("./%s/labels/" % object)
os.makedirs("./%s/labels/" % object)
sets = ['train', 'val']
classes = ["car", "truck", "bus", "van", "freight_car"]
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)
def convert_annotation(image_id):
in_file = open('./%s/xml/%s.xml' % (object, image_id))
out_file = open('./%s/labels/%s.txt' % (object, image_id), 'w')
image_file = open('./%s/images/%s.jpg' % (object, image_id))
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
# 这里的 width 和 height 在 Autolabelimg 下自动标注可能会被修改,需替换成图片的真实宽高
w, h = imagesize.get(image_file.name)
for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult) == 1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
xmin = float(xmlbox.find('xmin').text)
xmax = float(xmlbox.find('xmax').text)
ymin = float(xmlbox.find('ymin').text)
ymax = float(xmlbox.find('ymax').text)
# 处理越界坐标
xmin = xmin if xmin >= 0 else 0.0
xmax = xmax if xmax <= w else float(w)
ymin = ymin if ymin >= 0 else 0.0
ymax = ymax if ymax <= h else float(h)
b = (xmin, xmax, ymin, ymax)
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
for image_set in sets:
if not os.path.exists('./%s/labels/' % object):
os.makedirs('./%s/labels/' % object)
image_ids = open('./%s/ImageSets/%s.txt' % (object, image_set)).read().strip().split()
list_file = open('./%s/%s.txt' % (object, image_set), 'w')
for image_id in image_ids:
list_file.write('./images/%s.jpg\n' % (image_id))
convert_annotation(image_id)
list_file.close()
3.4 数据集划分
我只处理了可见光部分的数据集,红外光处理逻辑相同。由于不需要测试集,我将验证集和测试集按比例合并:
- 验证集: 原验证集 1469 个 + 原测试集 8980 个的 20% = 3265 个数据
- 训练集: 原训练集 17990 个 + 原测试集 8980 个的 80% = 25174 个数据
整理后的目录结构如下:

此时数据集已是标准的 YOLO 格式,可以直接开始训练。
4. 模型训练
我选择了 YOLO11s 的网络权重进行训练,共训练 100 个 epoch。结果如下:

可以看到训练曲线收敛良好,指标表现不错。
验证集上的标签可视化效果:

5. 推理预测
使用训练好的模型进行预测,结果比较理想。

第一张图来自验证集,第二张图取自网络公开样本,模型均能准确识别目标。
6. 总结与注意事项
从训练结果来看,针对垂直视角的无人机航拍数据,效果尚可。但需注意以下局限性:
- 如果是斜视视角,检测效果会下降。
- 目前仅测试了可见光,红外光及多模态融合效果未经过验证。
关键注意点:
- 务必处理图片四周的白边。
- 转换标签时注意处理超出图片边缘的检测框坐标,防止出现负值或归一化后大于 1 的情况。

