这段时间,利用matlab实现了一个集装箱箱号自动识别系统,以下对过程进行简单的记录。
首先对集装箱图像进行预处理,去除图像中所存在的干扰部分,尽量只保留集装箱箱号部分。
上图为原始图像,经过预处理后得到如下效果:
观察图像发现第一列为所需要的箱号部分,后边还存在一列干扰部分,接下来我们需要除去这一部分。对图像做垂直投影,第一个波峰为箱号产生,所以我们只需分割出第一个波锋的图像就能够得到只存在箱号的图像,分割后如下图:
然后就可以进行单个字符的切割啦,字符分割同样是通过投影法来做的:
得到单个字符后,对他们进行保存,再利用BP网络神经法进行识别,就能够得到最终的识别结果了:
上代码:
%% 清屏
clear;
close all;
clc;
%% 读取图像
[filename filepath]=uigetfile('.jpg','请选择图像');
file=strcat(filepath,filename);
img=imread(file);
figure('name','读取图像');
imshow(img);
title('初始图像');
%% 获得灰度图像
g_img=rgb2gray(img);
figure('name','灰度图像');
subplot(1,2,1);
imshow(g_img);
title('灰度图像');
subplot(1,2,2);
imhist(g_img);
title('灰度图像直方图');
%% 中值滤波
m_img=medfilt2(g_img,[3 3]);
figure('name','中值滤波');
imshow(m_img)
%% 二值化 (有不足,需要改进)
g1_img=g_img>220;
if g1_img~=1
g2_img=imadjust(g_img,[0 1],[1 0]);
g1_img=g2_img>200;
end
figure('name','二值化');
subplot(1,2,1);
imshow(g1_img);
title('二值化图像');
%去掉像素小于5的干扰部分
g1_img=bwareaopen(g1_img,5);
subplot(1,2,2);
imshow(g1_img);
title('二值化图像');
%% 判断箱号排列方向并进行第一次分割
[m,n]=size(g1_img);
imgCol=zeros(m,1); %列向量 存取统计每行的总像素值
imgRow=zeros(1,n); %行向量 存取统计每列的总像素值
%统计每行的总像素值
for i=1:m
for j=1:n
if g1_img(i,j)==1
imgCol(i,1)=imgCol(i,1)+1;
end
end
end
%判断图像在水平投影上出现几次波峰,若次数小于5,则确定为横向排列,否则为纵向排列
bottomB=[]; %存入每行的行号
b=0; %统计有多少行号码
for i=1:m
if (imgCol(i,1)~=0)&&(imgCol(i+1,1))==0 %
b=b+1;
bottomB(b)=i;
end
end
%统计每列的总像素值
for i=1:n
for j=1:m
if g1_img(j,i)==1
imgRow(1,i)=imgRow(1,i)+1;
end
end
end
%判断图像在水平投影上出现几次波峰,若次数小于5,则确定为横向排列,否则为纵向排列
bottomR=[]; %存入每列的列号
r=0; %统计有多少列号码
for i=1:n
if (imgRow(1,i)~=0)&&(imgRow(1,i+1))==0
r=r+1;
bottomR(r)=i;
end
end
%% 作投影图
y=1:n;
figure
subplot(211),plot(y,imgRow(y));
xlabel('列号/列');
ylabel('像素值/个');
title('垂直投影');
% 求水平投影
x=1:m;
subplot(212),plot(x,imgCol(x));
xlabel('行号/行');
ylabel('像素值/个');
title('水平投影');
%% 初次分割
left=1;
top=1;
right=n;
bottom=m;
img2=[];
% 确定排列方向
if b<=5 %横向排列
bottom=bottomB(2);
img2=g1_img(top:bottom+5,left:right);
elseif r<=4 %纵向排列
right=bottomR(1);
img2=g1_img(top:bottom,left:right+5);
end
figure('name','初次分割');
imshow(img2);
title('第一次分割后的图像');
%% 再次分割;
img3=my_imsplit(img2,5);
figure('name','再次分割');
imshow(img3);
title('再次分割后的图像');
%% 分割出单个字符
%分割竖直排列的箱号
[y,x]=size(img3);
rows=zeros(1,x); %存取统计每列的总像素值
cols=zeros(y,1); %存取统计每行的总像素值
for i=1:x
for j=1:y
if img3(j,i)==1
rows(1,i)=rows(1,i)+1;
end
end
end
for i=1:y
for j=1:x
if img3(i,j)==1
cols(i,1)=cols(i,1)+1;
end
end
end
ROW=[];
row=0;
for i=1:x-1
if (rows(1,i)~=0)&&(rows(1,i+1)==0)
row=row+1;
ROW(row)=i;
end
end
COL=[];
col=0
for i=1:y-1
if (cols(i,1)~=0)&&(cols(i+1,1)==0)
col=col+1;
COL(col)=i;
end
end
%% 分割垂直排列且有一行的图像
if row==1
figure('name','分割的字符');
[word1,result]=getword2(img3);
word1=imresize(word1, [40,20], 'nearest');
subplot(1,11,1);imshow(word1);
[word2,result]=getword2(result);
word2=imresize(word2, [40,20], 'nearest');
subplot(1,11,2);imshow(word2);
[word3,result]=getword2(result);
subplot(1,11,3);imshow(word3);
[word4,result]=getword2(result);
subplot(1,11,4);imshow(word4);
[word5,result]=getword2(result);
subplot(1,11,5);imshow(word5);
[word6,result]=getword2(result);
subplot(1,11,6);imshow(word6);
[word7,result]=getword2(result);
subplot(1,11,7);imshow(word7);
[word8,result]=getword2(result);
subplot(1,11,8);imshow(word8);
[word9,result]=getword2(result);
subplot(1,11,9);imshow(word9);
[word10,result]=getword2(result);
subplot(1,11,10);imshow(word10);
[word11,result]=getword2(result);
subplot(1,11,11);imshow(word11);
end
%% 分割水平排列且有两行的图像
if col==2
%先分割为两张图片
[y1,x1]=size(img3)
img4_0=img3(1:COL(1)+3,:);
img4=my_imsplit(img4_0,5);
img5_0=img3(COL(1)+3:y1,:);
img5=my_imsplit(img5_0,5);
figure('name','lll');
subplot(1,2,1);
imshow(img4);
subplot(1,2,2);
imshow(img5);
figure('name','分割的字符');
[word1,result]=getword(img4);
subplot(1,11,1);imshow(word1);
[word2,result]=getword(result);
subplot(1,11,2);imshow(word2);
[word3,result]=getword(result);
subplot(1,11,3);imshow(word3);
[word4,~]=getword(result);
subplot(1,11,4);imshow(word4);
[word5,result]=getword(img5);
subplot(1,11,5);imshow(word5);
[word6,result]=getword(result);
subplot(1,11,6);imshow(word6);
[word7,result]=getword(result);
subplot(1,11,7);imshow(word7);
[word8,result]=getword(result);
subplot(1,11,8);imshow(word8);
[word9,result]=getword(result);
subplot(1,11,9);imshow(word9);
[word10,result]=getword(result);
subplot(1,11,10);imshow(word10);
[word11,result]=getword(result);
subplot(1,11,11);imshow(word11);
end
%% 大小归一化处理
word1=imresize(word1, [40,20], 'nearest');
word2=imresize(word2, [40,20], 'nearest');
word3=imresize(word3, [40,20], 'nearest');
word4=imresize(word4, [40,20], 'nearest');
word5=imresize(word5, [40,20], 'nearest');
word6=imresize(word6, [40,20], 'nearest');
word7=imresize(word7, [40,20], 'nearest');
word8=imresize(word8, [40,20], 'nearest');
word9=imresize(word9, [40,20], 'nearest');
word10=imresize(word10, [40,20], 'nearest');
word11=imresize(word11, [40,20], 'nearest');
%% 存取字符图像图像
imwrite(word1,'a1.jpg');
imwrite(word2,'a2.jpg');
imwrite(word3,'a3.jpg');
imwrite(word4,'a4.jpg');
imwrite(word5,'a5.jpg');
imwrite(word6,'a6.jpg');
imwrite(word7,'a7.jpg');
imwrite(word8,'a8.jpg');
imwrite(word9,'a9.jpg');
imwrite(word10,'a10.jpg');
imwrite(word11,'a11.jpg');
%% BP神经网络识别法
liccode=char(['0':'9','A':'H','J':'N','P':'Z']);
P=[];
for i=1:34
for j=1:5
jj=num2str(j);
fname = strcat('识别模板\',liccode(i),'\',jj,'.jpg');
I=pretreatment(imread(fname));
P=[P;I];
end
end
P=P';
[mm,nn]=size(P);
T=zeros(34,nn);
for i=1:34
T(i,5*i-4:5*i)=1;
end
net=newff(minmax(P),[2000,300,34],{'logsig','logsig','logsig'},'trainrp');
net.inputWeights{1,1}.initFcn='rands';
net.inputWeights{2,1}.initFcn='rands';
net.trainparam.epochs=1000;
net.trainparam.show=50;
net.trainparam.goal=0.00001;
net=init(net);
[net,tr]=train(net,P,T);
test0=pretreatment(word1);
test1=pretreatment(word2);
test2=pretreatment(word3);
test3=pretreatment(word4);
test4=pretreatment(word5);
test5=pretreatment(word6);
test6=pretreatment(word7);
test7=pretreatment(word8);
test8=pretreatment(word9);
test9=pretreatment(word10);
test10=pretreatment(word11);
test=[test0',test1',test2',test3',test4',test5',test6',test7',test8',test9',test10'];
for i=1:11
out=sim(net,test(:,i));
out1=compet(out);%
d=find(out1==1)-1;
if(d==10)
str='A';
elseif(d==11)
str='B';
elseif(d==12)
str='C';
elseif(d==13)
str='D';
elseif(d==14)
str='E';
elseif(d==15)
str='F';
elseif(d==16)
str='G';
elseif(d==17)
str='H';
elseif(d==18)
str='J';
elseif(d==19)
str='K';
elseif(d==20)
str='L';
elseif(d==21)
str='M';
elseif(d==22)
str='N';
elseif(d==23)
str='P';
elseif(d==24)
str='Q';
elseif(d==25)
str='R';
elseif(d==26)
str='S';
elseif(d==27)
str='T';
elseif(d==28)
str='U';
elseif(d==29)
str='V';
elseif(d==30)
str='W';
elseif(d==31)
str='X';
elseif(d==32)
str='Y';
elseif(d==33)
str='Z';
else
str=num2str(d);
end
switch i
case 1
str0=str;
case 2
str1=str;
case 3
str2=str;
case 4
str3=str;
case 5
str4=str;
case 6
str5=str;
case 7
str6=str;
case 8
str7=str;
case 9
str8=str;
case 10
str9=str;
otherwise
str10=str;
end
end
s=strcat(str0,str1,str2,str3,str4,str5,str6,str7,str8,str9,str10);
figure('name','识别结果');
imshow(img);
title(['BP网络识别结果:',s],'color','b','FontSize',20);
代码有些繁琐,但能完成基本任务,后续在进行改进。