共计 2619 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
CCPD 数据集作为车牌检测领域的常用数据集,采用 XML 格式存储标注信息,而 YOLO 目标检测框架要求标注文件为特定格式的 TXT 文件。两种格式的主要差异体现在:

- 坐标表示方式:CCPD 使用绝对像素坐标,YOLO 需要归一化的相对坐标
- 文件结构:CCPD 每个 XML 对应一张图片,YOLO 需要将所有标注合并到单个 TXT
- 类别标识:CCPD 可能有多个车牌类别,YOLO 通常需要统一为单一类别
技术方案设计
我们设计了一个 Python 自动化转换脚本,主要处理流程如下:
- XML 解析:使用 ElementTree 读取 CCPD 标注文件
- 坐标转换:将绝对坐标转换为 YOLO 要求的归一化相对坐标
- 格式生成:按 YOLO 格式要求组织输出内容
- 错误处理:记录转换过程中的异常情况
- 进度显示:使用 tqdm 展示处理进度
完整代码实现
#!/usr/bin/env python3
"""CCPD to YOLO format converter"""
import argparse
import xml.etree.ElementTree as ET
from pathlib import Path
from tqdm import tqdm
def parse_args():
parser = argparse.ArgumentParser(description='CCPD to YOLO format converter')
parser.add_argument('--ccpd_dir', type=str, required=True, help='CCPD dataset directory')
parser.add_argument('--output_dir', type=str, required=True, help='Output directory for YOLO format')
parser.add_argument('--class_id', type=int, default=0, help='YOLO class ID for license plates')
return parser.parse_args()
def convert_bbox(size: tuple, box: list) -> list:
"""Convert CCPD bbox to YOLO format"""
dw = 1.0 / size[0]
dh = 1.0 / size[1]
x = (box[0] + box[2]) / 2.0 * dw
y = (box[1] + box[3]) / 2.0 * dh
w = (box[2] - box[0]) * dw
h = (box[3] - box[1]) * dh
return [x, y, w, h]
def process_file(xml_path: Path, output_dir: Path, class_id: int):
"""Process single XML file"""
try:
tree = ET.parse(xml_path)
root = tree.getroot()
# Get image size
size = root.find('size')
width = int(size.find('width').text)
height = int(size.find('height').text)
# Prepare output path
txt_path = output_dir / f"{xml_path.stem}.txt"
# Process each object
with open(txt_path, 'w') as f:
for obj in root.iter('object'):
bbox = obj.find('bndbox')
box = [float(bbox.find('xmin').text),
float(bbox.find('ymin').text),
float(bbox.find('xmax').text),
float(bbox.find('ymax').text)
]
yolo_box = convert_bbox((width, height), box)
f.write(f"{class_id} {' '.join([str(x) for x in yolo_box])}\n")
except Exception as e:
print(f"Error processing {xml_path}: {str(e)}")
def main():
args = parse_args()
ccpd_dir = Path(args.ccpd_dir)
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
xml_files = list(ccpd_dir.glob('*.xml'))
print(f"Found {len(xml_files)} XML files to process")
for xml_file in tqdm(xml_files, desc='Processing'):
process_file(xml_file, output_dir, args.class_id)
print(f"Conversion complete. Output saved to {output_dir}")
if __name__ == '__main__':
main()
验证环节
转换完成后,建议使用 OpenCV 验证转换结果是否正确:
- 加载原始图片和转换后的 YOLO 标注
- 将归一化坐标转换回像素坐标
- 使用 cv2.rectangle 绘制检测框
- 显示图片确认标注框位置正确
避坑指南
- 坐标越界处理 :确保转换后的坐标值在[0,1] 范围内,可以添加边界检查
- 图像路径编码:Windows 系统下注意处理路径中的中文和特殊字符
- 内存优化:处理大型数据集时,建议分批处理而非一次性加载所有文件
- 多类别处理:如果 CCPD 包含多种车牌类型,需要调整 class_id 处理逻辑
扩展思考
本方案可以扩展适配其他目标检测框架,主要需要考虑:
- 不同框架的标注格式要求(如 COCO、PASCAL VOC 等)
- 坐标表示方式的差异(如是否归一化、中心点或角点表示等)
- 类别 ID 的映射关系
通过抽象出格式转换的核心逻辑,可以构建通用的数据集转换工具,支持多种框架之间的数据格式转换。
总结
本文提供的解决方案实现了 CCPD 数据集到 YOLO 格式的高效转换,通过自动化脚本处理了标注格式差异的核心问题。代码包含完整的错误处理和进度显示功能,可直接应用于实际项目。验证环节确保转换质量,避坑指南帮助开发者避免常见问题。
正文完
发表至: 未分类
近一天内
