车牌识别技术作为计算机视觉领域的经典应用场景,已经渗透到我们生活的方方面面。从小区门禁到高速公路ETC,从停车场管理到交通违章抓拍,这项技术正在悄然改变着城市管理模式。而MATLAB作为工程计算领域的"瑞士军刀",其强大的图像处理工具箱和直观的矩阵运算能力,使其成为实现车牌识别算法的理想平台。
我曾在某智能交通项目中负责车牌识别模块开发,当时用MATLAB从零搭建的识别系统最终实现了98.7%的日间识别准确率。这个实战指南将完整还原我的开发过程,重点分享几个关键突破点:如何用形态学处理解决车牌倾斜问题、基于投影法的字符分割技巧,以及针对国内蓝牌/黄牌的特征优化方案。
推荐使用R2020a及以上版本,这个版本之后的Image Processing Toolbox新增了boundingbox函数,可以大幅简化车牌定位步骤。实测对比显示,在相同算法下,R2020a比R2018b的处理速度提升约23%。
安装时需要勾选以下工具箱:
车牌识别对实时性要求较高,建议配置:
重要提示:在MATLAB中启用GPU加速需要单独安装CUDA工具包,建议使用CUDA 10.1版本,这个版本与大多数MATLAB发行版的兼容性最好
matlab复制% 读取图像并统一处理为灰度图
img_orig = imread('car_plate.jpg');
img_gray = rgb2gray(img_orig);
% 自适应直方图均衡化增强对比度
img_enhanced = adapthisteq(img_gray);
% 高斯滤波去噪(σ=1.5效果最佳)
img_filtered = imgaussfilt(img_enhanced, 1.5);
% Sobel边缘检测
[~, threshold] = edge(img_filtered, 'sobel');
img_edge = edge(img_filtered, 'sobel', threshold * 0.5);
这个预处理组合拳是我经过上百次测试得出的最优方案:
国内车牌有两个显著特征:蓝底白字(小型车)或黄底黑字(大型车),以及7个字符的固定格式。基于此我们可以设计定位算法:
matlab复制% 形态学闭运算连接边缘
se = strel('rectangle', [30, 30]);
img_closed = imclose(img_edge, se);
% 查找连通区域
stats = regionprops(img_closed, 'BoundingBox', 'Area');
% 根据长宽比和面积筛选车牌区域
plate_ratio = 3.0; % 车牌长宽比经验值
valid_boxes = [];
for k = 1:length(stats)
box = stats(k).BoundingBox;
ratio = box(3)/box(4);
if ratio > plate_ratio*0.8 && ratio < plate_ratio*1.2 && ...
stats(k).Area > 1000
valid_boxes = [valid_boxes; box];
end
end
这里有几个关键技巧:
传统垂直投影法在字符粘连时效果不佳,我的改进方案是:
matlab复制% 车牌二值化(Otsu法自动阈值)
plate_bw = imbinarize(plate_roi, 'global');
% 垂直投影计算
vertical_proj = sum(plate_bw, 1);
% 动态平滑投影曲线
window_size = round(size(plate_bw,2)/20);
smoothed_proj = movmean(vertical_proj, window_size);
% 找波谷作为分割点
[min_vals, min_locs] = findpeaks(-smoothed_proj,...
'MinPeakDistance', size(plate_bw,2)/15);
实测表明,动态平滑窗口能有效解决"川"、"京"等字符的中间凹陷导致的误分割问题。对于最后一个字符经常出现的右边界残缺情况,可以添加后处理规则:如果最后一个分割区间小于平均宽度的60%,则与前一个区间合并。
制作自己的训练集时要注意:
我使用的数据增强代码:
matlab复制% 随机添加运动模糊
if rand() > 0.7
len = randi([5,15]);
theta = randi([0,180]);
psf = fspecial('motion', len, theta);
img = imfilter(img, psf, 'replicate');
end
% 随机亮度调整
img = img * (0.8 + rand()*0.4);
matlab复制layers = [
imageInputLayer([32 32 1])
convolution2dLayer(3, 32, 'Padding', 'same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2, 'Stride', 2)
convolution2dLayer(3, 64, 'Padding', 'same')
batchNormalizationLayer
reluLayer
fullyConnectedLayer(128)
reluLayer
dropoutLayer(0.5)
fullyConnectedLayer(num_classes)
softmaxLayer
classificationLayer];
这个轻量级网络在测试集上达到了99.2%的准确率,单字符识别耗时仅3ms(GTX 1060)。关键设计点:
matlab复制parfor i = 1:num_images
% 每个循环迭代处理一张图像
results{i} = processPlate(images{i});
end
使用parfor并行循环时要注意:
引入基于规则的纠错机制能显著提升系统鲁棒性:
我整理的常见省份编码表:
| 省份 | 简称 | 编码范围 |
|---|---|---|
| 北京 | 京 | A-Z |
| 广东 | 粤 | A-Z |
| 浙江 | 浙 | A-H |
使用MATLAB Profiler定位瓶颈:
matlab复制profile on
plateRecognition('test.jpg');
profile viewer
某次优化前后的对比:
| 模块 | 原耗时(ms) | 优化后(ms) |
|---|---|---|
| 图像预处理 | 45 | 28 |
| 车牌定位 | 120 | 65 |
| 字符分割 | 80 | 55 |
| 字符识别 | 150 | 40 |
关键优化点:
im2col加速局部特征提取处理视频流时容易内存泄漏,建议:
matlab复制% 显式释放大内存变量
clear large_var
% 定期调用垃圾回收
pack
% 使用memory命令监控
[usr, sys] = memory;
disp(['可用内存:', num2str(sys.PhysicalMemory.Available/1e9), 'GB'])
现象:旋转校正后字符仍然扭曲
解决方案:
应对策略:
新型新能源车牌特点:
需要单独调整:
建立量化评估体系:
matlab复制function [accuracy] = evaluateModel(test_set)
correct = 0;
for i = 1:length(test_set)
[~, pred] = plateRecognition(test_set(i).image);
if strcmp(pred, test_set(i).truth)
correct = correct + 1;
end
end
accuracy = correct / length(test_set);
end
评估指标建议:
在i7-11800H处理器上的典型表现: