输入纸质表格,输出excel文件
主程序输入I=imread(‘文件名’)的图片,I1为矩阵,再使用xlwrite(‘文件名’,I1),得到excel文件。
需要预先训练好一个CNN网络(看matlab深度学习帮助文档),保存为et.mat。
效果
%主程序 excel_id.m
function I1=excel_id(I)
global fi;
fi=0;
load 'et.mat';%加载CNN
I=cutall(I);%变黑白,去除空白
for i=1:10
if length(I)<=400
break;
end
I=imresize(I,0.9);%缩小图片
end
PA=cutline3(I);%分割成一个个单元格
[y,x]=size(PA);
for i=1:x
for j=1:y
PA2 = num_cut2(suo2(PA{j,i}));%提取一个个字符
sum=calcu(PA2,et);%识别字符,连起来
output{j,i}=sum;%保存结果
end
end
I1=output;
end
%去除空白部分
function T = cutall(I)
I=im2bw(I,0.43);%变黑白
[y, x]=size(I);
y2=floor(y/2);x2=floor(x/2);%定位四个点,提取表格主要部分
for i=1:x
if I(y2,i)==0
cut11=i;
break
end
end
for i=1:x
if I(y2,x+1-i)==0
cut12=x+1-i;
break
end
end
for j=1:y
if I(j,x2)==0
cut21=j;
break
end
end
for j=1:y
if I(y+1-j,x2)==0
cut22=y+1-j;
break
end
end
T=I(cut21:cut22,cut11:cut12);
end
%分割成一个个单元格
function PA = cutline4(I)
%I=imread('49-3-BW01.jpg');
[y, x]=size(I);
p=sum(I);
I1=I';
q=sum(I1);%计算水平和垂直投影
signnew=1;sign=1;
for i=floor(0.05*x):floor(0.95*x)
if((i-signnew)>floor(0.05*x))
if p(i) <= 0.4*y
sign=[sign i];%记录符合的点
signnew=i;
end
end
end
sign=[sign x];
[H11,W11]=size(sign);
signnew2=1;sign2=1;
for j=floor(0.05*y):floor(0.95*y)
if((j-signnew2)>floor(0.05*y))
if q(j) <= 0.4*x
sign2=[sign2 j];%记录符合的点
signnew2=j;
end
end
end
sign2=[sign2 y];
[H22,W22]=size(sign2);
PA=cell(W22-1,W11-1);
se=strel('square',2);
I=imerode(I,se);
I=qubiankuang(I);%去边框
for i=1:(W11-1)
for j=1:(W22-1)
PA{j,i}=I(sign2(1,j):sign2(1,j+1),sign(1,i):sign(1,i+1));%分割
end
end
end
%去除边框
function I1=qubiankuang(I)
I=im2bw(I);
I1=imcomplement(I);
[ L, num]=bwlabel(I1,8);%连通域标记
x=find(L==1);%找出边框所在位置
for i=x
I1(i)=0;%去除边框
end
I1=imcomplement(I1);
end
%剪去边缘
function s=suo2(Img)
[y, x]=size(Img);
s4=floor(0.95*y);
s3=ceil(0.1*y);
s2=floor(0.95*x);
s1=ceil(0.01*x);%减去边缘
Img=Img(s3:s4,s1:s2);
s=Img;
end
%分离出一个个字符
function PA2 = num_cut2(Img)
global fi;
Img=im2uint8(Img);
[y, x]=size(Img);
[~,~,c]=size(Img);
if c==1
f2= ~im2bw(Img);
else
Img=rgb2gray(Img);
f2= ~im2bw(Img);
end
f=f2;
f=bwareaopen(f,50);
str=strel('square',2);
f=imdilate(f,str);
fi=fi+1;figure(fi);
imshow(f);
[L,num] = bwlabel(f,8);%标注二进制图像中已连接的部分
Feastats = regionprops(L,'basic');%计算图像区域的特征尺寸
Area=[Feastats.Area];%区域面积
b=[Feastats.BoundingBox];%[x y width height]字符的大小
sub=cell(1,num);%存储分割后的图像
fi=fi+1;figure(fi);
%分割过程
for i=1:num
a=floor(b((i-1)*4+2));%b中字符的特性是按4个一组放的,前两个为左上顶点坐标,后两个为长宽。
if a==0
a=1;
end
e=b((i-1)*4+4);
d=floor(b((i-1)*4+1));
if d==0
d=1;
end
g=b((i-1)*4+3);
if( g<=0.8*x && e<=0.95*y)
sub{1,i}=f2(a:a+e,d:d+g);%取出字符块
subplot(1,num,i);imshow(sub{1,i});
end
end
hold on
for k=1:num
[r,c]=find(L==k);
rbar=mean(r);
cbar=mean(c); plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k','MarkerFaceColor','k','MarkerSize',10); plot(cbar,rbar,'Marker','*','MarkerEdgecolor','w');
end
PA2=sub;
end
%对每个单元格识别出结果
function num = calcu(PA2,net)
[y,x]=size(PA2);
y1m=1;
for i=1:x
[y1,x1]=size(PA2{1,i});
if y1>y1m
y1m=y1;%计算最大字符高度
end
end
n=0;si=[];
for i=1:x
[y1,x1]=size(PA2{1,i});
if(y1 > floor(0.3*y1m))%防止过小的物体被当做字符
n=n+1;
si=[si i];
end
end
PA3=cell(1,n);
for i=1:n
PA3{1,i}=PA2{1,si(i)};
end
PA2=PA3;
[y,x]=size(PA2);
sum=[];
for i=1:x
imin=Tresize(PA2{1,i});%缩放图片使其符合CNN输入尺寸
pred=classify(net,imin);%识别
N=char(pred);
sum=[sum N];%保存结果
end
num=sum;
end
%缩放图片使其符合CNN输入
function T = Tresize(T1)
T=imcomplement(T1);
[y, x]=size(T);
AD=ones(floor(0.1*y),x);
T=[AD; T; AD];
[y, x]=size(T);
AD=ones(y,floor((y-x)/3));
T=[AD T AD];%增添空白区域使其符合输入
T=imresize(T,[16 16]);%缩放
T=im2uint8(T);
end