Matlab车牌识别:图像处理定位、字符分割与BP/ONNX分类
2026/9/17 16:18:08 网站建设 项目流程

简介:这份《基于Matlab的车牌识别(完整版)》以单个doc文档交付,面向具备Matlab基础、正在做课程设计或毕业设计的学生,以及希望快速梳理车牌识别完整链路的开发者。文档按预处理、边缘检测、车牌定位、字符分割、字符识别五个环节组织,先交代智能交通场景下的设计原理与总体流程,再逐模块说明灰度化、开运算求背景、背景相减增强、阈值二值化、边缘提取、垂直投影分割,以及模板匹配和人工神经网络识别等实现思路,并附有对应代码片段与流程图。包内共1个doc文件,约1.33MB,便于直接阅读和对照编程。该文档已有877人学习,可用于复现从原始图像输入到车牌号码输出的关键处理节点,理解参数调整、字符切分与识别匹配的取舍,适合作为Matlab图像处理练习和算法入门参考。

1. 从一张违章抓拍图说起:Matlab 车牌识别到底在识别什么

一张 1280×720 的卡口抓拍图里,车牌常常只占 120×35 像素,车身反光、雨天泥点和轻微透视倾斜同时出现。Matlab 车牌识别要做的事,是把这块小区域从整幅图中抠出来,切成 7 个字符,再逐个判成省份汉字、字母或数字,最后拼成可读字符串。它适合做图像处理课程设计、模式识别大作业,也适合在没有 GPU 的工作站上快速验证定位与分割算法。

整条链路可以拆成四段:候选区域定位、车牌校正、字符切分、字符分类。后处理再按车牌编码规则做一次校验,比如燃油车第二位只能是字母、新能源车牌为 8 位。常见做法是先用经典图像处理把定位做扎实,字符分类再选模板匹配、BP 神经网络,或者接开源车牌检测识别模型导出的 ONNX 做推理。字符粘连、光照不均、汉字识别率低,是这条链路里最容易返工的三处。

2. 车牌识别的预处理链路:灰度、边缘、形态学与 matlab 图像处理函数怎么配

定位前要先统一输入尺度。不同相机分辨率差异大,固定尺寸的结构元在小图上会把字符糊掉,在大图上又连不成整块。我一般把图像高度统一到 480 像素,宽度按比例缩放,后续所有阈值都围绕这个尺度来定。matlab 安装完成后,图像处理工具箱里的 imread、rgb2gray、edge、strel、bwareaopen 就够覆盖定位链路的前半段,不需要额外附加功能。

2.1 灰度化与高斯滤波的取舍

rgb2gray 按亮度加权转换,蓝色车牌转灰后字符与底色的对比度会掉一截,但字符边缘的梯度仍然保留。直接对彩色图做边缘检测会得到三份边缘响应,融合规则反而更难调。如果抓拍噪点明显,先做一次小核高斯滤波再求边缘,代价是细笔画被削弱,需要把边缘阈值往回调一点。

% 读取并统一高度,宽度按比例缩放,保证结构元尺寸可复用 img = imread('car_01.jpg'); if size(img, 3) == 3 gray = rgb2gray(img); else gray = img; end gray = imresize(gray, [480 NaN]); % 高度锁定 480,NaN 表示宽度自动等比 % 轻度高斯滤波抑制传感器噪点,sigma 取 0.8 到 1.2 之间较常见 gray = imgaussfilt(gray, 1.0); gray = im2double(gray); % 后续 edge 对 double 型更友好 figure; imshow(gray); title('灰度与滤波结果');

imresize[480 NaN]把高度写死,宽度交给函数按纵横比推算,避免车牌被横向拉伸。imgaussfilt的第二个参数是标准差,超过 1.5 会把字符竖笔画的边缘抹平,二值化后容易出现断笔。im2double把像素归一到 0 到 1,edge函数在 double 输入下对阈值更敏感,调参时数值范围更好估计。

2.2 垂直边缘与形态学闭运算怎么配合

车牌区域的字符以竖笔画为主,垂直方向的 Sobel 响应比水平方向集中得多。先取垂直边缘,再用一个宽大于高的矩形结构元做闭运算,能把同一行字符的断裂边缘连成几块横向条带。闭运算之后接一次孔洞填充和面积过滤,车身纹理、路灯杆这类细长噪声基本能被压掉。

