news 2026/9/16 8:46:03

MATLAB车牌识别实战:从图像处理到字符分割的完整传统方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MATLAB车牌识别实战:从图像处理到字符分割的完整传统方案

简介:这份完整车牌识别系统项目包,以车辆检测、图像采集、预处理、车牌定位、字符分割与识别为主线,覆盖从触发采集到车牌号码输出的全流程,适合计算机、人工智能、自动化等专业学生用于毕设、课设或项目初期演示,也适合初学者对照源码学习图像处理与模式识别实战。包内共133个文件,其中jpg、png、bmp等图像样本用于测试不同场景下的定位与分割效果,wav音频文件可用于模拟车辆到达的采集触发环节,另有m脚本、fig图表、doc文档和课题介绍,配套说明文档对系统结构和各模块实现做了详细解析,便于快速上手和二次开发。压缩包约6.16MB,轻量易下载,目前已有57人学习。资源附带完整测试通过的源码和文档说明,下载后可按README或文档指引运行,若遇环境或运行问题,作者提供私聊远程教学支持。整体内容紧凑、结构清晰,是一份兼顾教学演示与实际部署参考的车牌识别入门到进阶资料。

1. 车牌识别不是一个我会建议你直接套用深度学习模板的任务

很多刚接触车牌识别的同学会把注意力放在字符识别上,实际上真正决定项目能否交付的是车辆检测和车牌定位。这套资源里包含车1.bmp、车2.bmp两张现场图像,以及chepai.fig、车牌识别文档详细解析.doc和一组Sam*.jpg字符模板,正好覆盖一个完整链路:从图像采集触发开始,经过预处理、定位、分割,最后输出车牌号码。它没有用任何深度学习框架,全部基于MATLAB图像处理工具完成,适合课程设计、毕设,也适合想重新复习传统图像处理流程的工程师。接下来的章节我会按图像数据流动顺序,把这几个单元拆开讲,并给出可以直接复现的代码和参数经验值。

2. 图像采集与预处理:从车1.bmp到可定位候选区的关键步骤

2.1 图像采集触发单元的数据来源

图像采集在真实路侧系统中通常由地感线圈或补光灯触发,车辆检测单元会先做帧差法判断目标是否进入画面。这套资源没有提供视频流,而是直接给出了已经触发成功的车1.bmp和车2.bmp,所以离线处理时可以直接跳过动态检测,把它们当作采集结果读入。我的处理顺序是:先把彩色图转为灰度图,再消除噪声,最后强化边缘,这样车牌区域才能在颜色阈值和形态学处理中形成明显候选块。预处理参数直接决定定位是否稳定,这一节里的数值大多可以在车牌识别文档详细解析.doc里找到出处。

2.2 灰度化、去噪与边缘增强的MATLAB实现

我常用的一组MATLAB代码如下:

% 读取现场图像 img = imread('车1.bmp'); % 灰度化:消除颜色冗余,为后续边缘检测做准备 gray = rgb2gray(img); % 中值滤波去噪:3x3窗口对椒盐噪声和传感器噪声有较好抑制 gray = medfilt2(gray, [3 3]); % 边缘增强:Sobel算子计算梯度幅值,0.08是经验阈值 edges = edge(gray, 'sobel', 0.08);

这里每一步都有取舍。rgb2gray直接采用YIQ亮度通道,符合人眼感知,比简单平均更接近车牌图像在黑白传感器下的表现。中值滤波用3x3而不是5x5,是因为车牌字符笔画宽度通常只有几个像素,窗口太大会把字符边缘抹平;如果图像中有明显粒状噪声,我会临时改成5x5,代价是后续字符分割时需要做一次形态学膨胀来恢复笔画宽度。Sobel阈值0.08是一个偏低的值,这样做的目的是宁可多留下一些阴影或路面纹理,也不能让车牌边框在边缘图上断裂。

预处理阶段我一般不会做透视校正,因为倾斜角较小时,后续形态学闭运算可以容忍;若倾斜角超过15度,再在车牌定位后单独做旋转矫正。对车2.bmp这种偏暗的图像,我会额外在灰度图上做一次直方图均衡化,注意不要在HSV的V通道上做太强拉伸,否则颜色饱和度会发生变化,导致后续HSV阈值漂移。

2.3 预处理参数对照表

下面这张表是我在调不同样本时总结的参数范围,比单独给一个固定值更有用:

处理步骤常用方法参数经验值参数失控时的表现
灰度化rgb2gray颜色信息在后续HSV定位中会进一步被利用,此处不可用自定义强度权重
去噪medfilt2[3 3] 或 [5 5]窗口过大导致字符笔画粘连,窗口过小噪声残留
边缘检测sobel0.05 ~ 0.12阈值过高,边框断裂;阈值过低,路面纹理被误认为边缘
亮度归一化histeq无参数过度拉伸会让蓝色区域偏移,影响HSV阈值范围

