![[深度学习] CCPD数据集实战:从数据解析到模型训练全流程](http://pic.xiahunao.cn/yaotu/[深度学习] CCPD数据集实战:从数据解析到模型训练全流程)
1. CCPD数据集概述与下载指南CCPDChinese City Parking Dataset是目前国内规模最大、标注最完善的开源车牌数据集之一。我第一次接触这个数据集是在2019年做智能交通项目时当时为了找合适的车牌数据翻遍了国内外平台直到发现CCPD才真正解决了数据瓶颈问题。这个数据集分为两个主要版本CCPD2019包含25万蓝色普通车牌图像CCPD2020专为新能源车设计的绿色车牌数据集数据集最让我惊喜的是其丰富的场景覆盖不同天气条件雨雪雾各种拍摄角度水平倾斜最高50度多种光照情况过曝/欠曝运动模糊等真实场景干扰下载方式很简单# CCPD2019 (12.26GB) wget https://example.com/ccpd2019.zip # 替换为实际下载链接 # CCPD2020 (865MB) wget https://example.com/ccpd2020.zip实测发现百度云下载速度更快建议用官方提供的百度云链接。下载后记得校验MD5值我遇到过两次下载中断导致文件损坏的情况。2. 数据标注解析实战CCPD最特别的是其文件名即标注的设计。刚开始用的时候觉得这种设计很反人类但熟悉后发现其实非常高效。来看个典型文件名示例025-95_113-154383_386473-386473_177454_154383_363402-0_0_22_27_27_33_16-37-15.jpg用Python解析非常方便def parse_filename(filename): parts filename.split(-) return { ratio: parts[0], # 车牌区域占比 angle: list(map(int, parts[1].split(_))), # 水平/垂直倾斜角 bbox: [list(map(int, p.split())) for p in parts[2].split(_)], # 边界框 vertices: [list(map(int, p.split())) for p in parts[3].split(_)], # 四顶点坐标 plate_num: decode_plate(parts[4]), # 车牌号码 brightness: int(parts[5]), # 亮度值 blurriness: int(parts[6].split(.)[0]) # 模糊度 }车牌号码的解码需要特别注意provinces [皖, 沪, 津, 渝, 冀, 晋, 蒙, 辽, 吉, 黑, 苏, 浙, 京, 闽, 赣, 鲁, 豫, 鄂, 湘, 粤, 桂, 琼, 川, 贵, 云, 藏, 陕, 甘, 青, 宁, 新] def decode_plate(plate_str): codes list(map(int, plate_str.split(_))) province provinces[codes[0]] chars [chr(ord(A)x) if x26 else str(x-26) for x in codes[1:]] return province .join(chars)3. 数据预处理技巧3.1 图像增强方案在车牌识别任务中我常用的增强组合是transform transforms.Compose([ transforms.ColorJitter(brightness0.3, contrast0.3), # 应对光照变化 transforms.RandomRotation(10), # 增强旋转鲁棒性 transforms.RandomPerspective(distortion_scale0.2), # 模拟视角变化 GaussianBlur(kernel_size3) # 抗模糊 ])3.2 数据清洗经验CCPD虽然标注质量整体不错但仍有约3%的脏数据需要处理。我通常用以下规则过滤检查边界框是否超出图像范围验证车牌号码是否符合编码规则剔除亮度/模糊度极值样本def is_valid_sample(metadata): # 检查边界框 x1, y1 metadata[bbox][0] x2, y2 metadata[bbox][1] if not (0 x1 x2 720 and 0 y1 y2 1160): return False # 检查车牌号码 plate metadata[plate_num] if len(plate) not in (7,8) or not plate[0] in provinces: return False return True4. 模型训练实战4.1 YOLOv5检测模型配置推荐使用以下配置进行训练# yolov5s_ccpd.yaml nc: 1 # 只有车牌一个类别 depth_multiple: 0.33 width_multiple: 0.50 anchors: - [10,13, 16,30, 33,23] # P3/8 - [30,61, 62,45, 59,119] # P4/16 - [116,90, 156,198, 373,326] # P5/32启动训练命令python train.py --img 640 --batch 32 --epochs 100 --data ccpd.yaml --cfg yolov5s_ccpd.yaml --weights yolov5s.pt4.2 LPRNet识别模型优化针对车牌识别任务我对原始LPRNet做了三点改进增加空间注意力模块调整CNN通道数适配车牌长宽比使用Focal Loss解决字符类别不平衡关键修改部分class EnhancedLPRNet(nn.Module): def __init__(self, lpr_max_len8): super().__init__() self.backbone nn.Sequential( nn.Conv2d(3, 64, 3, 1), nn.BatchNorm2d(64), SpatialAttention(), # 新增注意力 nn.ReLU(), # ... 其他层保持不变 ) self.loss FocalLoss(gamma2) # 替换原始CrossEntropy5. 模型部署与性能优化5.1 TensorRT加速实践将PyTorch模型转为TensorRT能获得3-5倍加速# 转换脚本示例 builder trt.Builder(TRT_LOGGER) network builder.create_network() parser trt.OnnxParser(network, TRT_LOGGER) # 加载ONNX模型 with open(lprnet.onnx, rb) as f: parser.parse(f.read()) # 配置优化参数 config builder.create_builder_config() config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 30) engine builder.build_engine(network, config)5.2 端侧部署技巧在树莓派等边缘设备上我推荐使用量化后的TFLite模型开启ARM NEON加速采用多线程流水线处理实测性能对比设备原始模型优化后提升Jetson Nano12 FPS28 FPS2.3xRaspberry Pi 43 FPS9 FPS3x6. 常见问题解决方案问题1小尺寸车牌检测效果差解决方案在YOLOv5中添加小目标检测层修改模型配置# 添加P2检测头 head: [[-1, 1, Conv, [256, 1, 1]], [-1, 1, nn.Upsample, [None, 2, nearest]], [[-1, 3], 1, Concat, [1]], [-1, 3, C3, [256, False]], [-1, 1, Conv, [256, 3, 2]], [[-1, 4], 1, Concat, [1]], [-1, 3, C3, [512, False]], # ... 原有结构 ]问题2新能源车牌识别率低根本原因CCPD2020数据量较少解决方案使用迁移学习先用CCPD2019预训练添加新能源车牌数据增强# 模拟绿色车牌色调 def green_plate_aug(img): hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsv[:,:,0] hsv[:,:,0] * 0.7 # 调整色相 return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)在实际项目中建议定期用bad case分析工具找出模型弱点有针对性地补充训练数据。我开发了一个自动化分析工具可以自动聚类识别错误的样本类型。