最近学习了数字图像处理的腐蚀、膨胀、闭运算、开运算等内容,于是想进行实践。车牌分割是一个不错的选择,里面涉及到了很多知识点。
这里先简述一下车牌分割的思路和流程(这里以绿色车牌为例):
1.定位绿色车牌区域
2.车牌矫正(如果图像中车牌是倾斜的话)
3.对图片进行剪切,只留下车牌区域即可
4.对车牌的每个字符进行分割。
接下来,对每一步进行详细说明。
车牌原图如下:
在这里需要说明的是,该代码用的方法只适用于汽车颜色和车牌颜色相差较大的汽车,若车辆为白色或者绿色,则较难实现上述功能。
1.定位绿色车牌区域。
(1)保留绿色和白色色域
clc;
clear;
close all;
%%因为绿色车牌是绿底黑字,因此在二值化后需要取反。
%% 定位绿色车牌区域
f=imread('D:\Matlab\Practice\LP.jpg');
gray=2*f(:,:,2)-1*f(:,:,1)-1*f(:,:,3)+0.1*(f(:,:,1)+f(:,:,1)+f(:,:,1));
figure,imshow(gray),title('保留绿色和白色色域');
我们知道,彩色图像一般有RGB三个通道,在matlab中,为:
f(:,:,1);——R通道
f(:,:,2);——G通道
f(:,:,3);——B通道
在这里,我们通过先提取出图片的Green分量,因为车牌的大部分是绿色的,并且为保证消除其他颜色分量,只保留车牌部分分量,需要减去Red和Blue分量。值得注意的是,新能源车牌是上白下绿的,如果只提取了绿色分量,提取出来的车牌部分就不完整,所以我们还需要提取白色分量。
通过不断地试验,最终提取绿色、白色分量的代码如上图所示。处理后的图像如下所示:
文章来源地址https://www.toymoban.com/news/detail-518040.html
(2)对图像进行二值化
level=graythresh(gray); %利用Ostu法获取图像的阈值
bw=imbinarize(gray,level); %根据Ostu法分割车牌图像
figure,imshow(bw),title('二值化后的图像');
这里用Ostu法对图像进行二值化,为了能更好的提取车牌轮廓。
Ostu法的作用简单来说就是设定一个阈值,使小于这个阈值的像素灰度值为0,大于这个阈值的像素灰度值为1。有关详细的说明请参考其他文章,这里不再赘述。
所用函数:
graythresh() 用Ostu法计算全局图像的阈值
imbinarize() 根据所计算的阈值,对二维灰度图像或三维灰度立体进行二值化
(3) 去除图像的噪点
bw1=bwareaopen(bw,500);%删除面积小于500的区域
figure,imshow (bw1),title ('删除小面积区域后的图像') ;
注意到进行二值化后的图像,除了车牌部分保留下来外,还有非车牌部分也保留了下来,所以在这里我们对非车牌部分进行去除。
这里需要注意,面积不能选取太大,否则会擦除部分车牌。
所用函数:
bwareopen() 删除小面积图像
(4)对图像进行闭运算
se=strel('cube',20);%创建一个边长为20的正方形
bw2=imclose(bw1,se);%闭运算连使整个车牌区域连接在一起
figure,imshow(bw2),title('进行闭运算后的车牌');
闭运算的过程是先膨胀后腐蚀,作用就是将没有连通的区域连起来。
显然,我们注意到车牌的上部和底部都存在着未连通的区域,于是我们对图像进行一次闭运算。
形态学结构元素有很多种,针对不同的问题可以选用不同的形态学结构元素,也可以混用。这里我们用 20x20 的正方形
所用函数:
stre() 设置形态学结构元素
imclose() 对图像进行闭运算
2.车牌矫正
由于这里选取的车牌是比较端正的,这部分只贴代码,不再赘述。感兴趣的同学可以自行研究。
%% 车牌矫正(利用radon变换)
theta=0:179;
r=radon(bw2,theta);
[m,n]=size(r);
c=0;
for i=1:m
for j=1:n
if r(1,1)<r(i,j)
r(1,1)=r(i,j);
c=j;
end
end
end
rot=90-c;
fx=imrotate(f,rot,'crop');
所用函数:
randon()
imrotate()
3.对图片进行剪切,只留下车牌区域即可。
%% 剪切定位车牌区域
s1=regionprops(bw2,'BoundingBox','Centroid') ; %获取车牌矩形区域,即二值图中值为1的矩形框
xy=s1(1).BoundingBox;%获取车牌矩形区域左上角坐标及矩形的长和宽, xy(1)为矩形框左上角的y坐标,xy(2)为矩形框左上角的x坐标
fcrop=f(round(xy(2)):round(xy(2)+xy(4)),round(xy(1)):round(xy(1)+xy(3)),:) ;
figure,imshow (fcrop),title('定位剪切后的绿色车牌图像');
虽然我们在1、2中对图片进行了一些操作,但是仅仅在于将图片中的车牌部分突出了出来,并没有将其进行提取。所以接下来我们对车牌部分进行提取。相应的说明已经附在代码后面,这里不再赘述。
所用函数:
regionprops()
4.对车牌字符进行分割
(1)对剪切后的车牌图像二值化
fgray=rgb2gray(fcrop);
level2=graythresh(fgray);
bw3=imbinarize(fgray,level2);
figure;imshow(bw3);title('定位剪切后的二值图像');
同理,先将彩色图转为灰度图,再用Ostu法即可。
(2)对二值化图像进行取反操作
bw4 = 1-bw3;%灰度值取反
figure;imshow(bw4);title('取反后的二值图像');
与提取蓝色车牌不同的是,新能源车牌是绿底黑字,为了后续更方便地处理,我们将其取反。
(3)删除小面积图像
%创建形态学结构元素
se2=strel('line',2,90);
se3=strel('cube',2);
se4=strel('disk',1);
se5=strel('cube',1);
bw3o=bwareaopen(bw4,25);%从二值图像中删除小对象,此处为去除图像中的噪点
figure;imshow(bw3o);title('删除小于25面积后的图像');
我们发现二值化后的车牌图像依然存在一些小的噪点,我们再用 bwareaopen() 函数将其删除即可。
(4)去除边缘像素
%很重要
bw3o=imclearborder(bw3o);
figure;imshow(bw3o);title('去除边缘像素(1)');
通过删除图像中的小面积噪声图像,字的部分越发地清晰了。但是我们仍然注意到,图像的边缘处并不平滑,存在着“毛边”,这对我们后续的处理会产生很大的影响,所以为了防止以后进行闭运算或者膨胀时导致某个字的缺失,我们对图像的边缘进行“平滑”处理。
所用函数:
imclearborder() 删除与二值图像边缘处相连的像素值为1的像素。
(5)对车牌进行膨胀和闭运算以便于分割
%对车牌进行膨胀和闭运算以便于分割
bw3o=imdilate(bw3o,se2);
bw3o=imdilate(bw3o,se3);
figure;imshow(bw3o);title('膨胀后的图像');
bw3oc =imclose(bw3o,se5);
figure;imshow(bw3oc);title('二值图像闭运算后');
有些同学到这里觉得应该能分割了,这不是每个字都没有连在一起吗?但是仔细观察后会发现,“京”字的偏旁和部首也分开了!Matlab在分割时,也会将偏旁和部首分割开来,这是我们不希望看到的。所以我们对图像进行膨胀和闭运算操作,使“京”的偏旁部首连接在一起。
注意:也要观察其它字进行膨胀和闭运算后是否接触到了图像边缘或者连接在一起,若接触到了,在分割时也会出错。所以这里大家就多试几次。
(6)图像边缘分割
bw4=imclearborder(bw3oc);
figure;imshow(bw4);title('去除边缘像素(2)');
为了保险起见,我们对图像再执行一次边缘切割。
(7)字符分割
%分割各个字符
s2=regionprops(bw4,'BoundingBox','Centroid');%获取各个字的矩形区域坐标
figure;
for i=1:length(s2)
xy=s2(i).BoundingBox;
bw60=fcrop(floor(xy(2)):floor(xy(2)+xy(4)),floor(xy(1)):floor(xy(1)+xy(3)),:);
gray1=50*bw60(:,:,2)-1*bw60(:,:,1)-1*bw60(:,:,3);% *50是为了显示的字符更清晰
level2=graythresh(gray1);
bw62=imbinarize(gray1,level2);
subplot(1,8,i);imshow(bw62);title(num2str(i));
end
完整代码如下:
clc;
clear;
close all;
%%因为绿色车牌是绿底黑字,因此在二值化后需要取反。
%% 定位绿色车牌区域
f=imread('D:\Matlab\Practice\LP.jpg');
gray=2*f(:,:,2)-1*f(:,:,1)-1*f(:,:,3)+0.1*(f(:,:,1)+f(:,:,1)+f(:,:,1));%关键
figure,imshow(gray),title('保留绿色和白色色域');
level=graythresh(gray); %利用Ostu法获取图像的阈值
bw=imbinarize(gray,level); %根据Ostu法分割车牌图像
figure,imshow(bw),title('二值化后的图像');
bw1=bwareaopen(bw,500);%删除面积小于500的区域
figure,imshow (bw1),title ('删除小面积区域后的图像') ;
se=strel('cube',20);%创建一个边长为20的正方形
bw2=imclose(bw1,se);%闭运算连使整个车牌区域连接在一起
figure,imshow(bw2),title('进行闭运算后的车牌');
%% 车牌矫正(利用radon变换)
theta=0:179;
r=radon(bw2,theta);
[m,n]=size(r);
c=0;
for i=1:m
for j=1:n
if r(1,1)<r(i,j)
r(1,1)=r(i,j);
c=j;
end
end
end
rot=90-c;
fx=imrotate(f,rot,'crop');
%% 剪切定位车牌区域
s1=regionprops(bw2,'BoundingBox','Centroid') ; %获取车牌矩形区域,即二值图中值为1的矩形框
xy=s1(1).BoundingBox;%获取车牌矩形区域左上角坐标及矩形的长和宽, xy(1)为矩形框左上角的y坐标,xy(2)为矩形框左上角的x坐标
fcrop=f(round(xy(2)):round(xy(2)+xy(4)),round(xy(1)):round(xy(1)+xy(3)),:);
figure,imshow (fcrop),title('定位剪切后的绿色车牌图像');
%% 分割字符
fgray=rgb2gray(fcrop);
level2=graythresh(fgray);
bw3=imbinarize(fgray,level2);
figure;imshow(bw3);title('定位剪切后的二值图像');
bw4 = 1-bw3;%灰度值取反
figure;imshow(bw4);title('取反后的二值图像');
%创建形态学结构元素
se2=strel('line',2,90);
se3=strel('cube',2);
se4=strel('disk',1);
se5=strel('cube',1);
bw3o=bwareaopen(bw4,25);%从二值图像中删除小对象,此处为去除图像中的噪点
figure;imshow(bw3o);title('删除小于25面积后的图像');
%很重要
bw3o=imclearborder(bw3o);
figure;imshow(bw3o);title('去除边缘像素(1)');
%对车牌进行膨胀和闭运算以便于分割
bw3o=imdilate(bw3o,se2);
bw3o=imdilate(bw3o,se3);
figure;imshow(bw3o);title('膨胀后的图像');
bw3oc =imclose(bw3o,se5);
figure;imshow(bw3oc);title('二值图像闭运算后');
bw4=imclearborder(bw3oc);
figure;imshow(bw4);title('去除边缘像素(2)');
%分割各个字符
s2=regionprops(bw4,'BoundingBox','Centroid');%获取各个字的矩形区域坐标
figure;
for i=1:length(s2)
xy=s2(i).BoundingBox;
bw60=fcrop(floor(xy(2)):floor(xy(2)+xy(4)),floor(xy(1)):floor(xy(1)+xy(3)),:);
gray1=50*bw60(:,:,2)-1*bw60(:,:,1)-1*bw60(:,:,3);
level2=graythresh(gray1);
bw62=imbinarize(gray1,level2);
subplot(1,8,i);imshow(bw62);title(num2str(i));
end
文章来源:https://www.toymoban.com/news/detail-518040.html
到了这里,关于用Matlab实现车牌分割(可识别大部分蓝色、绿色车牌)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!