在进行完对车牌的定位与裁剪之后,接下来就是字符分割操作。当然在车牌字符的分割之前,还需要做一些比较重要的预处理:
车牌倾斜位置矫正、形态学操作
1.车牌字符的算法及实现
代码主函数(继车牌定位之后)
close all;
clc
%------车牌图像灰度处理 % 1. 灰度处理
bw = rgb2gray(bw); % 车牌灰度图像
subplot(122),imshow(bw); % 显示车牌灰度图像
title('灰度图像'); % 图像标题
%------对车牌倾斜位置矫正
qingxiejiao = rando_bianhuan(bw); % 2. 获得图像倾斜角
bw = imrotate(bw,qingxiejiao,'bilinear','crop'); % 3.位置矫正
%图像进行位置矫正:取值为负值向右旋转 并选区双线性插值 并输出同样尺寸的图像
figure,subplot(121),imshow(bw); % 显示修正后的图像
title('倾斜校正');
%------转化为二值化图像
bw = imbinarize(bw,graythresh(bw)); % 4.二值化处理
subplot(122), imshow(bw);
title('二值图像');
%------形态学处理
bw = Xingtaixue_Chuli(bw,threshold); % 5.形态学操作
%------裁剪使得字体紧贴边界
bw = touying(bw); % 6. 贴近字符裁剪
%对图像进一步裁剪,保证边框贴近字体
figure,subplot(121),imshow(bw);
title('上下边界裁剪');
bw=~bw;
bw = bwareaopen(bw, threshold);
% 移除小面积对象函数 删除二值图像BW中面积小于threshold的对象
bw=~bw; % 7. 擦除
subplot(122),imshow(bw);
title('擦除');
%------分割车牌字符
[y,x]=size(bw); % 8. 单个字符边界分割
fenge=shuzifenge(bw,qingxiejiao);
%----拆分 % 9. 拆分车牌字符
[m,k]=size(fenge);
for s=1:2:k-1
subplot(1,k/2,(s+1)/2);
imshow(bw( 1:y,fenge(s):fenge(s+1)));
end
1.倾斜位置的矫正
关于车牌倾斜位置的矫正,之前也曾专门写过相关博客,基于拉冬变换实现的,参考连接:
MATLAB基于Randon变换的图像倾斜校正算法及实现
https://blog.csdn.net/weixin_43958974/article/details/84845707
2.字符上下边界
对定位后的车牌照进一步裁剪,紧贴字符的上下边界
代码:
function bw = touying(bw)
X_yuzhi=1;
[y,x]=size(bw);
Y_touying=(sum((~bw)'))'; %1.水平投影统计黑点
X_touying=sum((~bw)); %2.垂直投影统计黑点
%找黑体边缘
Y_up=fix(y/2);
Y_yuzhi=mean(Y_touying((fix(y/2)-10):(fix(y/2)+10),1))/1.6;
while ((Y_touying(Y_up,1)>=Y_yuzhi)&&(Y_up>1))
Y_up=Y_up-1; %3.根据阈值,不断上移获取上边界
end
Y_down=fix(y/2);
while ((Y_touying(Y_down,1)>=Y_yuzhi)&&(Y_down<y))
Y_down=Y_down+1; %4.根据阈值,不断上移获取上边界
end
%去除左边边框干扰
X_right=1;
if (X_touying(1,fix(x/14)))<=X_yuzhi
X_right=fix(x/14);
end
%找黑体边缘
bw=bw(Y_up:Y_down,X_right:x);
end
3.形态学操作
在图像处理中,形态学操作能更改地捕获图像特征,筛除噪声。在百度文库中发现了一篇相关的介绍,里面讲解的很详细了。
https://wenku.baidu.com/view/6fcc3e6178563c1ec5da50e2524de518964bd3b2.html
这里主要运用了断开H型、移除毛刺、开操作、擦除 处理
代码实现:
function bw=Xingtaixue_Chuli(bw,threshold)
bw = bwmorph(bw,'hbreak',inf);
% hbreak:断开图像中的H型连接,也就是去除两平行线中间的短小连接
figure, subplot(231),imshow(bw);
title('断开H连接');
bw = bwmorph(bw,'spur',inf); %移除刺激像素,细小分支,也叫“毛刺”
subplot(232),imshow(bw);
title('移除毛刺');
bw=bwmorph(bw,'open',5); %执行形态学开操作(先腐蚀后膨胀)
%可应用在去除电路板线路,只留元器件
subplot(233),imshow(bw);
title('先腐蚀后膨胀');
bw = bwareaopen(bw, threshold); %删除二值图像BW中面积小于threshold的对象,默认情况下使用8邻域
subplot(234),imshow(bw);
title('擦除');
bw=~bw;
subplot(235),imshow(bw);
title('取反');
end
4.字符分割
通过字符的大小与边界,进一步获取每个字符的左右边界。
function fenge = shuzifenge(imfenge,~)
[y,x]=size(imfenge);
SS=x*y;
% 1.设定分割阈值
if SS<=20000
shedingyuzhi=4;
elseif SS>20000&&SS<=30000
shedingyuzhi=4;
elseif SS>30000&&SS<=50000
shedingyuzhi=4;
elseif SS>50000&&SS<=80000
shedingyuzhi=4;
else
shedingyuzhi=4;
end
ganrao=SS/100; % 设置干扰系数
% 2. 统计垂直方向的黑点数(背景点数)
histogram=sum(~imfenge); % 对非图像点进行求和
k=1;
for h=1:x-1
if ((histogram(1,h)<=shedingyuzhi)&&(histogram(1,h+1)>shedingyuzhi))...
||((h==1)&&histogram(1,h)>shedingyuzhi)
% 3. 判定并存储单个字符的左边界
fenge(1,k)=h;
k=k+1;
elseif ((histogram(1,h)>shedingyuzhi)&&(histogram(1,h+1)<=shedingyuzhi))...
||((h==x-1)&&histogram(1,h)>shedingyuzhi)
% 4. 判定并存储单个字符的右边界
fenge(1,k)=h+1;
k=k+1;
else
end
end
k=k-1; %去掉上步中多产生的1
if k<10
msgbox('提取出错','警告');
else
end
% 5. 字符大小确认
if (sum(histogram(1,fenge(1,1):fenge(1,2)))<ganrao)||...
((fenge(1,2)-fenge(1,1))<(fenge(1,4)-fenge(1,3))/2)
%不符合字符的条件
for i=3:k
fenge(1,i-2)=fenge(1,i); %将字符边界刷选掉
end
else
end
[~, n]=size(fenge);
if n<14 %因为有7个字符,14个字符边界
msgbox('提取出错','警告'); % 6. 字符边界确认
end
fenge=fenge(1,1:14); % 7. 将字符的边界值赋值给fenge
end
5.代码实现效果