% Sobel 垂直边缘:字符竖笔画响应强,水平边缘被抑制 edgeImg = edge(gray, 'sobel', 'vertical', 0.12); % 矩形结构元的宽度大于高度,贴合车牌横向排布 se = strel('rectangle', [5 21]); closed = imclose(edgeImg, se); closed = imfill(closed, 'holes'); % 填充字符间隙形成的封闭孔洞 closed = bwareaopen(closed, 200); % 去掉面积小于 200 的碎片 figure; imshow(closed); title('垂直边缘闭运算结果');

edge最后的 0.12 是归一化阈值,调小会引入更多车身纹理,调大会让浅色车牌直接消失,通常按 0.08 到 0.18 扫一遍看候选数量。strel('rectangle', [5 21])的高度 5 决定了纵向容差,宽度 21 决定横向粘连能力,图像统一到 480 高度后这组值对常见蓝牌比较合适。bwareaopen的面积门槛要跟结构元配套,太小会让字符区域碎片化,太大可能把车牌两端吃掉。

2.3 候选区域筛选:行列投影与长宽比阈值

连通域标记只是第一步,真正决定定位准确率的是筛选规则。蓝牌外接矩形的长宽比大致在 2.8 到 4.5 之间,面积在统一高度下通常落在 800 到 6000 像素区间。再加上垂直方向的投影峰值数,可以进一步排除保险杠装饰条这类伪目标。

参数典型范围调大后的影响调小后的影响
长宽比2.8~4.5排除过宽目标,可能漏掉斜视车牌引入保险杠等横向条带
面积下限800漏掉远距离小车牌保留大量噪点区域
面积上限6000保留近景大车牌,误检增多近景车牌被直接过滤
投影峰数4~9容错提高,伪目标混入字符断裂时漏检
stats = regionprops(closed, 'BoundingBox', 'Area'); cand = []; for k = 1:numel(stats) bb = stats(k).BoundingBox; % [x y w h] ar = bb(3) / bb(4); % 长宽比 if ar > 2.8 && ar < 4.5 && stats(k).Area > 800 cand = [cand; bb]; % 收集合格候选 end end

regionprops返回的BoundingBox顺序是左上角横纵坐标加宽高,算长宽比时别把wh写反。Area是连通域实际像素数,和BoundingBox的面积不是一回事,斜视车牌用像素数更可靠。

2.4 车牌倾斜校正与 imrotate 的边界处理

抓到候选框后,先用 Canny 边缘和 Hough 变换估计上下边界的角度,也可以用最小二乘拟合车牌区域的上下轮廓。角度超过 3 度就用 imrotate 旋转,旋转会改变图像尺寸,需要把crop选项打开并重新裁剪。校正后再做字符分割,二值化后的字符竖直度会明显好转,连通域切分成功率随之提高。角度估计不准时别硬转,宁愿把容错留给分割阶段的投影法。

3. 字符分割与字符识别:从连通域到模板匹配、BP 神经网络与 ONNX 推理

定位框给出来之后,真正难的是把 7 个字符完整切开。中国车牌有约 31 类常用字符,汉字和字母数字的笔画密度差异大,单一分割策略往往在汉字处翻车。我的习惯是先做一次水平投影切分,失败再用连通域兜底,两者结果不一致时记录该样本,交给后处理规则判断。

3.1 Otsu 二值化与连通域标记做字符切分

蓝色车牌字符是浅色,转灰后比底色亮,Otsu 阈值算完后要取反,让字符变成白色前景。铆钉和泥点会形成小连通域,用面积过滤先清一遍,再按外接框的横坐标排序,判断是否满足“7 个字符、间距接近”的排布。

% 在定位框内做 Otsu 二值化,字符为浅色,需要取反 plate = gray(y:y+h, x:x+w); level = graythresh(plate); bw = imbinarize(plate, level); bw = ~bw; bw = bwareaopen(bw, 30); % 去掉铆钉、泥点等小连通域 stats = regionprops(bw, 'BoundingBox', 'Area', 'Centroid'); boxes = reshape([stats.BoundingBox], 4, [])'; % 按横坐标排序,准备判断字符顺序 [~, idx] = sort(boxes(:, 1)); boxes = boxes(idx, :);

