共计 1326 个字符,预计需要花费 4 分钟才能阅读完成。
背景与问题分析
CCPD 数据集作为国内最大的车牌检测公开数据集,在实际落地时会遇到几个典型挑战:

- 光照条件复杂:停车场夜间红外补光、强光反射等情况导致颜色失真
- 小目标检测困难:远距离拍摄时车牌仅占图像 5%-8% 像素面积
- 模糊与遮挡:移动车辆产生的运动模糊、临时污渍遮挡字符
- 长宽比极端:新能源车牌长度是普通车牌的 1.5 倍
技术方案设计
数据增强策略
- 光照归一化:
- 使用 CLAHE(限制对比度自适应直方图均衡化)替代传统直方图均衡
-
对 HSV 空间的 V 通道单独处理避免颜色畸变
-
随机擦除增强:
- 模拟车牌污损场景,随机擦除 15%-30% 的矩形区域
-
擦除时保留字符的结构连续性(避免中间断裂)
-
透视变换:
- 根据车牌四角坐标生成单应性矩阵
- 最大旋转角度限制在±15°防止过度扭曲
模型架构改进
基于 YOLOv5s 的三大改进点:
- 检测头增强:
- 增加 P2 特征层(下采样 8 倍)提升小目标召回率
-
使用 BiFPN 替换原 PANet 实现多尺度特征融合
-
损失函数优化:
- 分类任务采用 Focal Loss(α=0.25, γ=2)
-
回归任务使用 EIoU Loss 替代 CIoU
-
训练策略:
- EMA 模型平滑(decay=0.999)
- Warmup+Cosine 退火学习率调度
关键代码实现
数据预处理示例
# CLAHE 增强实现
def clahe_augment(img, clip_limit=2.0, grid_size=(8,8)):
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size)
cl = clahe.apply(l)
merged = cv2.merge((cl, a, b))
return cv2.cvtColor(merged, cv2.COLOR_LAB2BGR)
模型修改片段
# 在 YOLOv5 中添加 P2 检测层
class Detect(nn.Module):
def __init__(self, nc=80, anchors=()):
super().__init__()
self.stride = torch.tensor([8, 16, 32]) # P2/P3/P4
self.anchors = torch.tensor(anchors).float().view(3, -1, 2)
# 新增 P2 层的输出通道
self.p2 = nn.Conv2d(256, self.no * self.na, 1)
实验对比结果
| 方法 | mAP@0.5 | 推理速度(FPS) |
|---|---|---|
| YOLOv5s 基线 | 0.872 | 142 |
| + 数据增强 | 0.891 | 138 |
| + 模型改进 | 0.913 | 126 |
| 完整方案 | 0.928 | 118 |
部署优化技巧
- TensorRT 加速:
- 使用 FP16 量化时注意保持 BN 层精度
-
对检测头进行层融合减少内存访问
-
长宽比适配:
- 自定义 Anchor 时增加 [6.0, 2.0] 比例
- 测试阶段采用 Soft-NMS 替代传统 NMS
总结与展望
当前方案对新能源车牌中的分隔符(如 ” 沪 A·12345″)识别仍存在约 5% 的错误率。未来可探索的方向包括:
– 引入 OCR 模块增强字符级理解
– 针对各省份简称设计特定的分类头
欢迎在 GitHub 项目提交您的改进方案,共同完善车牌检测技术生态。
正文完
