CCPD数据集转YOLO格式实战指南:从数据解析到格式转换

1次阅读
没有评论

共计 2977 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

背景介绍

CCPD(Chinese City Parking Dataset)是一个大型车牌检测数据集,包含超过 30 万张车牌图像,广泛应用于车牌识别和车辆检测任务。而 YOLO(You Only Look Once)是一种流行的目标检测算法,其训练数据需要特定的格式。

CCPD 数据集转 YOLO 格式实战指南:从数据解析到格式转换

CCPD 数据集的特点:

  • 图像文件名包含车牌位置和角度信息
  • 使用四点坐标表示车牌位置
  • 包含多种光照和天气条件下的车牌图像

YOLO 格式要求:

  • 使用归一化的中心坐标和宽高表示目标位置
  • 每个图像对应一个.txt 标注文件
  • 类别标签为整数索引

两者之间的主要差异在于坐标表示方式,这带来了转换的主要挑战。

技术方案

1. CCPD 数据解析方法

CCPD 数据集的文件名包含了丰富的信息,我们需要从中提取出车牌的位置坐标。文件名格式通常为:

区域 - 车牌号 - 倾斜角度 - 亮度 - 模糊度 - 四个坐标点.jpg

我们需要特别关注的是最后的四个坐标点,它们以 _ 分隔,格式为x1,y1,x2,y2,x3,y3,x4,y4

2. 坐标转换算法

从四点坐标转换到 YOLO 格式的中心坐标和宽高,需要以下步骤:

  1. 计算四点坐标的最小外接矩形
  2. 将矩形坐标转换为中心坐标 (x_center, y_center) 和宽高(width, height)
  3. 将坐标归一化(除以图像宽高)
  4. 将类别索引(车牌通常为 0)和归一化坐标写入.txt 文件

3. 文件组织方式

转换后的文件应按照 YOLO 的标准格式组织:

  • 将所有图像放在 images 文件夹
  • 将所有标注文件放在 labels 文件夹
  • 保持图像和标注文件同名(仅扩展名不同)

代码实现

以下是完整的 Python 转换脚本:

import os
import cv2
import numpy as np

# 配置参数
data_dir = 'CCPD2020'  # CCPD 数据集目录
output_dir = 'yolo_format'  # 输出目录
class_id = 0  # 车牌类别 ID

# 创建输出目录
os.makedirs(os.path.join(output_dir, 'images'), exist_ok=True)
os.makedirs(os.path.join(output_dir, 'labels'), exist_ok=True)

# 遍历数据集
for filename in os.listdir(data_dir):
    if not filename.endswith('.jpg'):
        continue

    # 解析文件名获取坐标点
    parts = filename.split('-')
    coords = parts[-1].split('_')[-4:]
    coords = [list(map(int, c.split(','))) for c in coords]

    # 读取图像获取尺寸
    img_path = os.path.join(data_dir, filename)
    img = cv2.imread(img_path)
    img_h, img_w = img.shape[:2]

    # 计算最小外接矩形
    rect = cv2.minAreaRect(np.array(coords))
    box = cv2.boxPoints(rect)
    box = np.int0(box)

    # 获取矩形参数
    x_min, y_min = box.min(axis=0)
    x_max, y_max = box.max(axis=0)

    # 转换为 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

    # 写入标注文件
    base_name = os.path.splitext(filename)[0]
    label_path = os.path.join(output_dir, 'labels', base_name + '.txt')
    with open(label_path, 'w') as f:
        f.write(f'{class_id} {x_center} {y_center} {width} {height}\n')

    # 复制图像
    output_img_path = os.path.join(output_dir, 'images', filename)
    cv2.imwrite(output_img_path, img)

print('转换完成!')

验证方法

转换完成后,我们需要验证结果是否正确:

  1. 随机选择几张转换后的图像和对应的标注文件
  2. 使用以下脚本可视化检查标注框是否正确
import cv2
import random

# 随机选择一张图像
image_files = os.listdir(os.path.join(output_dir, 'images'))
sample_image = random.choice(image_files)

# 读取图像和标注
img = cv2.imread(os.path.join(output_dir, 'images', sample_image))
label_path = os.path.join(output_dir, 'labels', os.path.splitext(sample_image)[0] + '.txt')

with open(label_path, 'r') as f:
    line = f.readline().strip()
    class_id, x_center, y_center, width, height = map(float, line.split())

# 将 YOLO 坐标转换为图像坐标
img_h, img_w = img.shape[:2]
x_center *= img_w
y_center *= img_h
width *= img_w
height *= img_h
x_min = int(x_center - width/2)
y_min = int(y_center - height/2)
x_max = int(x_center + width/2)
y_max = int(y_center + height/2)

# 绘制矩形
cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)

# 显示结果
cv2.imshow('Validation', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

避坑指南

  1. 坐标归一化处理
  2. 确保所有坐标都除以图像的实际宽高
  3. 注意 OpenCV 读取图像时尺寸顺序是(height, width)

  4. 图像尺寸不一致问题

  5. CCPD 数据集中的图像尺寸可能不同
  6. 必须对每张图像单独计算归一化系数

  7. 特殊字符处理

  8. 文件名中可能包含特殊字符
  9. 建议在解析前先对文件名进行规范化处理

  10. 四点坐标顺序问题

  11. 四点坐标可能不是顺时针或逆时针顺序
  12. 使用 cv2.minAreaRect() 可以自动处理这个问题

性能优化建议

  1. 多进程处理
  2. 对于大规模数据集,可以使用 Python 的 multiprocessing 模块加速处理

  3. 增量处理

  4. 记录已处理的文件,避免重复处理

  5. 内存优化

  6. 对于非常大的图像,可以分块读取处理

  7. 并行 I /O

  8. 使用异步 I / O 操作提高文件读写效率

扩展功能

转换完成后,您可以进一步:

  1. 实现数据增强(旋转、缩放、色彩变换等)
  2. 添加可视化工具实时检查标注质量
  3. 将转换流程封装为命令行工具
  4. 集成到自动化训练流程中

希望这篇指南能帮助您顺利完成 CCPD 到 YOLO 格式的转换,祝您的目标检测项目取得成功!

正文完
 0
评论(没有评论)