共计 1636 个字符,预计需要花费 5 分钟才能阅读完成。
背景与痛点
车牌识别作为计算机视觉的经典应用,看似简单却暗藏玄机。我刚开始尝试时,经常遇到这些问题:阴天识别率暴跌、倾斜车牌无法处理、字符粘连导致分割失败。传统方法依赖固定阈值和规则判断,就像用尺子量波浪——根本抓不住变化。

技术选型
经过多次踩坑,我总结出这样的工具组合:
- OpenCV:图像处理核心库,好比视觉项目的瑞士军刀
- DNN 模块 :适合复杂场景,但需要大量标注数据
- 传统算法 :灵活可控,对硬件要求低
推荐新手先用传统方法打好基础,就像学骑车先装辅助轮。
核心实现
1. 车牌定位
颜色空间转换
// RGB 转 HSV 更易提取车牌颜色
Mat hsv;
cvtColor(src, hsv, COLOR_BGR2HSV);
// 蓝色车牌范围(不同地区需调整)inRange(hsv, Scalar(100, 70, 70), Scalar(124, 255, 255), mask);
形态学处理
- 先腐蚀去除小噪点
- 再膨胀连接断裂区域
- 最后闭运算填充内部空隙
2. 字符分割
垂直投影法
就像用梳子梳理字符间距:
// 计算垂直方向像素投影
for (int col = 0; col < binary.cols; ++col) {
int count = 0;
for (int row = 0; row < binary.rows; ++row) {if (binary.at<uchar>(row, col) == 255) count++;
}
projection[col] = count;
}
连通域分析
配合 findContours() 精确定位每个字符的边界框,注意过滤过小区域。
3. 字符识别
模板匹配
适合字体规范的车牌,就像玩找不同游戏:
// 加载模板字符
vector<Mat> templates = loadTemplates();
// 归一化匹配
matchTemplate(charROI, template, result, TM_CCOEFF_NORMED);
SVM 分类器
更智能但需要训练数据:
- 收集 500+ 字符样本
- 提取 HOG 特征
- 训练分类模型
完整代码框架
// 谷歌风格代码示例
#include <opencv2/opencv.hpp>
class LicensePlateRecognizer {
public:
explicit LicensePlateRecognizer(const string& templatePath);
struct RecognitionResult {
string plateNumber;
Rect platePosition;
double confidence;
};
RecognitionResult recognize(const Mat& inputImage);
private:
Mat preprocessImage(const Mat& src);
vector<Rect> locatePlates(const Mat& binary);
vector<Mat> segmentCharacters(const Mat& plateROI);
string recognizeCharacters(const vector<Mat>& chars);
};
性能优化技巧
- 多尺度检测 :像调整望远镜焦距,从 0.8~1.5 倍逐步缩放检测
- ROI 缓存 :对视频流只处理变化区域
- 并行处理 :使用 OpenCV 的 parallel_for_加速循环
常见问题解决
图像质量差
- 过曝:先做 CLAHE 均衡化
- 模糊:Wiener 滤波恢复
- 阴影:对数变换增强对比度
字符误分割
- 先统计平均字符宽度
- 对异常宽度的区域进行二次分割
- 考虑笔画密度特征辅助判断
扩展思考
新能源车牌识别要注意:
- 黄绿底色需调整颜色阈值
- 8 位字符需要修改分割逻辑
- 汉字识别需增训练样本
资源推荐
- 数据集:CCPD 中文车牌数据集
- 书籍:《OpenCV4 快速入门》
- 进阶:学习 PyTorch 实现更复杂模型
经过三个版本的迭代,我的车牌识别系统在测试集上达到了 92% 的准确率。记住:计算机视觉就像教小孩认字,需要耐心调整每个步骤的参数。建议先用 100 张图片做测试,逐步优化每个模块,最终你会看到那些模糊的车牌逐渐变得清晰可辨。
正文完