实际项目里,最容易被忽视的是图像割裂现象。车1.bmp和车2.bmp如果直接跑同一个参数,通常会出现候选区域面积差异极大的情况。我建议先跑整个数据集,统计边缘图上非零像素占比,用sum(edges(:)) / numel(edges)输出,把目标比例控制在0.05到0.2之间。如果某个样本低于0.05,说明边缘过弱,需要降低Sobel阈值;高于0.2,则噪声过多,应优先加强中值滤波而不是继续调阈值。

3. 车牌定位:HSV颜色阈值与形态学闭运算的工程组合

3.1 为什么使用HSV而不是RGB进行粗定位

车牌的背景色通常是蓝色或黄色,RGB空间下三个通道互相耦合,受光线影响很大,同样的蓝色在阴影中可能R和G分量升高,导致阈值难以设定。HSV空间把色相单独分出来,我可以只关心H通道范围,同时用S和V排除白色和暗色区域。MATLAB的rgb2hsv返回H、S、V都是0到1的浮点数,蓝底车牌对应的H范围大概在0.55到0.75之间,这个区间在不同相机下会有小幅偏移,我会先用滑块工具手动确认一下当前数据集的色相分布,再写入固定阈值。

3.2 形态学闭运算、连通域筛选与区域坐标还原

一种常见做法是先对HSV掩码做闭运算,把断裂的车牌字符和边框连接成一体,再用连通域分析提取候选矩形。示例代码如下:

% 转换颜色空间 hsv = rgb2hsv(img); % 蓝色车牌的HSV阈值,S下限和V下限用于排除灰色区域 mask = (hsv(:,:,1) > 0.55) & (hsv(:,:,1) < 0.75) & ... (hsv(:,:,2) > 0.3) & (hsv(:,:,3) > 0.15); % 闭运算:先膨胀再腐蚀,弥合字符间隙 se = strel('rectangle', [15, 4]); mask = imclose(mask, se); % 连通域分析 cc = bwconncomp(mask); stats = regionprops(cc, 'BoundingBox', 'Area'); % 根据车牌宽高比和面积筛选 candidate = []; for k = 1:length(stats) w = stats(k).BoundingBox(3); h = stats(k).BoundingBox(4); areaRatio = stats(k).Area / (size(img,1) * size(img,2)); if w/h > 2.5 && w/h < 5.5 && areaRatio > 0.01 && areaRatio < 0.2 candidate = stats(k).BoundingBox; end end % 裁剪出车牌区域 plateImg = imcrop(img, candidate);

闭运算的结构元素我用一个宽15像素、高4像素的矩形,这个比例接近一个字符的笔画密度,能很好地把相邻字符之间的狭长间隔连起来。如果结构元素太短,连接效果差,多个字符块会分成两个候选区域;太长又容易把车灯或保险杠上的横向纹理也连进来。宽高比范围选择2.5到5.5,因为中国车牌的标准尺寸是440mmx140mm,近似3.14,但样本倾斜或透视会拉宽,所以上下各留了余量。面积比控制在0.01到0.2,是为了排除远处小车和近处车头整体区域。

这里有一个工程细节:regionprops默认返回的BoundingBox是轴对齐的,如果车牌有轻微旋转,宽高比会被放大。此时可以额外读取Orientation属性,用最小外接矩形重新计算长度和宽度。下面是一组我会在代码里同时使用的筛选范围:

筛选参数取值范围场景说明
宽高比 w/h2.5 ~ 5.5标准车牌约3.14,倾斜时放宽到5.5
面积占比0.01 ~ 0.2小于0.01是远距离小目标,大于0.2可能是整块车体
角度-15° ~ 15°超过后需要先做旋转校正,否则重算w/h

3.3 两张现场图的定位差异和chepai.fig带来的排错信息

我实际运行车1.bmp和车2.bmp时发现一个典型差异:车1.bmp的蓝色HSV掩码比较干净,经过闭运算后只有一个大连通域;车2.bmp因为车辆处于侧向位置,牌照产生透视,掩码区域被拉得很扁,宽高比接近6,直接越过筛选阈值。此时不能只调整宽高比上限,而是先对候选区域做一次极小角度旋转矫正,或者改用上面提到的最小外接矩形,再重新计算宽高比。

资源里的chepai.fig是MATLAB的figure文件,用openfig('chepai.fig')打开后,能看到当初记录下来的定位中间结果,包括HSV掩码层、闭运算后和最终矩形框三个图。这个文件对排错很有帮助,能直接对比你的参数和原始设计者的参数在哪个环节分叉。如果手头没有MATLAB,也可以用Octave的load打开部分兼容数据,但figure交互功能会弱一些。