graythresh返回 0 到 1 之间的归一化阈值,用它驱动imbinarize比手写 128 更适应不同曝光。bwareaopen的 30 是像素面积,调大能去掉更多噪声,但汉字内部断裂的小块也可能被误删。排序后要检查首字符宽度是否明显大于后续字符,新能源车牌为 8 位,长度分支要单独处理。

3.2 字符归一化到 20×40 与特征向量构造

切出来的字符尺寸不一,分类器需要统一输入。把每个字符外接框裁出后缩放到 20×40 的二值图,再拉成 800 维列向量,这是经典模板匹配和浅层神经网络的通用输入格式。字符被拉伸会改变笔画比例,缩放前先按外接框做一次边界裁剪,去掉上下多余白边。

chars = cell(1, numel(stats)); for k = 1:numel(stats) bb = round(boxes(k, :)); roi = bw(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1); roi = imresize(roi, [40 20]); % 统一到 40 行 20 列 chars{k} = roi(:); % 拉成 800×1 列向量 end X = double(cat(2, chars{:})); % 800×N 特征矩阵

imresize用默认的双线性插值,二值图缩放后会出现中间灰度值,送进分类器前可以再imbinarize一次。先裁剪再缩放,比直接缩放整块定位图更不容易引入背景干扰。

3.3 用 BP 神经网络做字符分类时怎么避开常见坑

BP 神经网络拟合曲线是 matlab 里最常见的入门示例,换到字符分类上,结构其实一样,差别在于输出层用 softmax 或 onehot 编码,损失函数选交叉熵。网络不需要很深,两个隐层通常够用,样本量少的时候隐层节点数超过 200 很容易过拟合。

% X: 800×N 特征,Y: 31×N onehot 标签,字符集不含 I、O net = feedforwardnet([120 60]); net.trainFcn = 'trainscg'; % 小样本下收敛较平稳 net.performFcn = 'crossentropy'; net.trainParam.epochs = 1500; net.trainParam.goal = 1e-4; net.divideParam.trainRatio = 0.75; net.divideParam.valRatio = 0.15; net.divideParam.testRatio = 0.10; [net, tr] = train(net, X, Y);

trainscg是量化共轭梯度法,对批大小不敏感,适合几百到几千张字符图。divideParam要显式设置,默认划分可能让验证集里缺某一类字符,训练曲线看着很好、实际错分集中。训练完别只看整体准确率,按字符类别出一份混淆矩阵,汉字和数字 0、字母 O 这类易混项要单独看。

3.4 在 Matlab 中调用 ONNX 模型做字符分类

如果已经有开源车牌检测识别模型导出的 ONNX 文件,可以省掉训练环节,直接在 matlab 里做推理。前提是通过附加功能管理器安装 ONNX 支持包,否则importONNXNetwork会直接报未定义函数。

% 导入 ONNX 字符分类模型,输出层按分类任务处理 net = importONNXNetwork('plate_char.onnx', ... 'OutputLayerType', 'classification'); % 输入尺寸按模型要求调整,假设为 32×32 单通道 inputImg = imresize(roi, [32 32]); prob = predict(net, inputImg); [~, label] = max(prob);

OutputLayerType要根据模型最后一层的类型选classificationregression,选错会导致输出无法直接映射到类别。ONNX 模型的输入尺寸、通道数和归一化方式必须和导出时一致,最常见的失败原因是预处理对不上,不是模型本身有问题。

识别方案训练成本适用场景主要风险
模板匹配无需训练字体规整、样本少光照和倾斜敏感
BP 神经网络中等有几百张标注字符容易过拟合
ONNX 模型无需训练已有可用模型文件预处理不一致

4. 整条链路跑起来:参数表、GUI 封装与批量测试的坑

单张图调通不等于整批可用。抓拍图的曝光、角度、车牌脏污程度差异很大,参数表要能快速回查,否则改一个阈值就得重新翻代码。我通常把定位和分割阶段的参数集中到一个结构体里,GUI 和批量脚本共用同一份配置。

4.1 定位与分割参数速查表

阶段参数名建议初值调整方向
预处理缩放高度480远距离车牌多时降到 360
边缘Sobel 阈值0.12漏检调低,误检调高
形态学结构元尺寸[5 21]车牌斜视时高度加到 7
过滤面积下限800小目标多时降到 400
分割字符面积下限30汉字断裂时降到 20

