压印字符识别

转载自https://blog.csdn.net/woshilicong33/article/details/54234261

分享一个前段时间做的一个小东西吧,很简单,就是压印字符识别,当时老师的想法是想快速测量汽车发动机上边的型号,识别上边的字符,但是我们在实验室也没有买一台发动机过来,我就用3D打印机打印了一个不同高度的字符,其实方法很简单。就是利用高度调制余弦光栅相位变化,测相位变化量对应高度的关系,然后在同意一高度上抽取字符信息,然后扔到matlab里边就能识别,大概方法就是这样,获取相位展开这部分参考的是一篇论文《

Improved method for phase wraps reduction inprofilometry

》这个相位展开方法有一个缺陷就是高度超过2pi的是不 能完全展开的,但是我们的压印字符与背景的高度差很小,所以这种方法是完全适合的,而且速度很快,只要进行一维傅里叶变换就可以了,目前很多方法都是用的二维傅里叶变换,然后再逆变换回来,那样也可以得到,但是速度肯定是没有进行一维傅里叶变换来得更快,我们是不需要进行逆变换的。就当以上是一个摘要吧吐舌头

首先先讲讲基本算法。看一下结构图。

突起部分是被测表面,由于物体高度调制作用,原本打在A的光变成了C点的信息,如果我们投射结构光,那么接收的图像会有一个错位的变化,结构光选择余弦光栅,接收图像的变化就变成余弦光栅相位的变化。投影仪光心与摄像头的光心水平距离为 d ,两光心的水平线与参考面平行,摄像头与参考面的垂距离为 L 。当投影仪的出射光照射到参考平面的 A 点时,由于受到高度调制作用使照射在 A 点的光转移至 C 点。若设物体D点的高度为 h ,则由三角原理可得:

这样就建立了相位和高度的对应关系,下一步的关键就是获得相位信息。由于正弦光栅投射到漫反射物体表面后,COMS相机获取的变形栅像可以表示为:

 

式中, R( x , y ) 表示所测物体表面的不均匀分布反射率, A ( x , y)是背景强度, B ( x , y )/A( x , y ) 表示光栅条纹的对比度。 φ ( x , y)是相位值。采用移相的方法则可以比较准确的获取相位值,在相移法中,每次移动光栅周期的1/4,因而相移量为 π 2 。采集到的对应的四帧条纹图分别为:

 

此时获得的相位信息并不是真实的相位,因为反tan是一个周期函数,所以下一步就获得真实相位,也叫相位展开或者解包裹或者什么什么的。。。。

相位展开的方法就是用的Guangliang Du1等人的论文。想看英文原版的可以自己去下载,我就简单说一下原理。也是很简单的。得到折叠相位图像之后选取图像非字符区域的一行和一列,通常为第一行第一列。在选取的两个一维向量的两端进行补零操作具体公式为:

根据傅里叶变换的频移特性可知:

所以获得频移后的相位信息图像则可以进行移频计算:

只需要获得频移后的图像信息,所以不需要进行2维傅里叶变换和2维傅里叶逆变换,只需要进行如下计算即可:

所以相位信息即可由下列公式获得:

至此我们就得到了真实的相位信息,总结起来就很简单了,其实就是获取折叠相位背景的横纵频率,找到基频位置,把图像转换到复数域之后整幅图像根据横纵方向的基频进行移动,这样就把背景给滤掉了,只剩下字符的相位信息。来说一下实测过程。

结构图

 

被测字符

被测物体,有人看到被测物体说我这个环境要求太高,背景都是黑色的,其实不是这样的,这跟打光和光圈调节有关系,而且我们的误差也不在黑色部分,而是那个白色的背景才是干扰部分,黑色部分没有我们需要的信息,首先设置感兴趣去就是那个正方形的白色字符,然后投射四幅相位差是pi/2的余弦光栅。获得折叠相位。

 