4. 字符分割与识别:把Sam渝.jpg变成可输出号码

4.1 水平投影与垂直投影的分割原理

车牌定位完成后,得到的基本是一张包含蓝色边框和白色字符的彩色图。字符分割前需要先做二值化,把字符变成1,背景变成0。我倾向使用OTSU全局阈值,因为车牌区域的对比度通常稳定,局部自适应阈值反而会把边框噪声引入字符区域。接下来执行水平投影和垂直投影,投影就是逐行或逐列对二值图像求和,连续的非零区间对应字符行或列。代码可以写成一个函数:

function charCells = splitChars(bwPlate) % 水平投影:定位字符区域上下边界 hProj = sum(bwPlate, 2); hRows = find(hProj > 0.1 * max(hProj)); bwPlate = bwPlate(min(hRows):max(hRows), :); % 垂直投影:定位每个字符左右边界 vProj = sum(bwPlate, 1); vProj = vProj > 0.1 * max(vProj); % 找连续非零段的起止索引 diffVec = diff([0, vProj, 0]); startIdx = find(diffVec == 1); endIdx = find(diffVec == -1) - 1; % 切分字符 charCells = cell(1, length(startIdx)); for i = 1:length(startIdx) charCells{i} = bwPlate(:, startIdx(i):endIdx(i)); end end

投影阈值的0.1倍max是为了自适应不同光照,避免第二行字符或边框噪声破坏分割。如果字符内部笔画较细,最大值可能来自一条横线,此时0.1倍可能导致分割线断裂。我会在二值化之后先调用一次imclose(bwPlate, [1 5]),做小尺度的水平连接,把同一个字符内断裂的笔画合起来。

4.2 基于模板匹配和特征比对的字符识别

识别阶段,资源里的SamO.jpg、Sam0.jpg、Sam8.jpg、Sam渝.jpg、SamG.jpg、SamC.jpg就是模板库。这组文件名混合了数字、字母和汉字,正好覆盖了容易混淆的类别:O与0的外观几乎一致,G与C的区别只在缺口位置。传统模板匹配代码很直接:

% 统一字符尺寸为40x20像素 templates = {'SamO.jpg', 'Sam0.jpg', 'Sam8.jpg', 'Sam渝.jpg', ... 'SamG.jpg', 'SamC.jpg'}; for i = 1:length(charCells) charImg = imresize(charCells{i}, [40 20]); bestScore = Inf; bestChar = ''; for j = 1:length(templates) tpl = imread(templates{j}); tpl = imresize(tpl, [40 20]); score = sum(sum(abs(double(charImg) - double(tpl)))) / numel(tpl); if score < bestScore bestScore = score; bestChar = templates{j}; end end result(i) = bestChar; end % 输出车牌号 fprintf('识别结果: %s\n', result);

绝对差匹配逻辑足够应付规格统一的正常车牌。它的缺陷在于对笔画粗细和字体变化很敏感,所以我会在匹配后加一道二次校验:统计连通域数量。数字8和字母B都有两个孔洞,保护号码中第2个字符是字母,假设第2位为字母,则当候选字符的孔洞数为两个时,优先分配B或8;第1位是汉字,只能用模板库中的有限汉字集合匹配。下表是我在处理常见混淆对时使用的方法:

混淆对区分方法
0与O结合车牌位置先验:第2位是字母时选O,第3位及以后选0
8与B孔洞数都是2,但B右侧有一条垂直边,8中心孔洞位置偏高
渝与G对汉字区域单独放大模板权重,避免被外边框干扰

4.3 识别结果组装与输出

识别结果不能直接拼接模板文件名,需要去掉扩展名,再按中国车牌编码规则装配。常见输出格式是省份汉字+字母+5位数字或字母组合,但在课程设计里只需要将字符数组连接并过滤杂质。如果分割阶段误把车牌中的小圆点算成一个字符,要提前设置宽度过滤:字符宽度占整个车牌宽度的比例低于3%时直接丢弃。这个尺寸过滤通常放在splitChars函数返回值之后,可以节省大量调参时间。我还会把每个字符的匹配得分保存下来,识别器输出时附带一个置信度,方便在毕设答辩时解释哪里识别错了。

5. 课程设计与毕设工程化的几个验证技巧

5.1 用文档说明和README.md还原完整流程

