共计 2239 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
CCPD(Chinese City Parking Dataset)是目前国内最全面的车牌检测数据集之一,包含了不同天气、光照条件下的车牌图像,非常适合用于训练鲁棒的车牌检测模型。而 YOLO(You Only Look Once)作为当前流行的目标检测算法,其数据格式要求与 CCPD 原始标注格式存在较大差异,因此需要进行格式转换。

YOLO 格式的基本要求是:
- 每个图像对应一个.txt 文件,文件名相同
- 每行表示一个目标,格式为:
class_id x_center y_center width height - 坐标和尺寸都是相对于图像宽高的归一化值(0- 1 之间)
技术难点
CCPD 原始标注与 YOLO 格式的主要差异体现在:
- 坐标系统不同:CCPD 使用绝对坐标,YOLO 需要相对坐标
- 标注方式不同:CCPD 使用四点坐标表示车牌,YOLO 使用中心点 + 宽高
- 文件结构不同:CCPD 标注集中在一个文件,YOLO 需要每个图像单独标注
- 类别表示不同:CCPD 没有显式类别 ID,YOLO 需要明确类别编号
实现方案
下面是一个完整的 Python 转换脚本,实现了从 CCPD 到 YOLO 格式的转换:
import os
import cv2
import json
from pathlib import Path
def convert_ccpd_to_yolo(ccpd_annotation_path, output_dir, class_id=0):
"""
将 CCPD 标注转换为 YOLO 格式
:param ccpd_annotation_path: CCPD 标注文件路径
:param output_dir: YOLO 格式输出目录
:param class_id: 类别 ID(车牌默认为 0)"""
# 确保输出目录存在
os.makedirs(output_dir, exist_ok=True)
with open(ccpd_annotation_path, 'r') as f:
annotations = json.load(f)
for img_name, points in annotations.items():
try:
# 读取图像获取尺寸
img_path = os.path.join(os.path.dirname(ccpd_annotation_path), img_name)
img = cv2.imread(img_path)
if img is None:
print(f"警告:无法读取图像 {img_path}")
continue
img_h, img_w = img.shape[:2]
# 计算边界框(四点坐标转矩形)x_coords = [p[0] for p in points]
y_coords = [p[1] for p in points]
x_min, x_max = min(x_coords), max(x_coords)
y_min, y_max = min(y_coords), max(y_coords)
# 转换为 YOLO 格式(归一化中心坐标和宽高)x_center = (x_min + x_max) / 2 / img_w
y_center = (y_min + y_max) / 2 / img_h
width = (x_max - x_min) / img_w
height = (y_max - y_min) / img_h
# 写入 YOLO 格式文件
output_path = os.path.join(output_dir, Path(img_name).stem + '.txt')
with open(output_path, 'w') as f:
f.write(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
except Exception as e:
print(f"处理 {img_name} 时出错: {str(e)}")
# 使用示例
if __name__ == "__main__":
convert_ccpd_to_yolo("ccpd_annotations.json", "yolo_labels")
性能优化
当处理大规模 CCPD 数据集时,可以考虑以下优化策略:
- 内存管理:
- 使用生成器逐批处理图像,避免一次性加载所有数据
-
及时释放不再需要的图像内存
-
并行计算:
- 使用 Python 的 multiprocessing 模块实现多进程处理
-
将数据集分片,每个进程处理一部分数据
-
IO 优化:
- 使用 SSD 存储加速读写
- 合并小文件写入操作
避坑指南
在实际转换过程中,常见的错误及解决方案包括:
- 坐标归一化错误:
- 错误:忘记将坐标除以图像宽高
-
解决:确保所有坐标都转换为 0 - 1 之间的值
-
图像路径问题:
- 错误:图像路径拼接不正确
-
解决:使用 os.path.join 保证跨平台兼容性
-
四点坐标顺序混乱:
- 错误:四点坐标不是顺时针或逆时针顺序
-
解决:对点坐标进行排序后再计算边界框
-
图像加载失败:
- 错误:图像损坏或路径错误
-
解决:添加异常处理,跳过问题图像
-
类别 ID 冲突:
- 错误:多类别场景下类别 ID 定义混乱
- 解决:建立明确的类别映射表
扩展思考
本方案可以轻松适配到其他自定义数据集,主要修改点包括:
- 解析不同的原始标注格式
- 调整坐标转换逻辑
- 扩展多类别支持
对于其他四点标注的数据集,只需修改边界框计算部分;对于其他坐标表示的数据集,调整归一化计算方式即可。
实践任务
建议读者尝试以下实践:
- 下载 CCPD 数据集(至少 1000 张图像)
- 使用提供的脚本进行格式转换
- 使用 YOLOv5 或 YOLOv8 验证转换结果
- 尝试训练一个简单的车牌检测模型
通过实际动手操作,可以更深入地理解数据格式转换的关键点,为后续的模型训练打下坚实基础。
正文完