这张表不是固定答案,它更像是调参起点。每换一批相机或换一个拍摄距离,至少重扫一次边缘阈值和面积下限,比盲调神经网络参数见效快得多。

4.2 用 App Designer 封装一个可交互的车牌识别界面

把读图、定位、分割、识别四个按钮串起来,中间结果用坐标区显示,调参时能直接看到形态学输出。App Designer 里不要在每个回调里重新训练网络,把训练好的 net 存成 MAT 文件,启动时加载一次即可。

% 界面启动时加载已训练模型,避免重复训练 function startupFcn(app) data = load('plate_net.mat'); app.net = data.net; app.params = struct('height', 480, 'sobelT', 0.12, ... 'seSize', [5 21], 'areaMin', 800); end

startupFcn只跑一次,把网络和参数挂在 app 对象上,回调函数里用app.net取用。参数结构体集中管理,改阈值不用改界面布局,批量脚本直接复用同一个结构体。

4.3 批量跑图与识别准确率统计

批量测试要按“定位正确、分割正确、字符正确”三级统计,否则定位错了却把准确率算到分类器头上。每张图输出定位框、分割字符数和最终字符串,方便回看。

files = dir('test_imgs/*.jpg'); hitPos = 0; hitChar = 0; for i = 1:numel(files) result = platePipeline(fullfile(files(i).folder, files(i).name), params); if result.posOK, hitPos = hitPos + 1; end if strcmp(result.text, result.gt), hitChar = hitChar + 1; end fprintf('%s -> %s\n', files(i).name, result.text); end fprintf('定位率 %.2f%%,整牌识别率 %.2f%%\n', ... hitPos/numel(files)*100, hitChar/numel(files)*100);

platePipeline把整条链路封成一个函数,输入图像路径和参数,输出结构体。三级统计能快速判断瓶颈在定位还是识别,如果定位率高、整牌识别率低,优先查字符分割和汉字分类。

4.4 常见报错与定位手段

Undefined function 'importONNXNetwork'多半是 ONNX 支持包没装,去附加功能管理器确认一次。Index exceeds matrix dimensions通常出现在候选框坐标越界,裁剪前用max(1, x)min(w, x+w-1)夹一下边界。车牌定位到多个候选时,不要只取第一个,按面积和长宽比打分排序,取分数最高且与水平方向夹角最小的一项。二值化后字符粘连,切分数量小于 7,改用水平投影找谷底,或把结构元宽度调小后重跑定位。

5. 进阶:用 kmeans 聚类算法做字符分割、用 matlab 优化工具箱搜阈值

5.1 kmeans 聚类算法 matlab 版做字符区域聚类

字符排布有规律,质心横坐标近似等间距。把连通域的横坐标、宽度组成二维特征,用 kmeans 聚成 7 类,再按类中心排序,能比单纯按横坐标切分更抗噪。kmeans聚类算法matlab 的调用很直接,关键是初始化和距离度量。

feat = [centersX, widths]; % 横坐标与宽度组成的特征 [idx, C] = kmeans(feat, 7, ... 'Replicates', 5, 'Distance', 'cityblock'); [~, order] = sort(C(:, 1)); % 按类中心横坐标排序

Replicates设为 5 能降低局部最优的影响,cityblock距离对横坐标这种一维主导的特征更合适。聚类数固定为 7 只适用于燃油车,新能源车牌要改成 8。聚类结果里如果某一类只有一个样本,说明该字符可能被噪声吞掉,需要回到二值化阶段查。

5.2 用 matlab 优化工具箱自动搜索形态学参数

手工扫参效率低,可以把定位准确率写成目标函数,用 fminsearch 或 ga 在参数空间里搜索。搜索前固定随机种子和测试集,否则每轮评分的波动会盖过参数差异。

% p = [结构元高, 结构元宽, 面积下限] score = @(p) plateScore(imgFolder, round(p), net); p0 = [5, 21, 800]; opts = optimset('MaxFunEvals', 60, 'Display', 'iter'); [pBest, fBest] = fminsearch(score, p0, opts);

fminsearch会返回非整数,目标函数里先用round取整再代入形态学操作。评分函数只跑定位阶段,不重复训练网络,单轮评估控制在几十秒内,否则 60 次函数评估会拖很久。pBest取整后写回参数结构体的seSizeareaMin,下一批图直接按新参数走,比在代码里逐个试值省事。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询