下载资源后不要急着改代码,先打开车牌识别文档详细解析.doc,里面通常会列出参数表和流程图。如果有README.md,第一步先把运行顺序记录下来:读取图片、预处理、HSV定位、闭合运算、连通域筛选、字符分割、模板匹配。我习惯把每个中间变量在MATLAB工作区保存为.mat文件,这样后续可以用load直接对比。chepai.fig里保存的定位中间结果可以当作标准答案,验证你的定位框是否和原始设计者一致。

5.2 没有MATLAB环境时如何快速验证算法思路

如果只有一台没有MATLAB的电脑,可以用Octave运行部分脚本。但chepai.fig和模板匹配代码中部分工具箱函数不兼容,这时可以用Python OpenCV写一个最小验证版本:cv2.imread后先用cv2.cvtColor转到HSV,再走一遍同样的阈值和morphologyEx闭运算,会发现能复现相同的定位结果。这个迁移过程也能帮你确认算法依赖到底在哪里。对已经入行的工程师,这种传统图像处理方案的价值在于无依赖、可解释,适合那些不允许安装深度学习运行时的嵌入式环境。

5.3 从传统方案过渡到更现代的检测流程

现在商业车牌识别产品早已用上深度学习,常见做法是用YOLOv5或YOLOv8直接检测车牌区域,替代HSV定位和形态学连接。你在这套资源中学到的字符分割和模板匹配,可以保留作为识别后处理。验证时建议用同一批图片分别跑传统流程和深度学习流程,记录定位框的IoU和整体识别准确率。一个实用的技巧是:将chepai.fig中的结果与YOLOv5输出叠加到同一张图上,可以直观看到传统方法漏检的模糊、倾斜样本,这些样本才会成为改进深度模型的训练集。如果在STM32这类边缘端做车辆检测,处理流程会进一步重构成灰度和轻量卷积结构,而这块资源的预处理与IoU评估逻辑依然可以直接复用。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 8:45:33

配电网拓扑约束建模:断线解环原理与MATLAB实现

1. 项目背景与核心价值配电网拓扑约束建模一直是电力系统优化领域的核心难题。传统方法往往采用生成树算法或整数规划来保证网络辐射状结构&#xff0c;但这些方法要么计算复杂度高&#xff0c;要么约束条件冗余。我们团队在分析IEEE 33节点等经典配电网模型时发现&#xff0c;…

作者头像 李华
网站建设 2026/9/16 8:44:02

小白程序员也能抓住AI红利,高薪Offer轻松拿下!

随着AI技术的快速发展&#xff0c;传统技能岗位需求下降&#xff0c;而AI高薪就业岗位激增。 现在的环境&#xff0c;真的替不少人捏把汗。 五六年前&#xff0c;会数学、C语言、机械化、电脑操作、excel、运营等一套系统化流程就能稳稳拿到高薪offer&#xff0c;如今这些技能不…

作者头像 李华
网站建设 2026/9/16 8:43:54

新能源零部件|密封锁付装配工位,合米科技AI SOP视觉防错规避工艺遗漏带来的售后故障

摘要新能源零部件密封锁付工位对工序完整性要求极高&#xff0c;密封件漏放、螺丝锁付不到位会直接影响产品防水、安全性能。本文剖析新能源零部件产线管理痛点&#xff0c;介绍深圳合米科技 AISOP 视觉防错系统落地效果&#xff0c;以工位数据对比&#xff0c;展现系统在新能源…

作者头像 李华
网站建设 2026/9/16 8:42:55

Agent技能系统设计指南:从工具调用到稳定编排

最近两周我都在捣鼓一个内部 Agent 项目&#xff0c;越调越觉得"技能"这件事值得单独拿出来聊聊。之前我们把所有能力都塞进系统提示词里&#xff0c;结果上下文一长&#xff0c;模型行为就开始飘&#xff1b;后来把能力拆成一个个函数&#xff0c;还是不够&#xff…

作者头像 李华
网站建设 2026/9/16 8:42:31

基于uniapp的餐厅预约微信小程序开发实战拆解

1. 项目背景与整体设计思路1.1 餐厅预约这个需求到底在解决什么问题先说个真实场景。我以前在一家连锁餐饮品牌做技术顾问&#xff0c;门店高峰期前台电话基本没停过&#xff0c;顾客问得最多的就是"现在还有没有位置""需要等多久"。线下排队叫号系统又贵又…

作者头像 李华
网站建设 2026/9/16 8:42:20

MobaXterm在嵌入式开发中的高效文件传输实践

1. 为什么选择MobaXterm进行开发板文件传输第一次接触嵌入式开发时&#xff0c;我试过至少5种不同的SSH工具&#xff0c;最终发现MobaXterm在稳定性和易用性上确实优势明显。这款集成了SSH、SFTP、X11等功能的全能终端&#xff0c;特别适合需要频繁与Linux开发板交互的场景。相…

作者头像 李华