文章目录
-
- 引言:为什么用Matlab做车牌识别?
- 车牌识别的核心流程:5步搞定
- 第一步:图像预处理------让图片"听话"
-
- [1.1 读取图片 & 转灰度图](#1.1 读取图片 & 转灰度图)
- [1.2 去噪滤波](#1.2 去噪滤波)
- [1.3 增强对比度](#1.3 增强对比度)
- [1.4 二值化处理](#1.4 二值化处理)
- 第二步:车牌定位------找到车牌在哪里
-
- [2.1 边缘检测](#2.1 边缘检测)
- [2.2 形态学操作:让边缘连起来](#2.2 形态学操作:让边缘连起来)
- [2.3 筛选车牌区域](#2.3 筛选车牌区域)
- 第三步:字符分割------把每个字符分开
-
- [3.1 预处理车牌区域](#3.1 预处理车牌区域)
- [3.2 计算垂直投影](#3.2 计算垂直投影)
- [3.3 找分割点](#3.3 找分割点)
- 第四步:字符识别------认出每个字符
-
- [4.1 制作模板库](#4.1 制作模板库)
- [4.2 模板匹配](#4.2 模板匹配)
- 第五步:结果输出------展示成果
- [常见问题 & 解决方法](#常见问题 & 解决方法)
- 总结:动手试试吧!
引言:为什么用Matlab做车牌识别?
说起车牌识别,你可能第一时间想到的是交通摄像头抓拍、停车场自动计费这些场景------但你知道吗?用Matlab也能轻松实现这个功能!作为一个曾经在Matlab里踩过无数坑的技术爱好者,我必须说:Matlab的图像处理工具箱简直是为这类任务量身定做的!它自带的函数库能帮你搞定从图像读取到字符匹配的所有步骤,而且代码量比其他语言少得多,对新手友好到爆炸!今天我就把自己摸索出来的完整流程分享给大家,从入门到实战,保证你看完就能动手做一个简单的车牌识别系统!
车牌识别的核心流程:5步搞定
不管用什么工具,车牌识别的基本逻辑都是一样的。咱们把它拆成5个关键步骤,一步步来:
- 图像预处理:把原始图片变得更"干净",方便后续操作
- 车牌定位:从整张图里找出车牌所在的区域
- 字符分割:把车牌上的每个字符(比如"京A12345"里的每个字)分开
- 字符识别:识别每个分割出来的字符是什么
- 结果输出:把识别到的字符组合成完整的车牌号码
听起来是不是很清晰?接下来咱们用Matlab逐个攻破这些步骤!
第一步:图像预处理------让图片"听话"
原始图片往往有很多干扰:比如光线太暗、有噪点、颜色太鲜艳......预处理就是要解决这些问题,让车牌区域更突出。
1.1 读取图片 & 转灰度图
Matlab里读图片用imread()函数,比如img = imread('car.jpg');。但彩色图处理起来太麻烦,咱们先转成灰度图------因为车牌的字符和背景在灰度上差异更大。转灰度用rgb2gray():gray_img = rgb2gray(img);。
1.2 去噪滤波
图片里的小噪点会影响后续的边缘检测,所以得先过滤掉。最常用的是高斯滤波,Matlab里用imgaussfilt():filtered_img = imgaussfilt(gray_img, 1.5);。这里的1.5是滤波半径,数值越大越模糊,自己调一调试试!
1.3 增强对比度
如果图片光线不均,字符和背景的差异会变小。这时候用imadjust()函数增强对比度:adjusted_img = imadjust(filtered_img, [0.2 0.8], []);。括号里的[0.2 0.8]是输入灰度范围,把这部分拉伸到0-255,对比度一下子就上来了!
1.4 二值化处理
二值化就是把图片变成黑白两色------字符是黑色,背景是白色(或者反过来)。Matlab里用im2bw():binary_img = im2bw(adjusted_img, 0.5);。这里的0.5是阈值,超过的变白色,低于的变黑色。如果效果不好,试试调整这个数值!
超级重要!!! 预处理的效果直接决定后面步骤的成败,一定要多试几次参数,直到图片里的车牌边缘清晰可见!
第二步:车牌定位------找到车牌在哪里
车牌定位是整个流程中最关键也最难的一步。咱们用"边缘检测+形态学操作+区域筛选"的组合拳来搞定它!
2.1 边缘检测
车牌的字符和背景之间有明显的边缘,用Canny边缘检测算法找边缘是最常用的方法。Matlab里用edge()函数:edge_img = edge(binary_img, 'Canny', [0.1 0.3]);。这里的两个阈值控制边缘的灵敏度,自己调调看!
2.2 形态学操作:让边缘连起来
边缘检测后,车牌区域的边缘可能是零散的。咱们用形态学的"闭操作"(膨胀+腐蚀)把这些零散的边缘连在一起,形成一个完整的车牌区域。Matlab里用imclose():
matlab
se = strel('rectangle', [15 5]); % 创建一个矩形结构元素
closed_img = imclose(edge_img, se);
这里的[15 5]是矩形的大小,你可以根据图片尺寸调整------比如图片大就用更大的数值。
2.3 筛选车牌区域
现在图片里有很多连通区域,咱们需要找出符合车牌特征的那个。车牌的特征是什么?一般是:
- 长宽比大概是3:1(比如标准车牌长440mm,宽140mm)
- 面积不能太小也不能太大
Matlab里用bwconncomp()找连通区域,再用regionprops()获取每个区域的属性:
matlab
stats = regionprops(closed_img, 'BoundingBox', 'Area');
plate_region = [];
for i = 1:length(stats)
bb = stats(i).BoundingBox;
area = stats(i).Area;
width = bb(3);
height = bb(4);
% 筛选长宽比在2.5到3.5之间,面积大于1000的区域
if width/height > 2.5 && width/height <3.5 && area>1000
plate_region = imcrop(gray_img, bb); % 裁剪出车牌区域
break;
end
end
如果找到符合条件的区域,就用imcrop()裁剪出来------这就是咱们要的车牌图片啦!
第三步:字符分割------把每个字符分开
车牌区域找到了,接下来要把每个字符分开。这里最常用的是"垂直投影法"------因为字符之间有空隙,垂直方向上的像素和会出现谷点,谷点就是分割线!
3.1 预处理车牌区域
先把裁剪出来的车牌区域再做一次二值化,确保字符是黑色的:plate_binary = im2bw(plate_region, 0.6);。然后可以用imcomplement()反转一下,让字符变成白色(方便后续处理):plate_binary = imcomplement(plate_binary);。
3.2 计算垂直投影
垂直投影就是计算每一列的白色像素数量。Matlab里用sum()函数:proj = sum(plate_binary, 1);。这里的1表示按列求和。
3.3 找分割点
投影结果里,谷点(数值小的地方)就是字符之间的空隙。咱们可以设置一个阈值,比如投影值小于最大值的10%的地方就是分割点。然后根据这些分割点裁剪出每个字符:
matlab
proj = proj/max(proj); % 归一化投影值
split_points = find(proj < 0.1); % 找谷点
% 把分割点分组,得到每个字符的列范围
char_regions = [];
start_col = 1;
for j = 2:length(split_points)
if split_points(j) - split_points(j-1) >5 % 间隔大于5的是字符之间的空隙
end_col = split_points(j-1);
char_regions = [char_regions; start_col end_col];
start_col = split_points(j);
end
end
% 裁剪每个字符
chars = [];
for k =1:size(char_regions,1)
c = imcrop(plate_binary, [char_regions(k,1) 1 char_regions(k,2)-char_regions(k,1)+1 size(plate_binary,1)]);
chars{end+1} = c;
end
这样就能得到每个字符的图片啦!如果字符粘连,可以用imerode()做一次腐蚀操作,把它们分开。
第四步:字符识别------认出每个字符
字符识别最基础的方法是"模板匹配"------把分割出来的字符和咱们提前做好的模板对比,找最像的那个!
4.1 制作模板库
首先得有一个模板库,包含所有可能的车牌字符:汉字(比如"京、沪、粤"等)、字母(A-Z)、数字(0-9)。你可以找一张标准车牌的图片,裁剪出每个字符,保存成单独的图片,比如"jing.png""A.png""1.png"等。然后把这些模板读入Matlab,统一大小(比如20x20像素):
matlab
template_dir = 'templates/';
template_files = dir(fullfile(template_dir, '*.png'));
templates = [];
labels = [];
for m=1:length(template_files)
t = imread(fullfile(template_dir, template_files(m).name));
t = imresize(t, [20 20]); % 统一大小
t = im2bw(t,0.5); % 二值化
templates{end+1} = t;
labels{end+1} = template_files(m).name(1:end-4); % 取文件名作为标签
end
4.2 模板匹配
对于每个分割出来的字符,咱们用normxcorr2()计算它和每个模板的相关系数------相关系数越大,说明越像。然后取最大的那个对应的标签就是识别结果:
matlab
result = '';
for n=1:length(chars)
char_img = imresize(chars{n}, [20 20]); % 调整字符大小和模板一致
char_img = im2bw(char_img,0.5);
max_corr = 0;
best_label = '';
for p=1:length(templates)
corr = normxcorr2(templates{p}, char_img);
current_max = max(corr(:));
if current_max > max_corr
max_corr = current_max;
best_label = labels{p};
end
end
result = [result best_label];
end
最后result变量里就是咱们识别到的车牌号码啦!
第五步:结果输出------展示成果
识别完成后,咱们可以用disp()函数输出结果,或者在图片上画个框显示车牌区域和识别结果:
matlab
% 在原始图片上画框
img_with_plate = img;
bb = stats(i).BoundingBox;
img_with_plate = rectangle('Position', bb, 'EdgeColor', 'red', 'LineWidth',2);
hold on;
% 显示识别结果
text(bb(1), bb(2)-10, result, 'Color','red', 'FontSize',12);
hold off;
imshow(img_with_plate);
disp(['识别到的车牌号码:', result]);
这样就能直观地看到结果啦!
常见问题 & 解决方法
在实战中,你可能会遇到一些问题,这里分享几个我踩过的坑和解决办法:
问题1:车牌倾斜怎么办?
如果车牌是倾斜的,定位和分割都会出错。解决办法是用霍夫变换找倾斜角度,然后旋转图片。Matlab里用hough()函数:
matlab
% 找倾斜角度
[H, theta, rho] = hough(edge_img);
peaks = houghpeaks(H, 5);
lines = houghlines(edge_img, theta, rho, peaks);
angle = lines(1).Theta;
if angle >45, angle = angle-90; end
% 旋转图片
rotated_img = imrotate(img, angle, 'bilinear', 'crop');
问题2:光线太暗/太亮怎么办?
用直方图均衡化histeq()增强对比度:equalized_img = histeq(gray_img);。这个函数能让图片的灰度分布更均匀,暗的地方变亮,亮的地方变暗。
问题3:字符识别错误怎么办?
可能是模板库不够全,或者字符预处理不好。试试:
- 增加更多模板(比如不同字体的字符)
- 调整字符分割的阈值
- 对字符做"细化"处理(用
bwmorph()函数的'thin'选项)
总结:动手试试吧!
好了,整个流程都讲完了!其实基于Matlab的车牌识别并不难------关键是理解每个步骤的目的,然后灵活运用Matlab的图像处理函数。你可以找一张自己拍的汽车图片,按照这个流程一步步写代码,看看能不能识别出车牌号码!
最后想说:技术学习最忌讳纸上谈兵,一定要动手实践!哪怕一开始识别错误,调整几个参数,多试几次,你一定会看到进步的。希望这篇教程能帮到你,祝你学习愉快!
(注:本文所有代码仅为示例,实际使用时请根据图片情况调整参数和细节哦!)
解每个步骤的目的,然后灵活运用Matlab的图像处理函数。你可以找一张自己拍的汽车图片,按照这个流程一步步写代码,看看能不能识别出车牌号码!
最后想说:技术学习最忌讳纸上谈兵,一定要动手实践!哪怕一开始识别错误,调整几个参数,多试几次,你一定会看到进步的。希望这篇教程能帮到你,祝你学习愉快!
(注:本文所有代码仅为示例,实际使用时请根据图片情况调整参数和细节哦!)