详解基于MATLAB的车牌识别系统设计与实现:字符分割

时间:2024-03-22 10:49:57

在进行完对车牌的定位与裁剪之后,接下来就是字符分割操作。当然在车牌字符的分割之前,还需要做一些比较重要的预处理:
车牌倾斜位置矫正形态学操作

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.代码实现效果
详解基于MATLAB的车牌识别系统设计与实现:字符分割
详解基于MATLAB的车牌识别系统设计与实现:字符分割
详解基于MATLAB的车牌识别系统设计与实现:字符分割
详解基于MATLAB的车牌识别系统设计与实现:字符分割