12.5 图像识别应用综合实例
本实例中,要求使用Visual C++(www.cppentry.com)和MATLAB进行混合编程(www.cppentry.com),实现对给定的文字图像进行识别,能够识别出文字的基本轮廓。该实例使用MATLAB的M文件编辑器建立M文件,文字识别的关键过程和算法使用MATLAB编写程序,界面使用Visual C++(www.cppentry.com)设计开发。在两者的接口上,通过使用MATLAB中提供的COM组件创建工具,将图像识别的M文件创建为COM组件,然后在Visual C++(www.cppentry.com)环境中创建工程,通过COM接口访问COM组件中的接口函数,实现文字图像的识别。具体过程如下。
12.5.1 新建图像识别M文件
新建文件名为FuncTextRecog.m的M文件,在该文件中输入以下程序语句:
- function []= FuncTextRecog()
- [FileName,PathName] = uigetfile('*.*','选择二值图像文件');
- imfile = strcat(PathName,FileName);
- I0=imread(imfile);
- I=im2bw(I0,0.4); %将I0图像的格式转换为二值图
- [y0 x0]=size(I); %将图像I的像素尺寸分别赋值给y0、x0
- Range=sum((~I)');
- Hy=0;
- for j=1:y0
- if (Range(j)>=1)
- HyHy=Hy+1;
- end
- end
- RangeX=sum((~I));
- Wx=0;
- for i=1:x0
- if (RangeX(i)>=1)
- WxWx=Wx+1;
- end
- end
- Amp=24/Hy; % 将文字图像归一化到24像素点的高度
- I=imresize(I,Amp);
- [y x]=size(I);
- %I=bwmorph(~I,'skel',Inf);
- %I=~I;
- tic
- %====== 基本结构的定义和检测 =======%
- % 第一类:竖(V);左斜(L);右斜(R);突变(P)
- % 第二类:左半圆弧(C);右半圆弧(Q)
- % 第三类:结构待定(T);
- %=====================================%
- Left=zeros(1,y); % 左端轮廓检测
- for j=1:y
- i=1;
- while ((i<=x)&&(I(j,i)==1))
- ii=i+1;
- end
- if (i<=x)
- Left(j)=i;
- end
- end
- for j=1:y-1
- LeftD(j)=Left(j+1)-Left(j);
- end
- %========== 结构特征提取 =============%
- j=1;
- while ((Left(j)<1)&&(j<y))
- jj=j+1;
- end
- Y1=j;
- j=y;
- while ((Left(j)<1)&&(j>1))
- jj=j-1;
- end
- Y2=j-1; % 去掉急剧变化的两端
- %============== 右边 ==================%
- Right=zeros(1,y); % 左端轮廓检测
- for j=1:y
- i=x;
- while ((i>=1)&&(I(j,i)==1))
- ii=i-1;
- end
- if (i>=1)
- Right(j)=i;
- end
- end
- for j=1:y-1
- RightD(j)=Right(j+1)-Right(j);
- end
- %=======顶端轮廓检测================%
- Top=zeros(1,x);
- for i=1:x
- j=1;
- while ((j<=y)&&(I(j,i)==1))
- jj=j+1;
- end
- if (j<=y)
- Top(i)=j;
- end
- end
- for i=1:x-1
- TopD(i)=Top(i+1)-Top(i);
- end
- i=1;
- while ((Top(i)<1)&&(i<x))
- ii=i+1;
- end
- X1=i;
- i=x;
- while ((Top(i)<1)&&(i>1))
- ii=i-1;
- end
- X2=i-1; % 去掉急剧变化的两端
- %=========底部轮廓检测===============%
- Bottom=zeros(1,x);
- for i=1:x
- j=y;
- while ((j>=1)&&(I(j,i)==1))
- jj=j-1;
- end
- if (j>=1)
- Bottom(i)=j;
- end
- end
- for i=1:x-1
- BottomD(i)=Bottom(i+1)-Bottom(i);
- end
- %数字 1的宽度特征%
- Width=zeros(1,y);
- for j=1:y
- Width(j)=Right(j)-Left(j);
- end
- W=max(Width);
- Po=0; % 用于检测笔画
- Ne=0;
- NS=0;%笔画数
- for i=X1+4:X2-4
- for j=1:y-1
- if ((I(j+1,i)-I(j,i))>0) % 由黑到白
- PoPo=Po+1;
- if ((Po>=2)&&(j<=fix(0.7*y)))
- Po=3;
- end
- else if ((I(j+1,i)-I(j,i))<0) % 由白到黑
- NeNe=Ne+1;
- if ((Ne>=2)&&(j<=fix(0.7*y)))
- Ne=3;
- end
- end
- end
- end
- NS=[NS max(Po,Ne)];
- Po=0;
- Ne=0;
- end
- Comp=max(NS);
- %======轮廓结构特征的提取======%
- if (min(W,Wx)>10)
- StrokeT=StrDetect01(TopD,X1,X2,3,6); % 检测顶部基本结构
- StrokeL=StrDetect01(LeftD,Y1,Y2,3,5); % 检测左边基本结构
- StrokeR=StrDetect01(RightD,Y1,Y2,3,5); % 检测右边基本结构
- StrokeB=StrDetect01(BottomD,X1,X2,3,6); % 检测底部基本结构
- %========== 识别 ==========%
- Digit=Recognition(StrokeT,StrokeL,StrokeR,StrokeB,Comp)
- else
- Digit='1'
- end
- t=toc
- % 以下代码显示识别出来的文字的各个部分轮廓
- px=(1:x);
- py=(1:y);
- figure(1);
- imshow(I); %在图像1中显示图像I
- figure(2);
- plot(Left);grid %在图像2中标注左轮廓
- title('左轮廓');
- figure(3);
- plot(Top);grid %在图像3中标注上轮廓
- title('上轮廓');
- figure(4);
- plot(Right);grid %在图像4中标注右轮廓
- title('右轮廓');
- figure(5);
- plot(Width);grid %在图像5中标注宽度
- title('宽度');