这是折叠相位的图像,因为我们投射光栅的频率比较低,字符的板子又比较短所以打在字符上的光也很少,我们提取感兴趣之后,字符板子上只有不到2个周期的光栅,当然这是不影响测量的,只是看着不太好看。

下一步就是提取第一行和第一列的数据然后进行补零操作,这一步的补零目的就是提高傅里叶的采样频率,这样可以提高基频位置的精度。补零很简单了,中间是数据,两边就是零。下图

然后进行傅里叶变换,算横纵两个方向的基频,傅里叶变换之后的图像。

找到两个方向的基频,把图像转换到复数域之后,进行频移变换。就可以得到字符的相位信息。

这是三维的图像,再看一下灰度的图像。

 

中间的字符部分的灰度值比较高,高度不同的三行字符,他们的灰度值也是不同,此时灰度值反应的就是字符的高度信息。选取不同的阈值进行滤波就可以得到字符信息。

v6-fsi 是高度1mm的字符,下边的bosch是3mm的字符,设定不同阈值选取不同高度下的字符。然后直接让matlab去识别就好了,那就是很传统的方法我就不说了。这里边我这个效果还不是很好,这里边我能想到几个原因,首先就是我们拍摄的距离比较远,而相机的像素也不是很高,所以很多细节都拍不到的。因为相位对高度是很敏感的,我们用肉眼都很难分辨相位的变换,还有一个问题就是我们的光栅频率比较小,理论上光栅频率越大我 们能分辨的细节越多。我们实验室用相位的方法都可以测量出指纹的高度。很精密的东西。最后看一下matlab的代码。很多人可能可以看懂公式但是没办法把公式别称代码,这个是需要多加练习就可以。很简单也就是六十多行。

thre=0.1;  %滤波二值化阈值
fs=1;   %操作图像放缩比
A0=double(rgb2gray(imread('D:\222\0.JPG')))/255;
A1=double(rgb2gray(imread('D:\222\L1.JPG')))/255;
A2=double(rgb2gray(imread('D:\222\L2.JPG')))/255;
A3=double(rgb2gray(imread('D:\222\L3.JPG')))/255;
A4=double(rgb2gray(imread('D:\222\L4.JPG')))/255;
A0=im2bw(A0,thre);
imshow(A0);
h = imrect;
position = wait(h);
A2_4=A4-A2;
A3_1=A1-A3;
a1=atan2(A2_4,A3_1);
imshow(a1);
a1=double(A0).*a1;
a1=imresize(a1,fs); %可选
imshow(a1);
a1=imcrop(a1,position);
imshow(a1);
li=1;
[m,n]=size(a1+pi);
fwc=cos(a1)+1i*sin(a1);
fwc1=[zeros(1,20*n),fwc(li,:),zeros(1,20*n)];
fwc2=[zeros(20*m,1);fwc(:,li);zeros(20*m,1)];
fx=fft(fwc1);
[fxm,fxn]=max(fx);
fxn=(fxn-1)/41;
fy=fft(fwc2);
[fym,fyn]=max(fy);
fyn=(fyn-1)/41-(fyn-1)/41;
 
for k=1:m
    for j=1:n
        x3(k,j)=fwc(k,j)*exp(-1i*2*pi*((fyn)*(k-1)/m+(fxn)*(j-1)/n));
    end
end
y1=atan(imag(x3)./real(x3));
figure;
mesh(-y1);
 
y2=-y1;
[m1,n1]=size(y2);
OutImg = Normalize(y2);
mesh(OutImg);
for k=1:m1   %1:m
   for j=1:n1   %1:n
       if OutImg(k,j) > 170
          Fc3(k,j)=1;    
       else 
          Fc3(k,j)=0; 
       end
   end
end
figure(2);
imshow(Fc3);
 
ocrResults = ocr(Fc3);   
recognizedText = ocrResults.Text;   
imshow(Fc3);   
text(10,50,recognizedText,'BackgroundColor',[1,1,1]);   
title('识别字符'); 

  

猜你喜欢

转载自www.cnblogs.com/qcjd/p/9455151.html