车牌识别--倾斜矫正

来源:互联网 发布:淘宝帐号能注销吗 编辑:程序博客网 时间:2024/04/27 19:23

在车牌识别系统中, 车牌字符能够正确分割的前提是车牌图像能够水平,以至于水平投影和垂直投影能够正常进行。如果车牌倾斜没有矫正,那么水平投影和垂直投影,甚至铆钉都无法正常处理。所以,当车辆信息中获取车牌的第一步,应该是检查倾斜角度,做倾斜矫正。

倾斜矫正,这里使用的算法:

1、倾斜角度检测: 霍夫变换

关于hough变换,可以参考前面图像处理博文:

http://blog.csdn.net/liujia2100/article/details/6989693   直线检测

http://blog.csdn.net/liujia2100/article/details/6989688   文本图像倾斜矫正


2、倾斜矫正: 图像旋转


下面详细说明倾斜矫正过程:

原车牌图像为(从车牌图像中,可以看到车牌有倾斜角度):



1、 获取车牌在车辆中的粗略位置(可以用多种方法,这里暂不分析)


2、提取车牌整体图片数据, 根据第一步结果,提取出,车牌在辆大体位置信息。

关于车牌定位,我使用两部,第一步粗略定位,然后做一些预处理,比如倾斜矫正,然后第二部才是精确定位,只提取车牌的位置信息图像


3、利用HSV颜色空间转换,获取车牌背景蓝色区域位置,获取车牌粗略信息图像后,由于车牌背景颜色与周围颜色有很明显的区别,这里采用HSV颜色过滤的方法,过滤绿色背景图像


4、水平膨胀, 水平膨胀的目的,是为了边缘检测,只要求检测边缘,尽量除去字符信息,也可以降低hough变换的运算量


5、水平差分运算,相当于 边缘检测,经过上面的处理后,才进行边缘检测


6、这个时候就可以利用hough变换检测直线了。

由于hough变换运算量十分大,所以,尽量减少图像中的白点,来降低计算量,因此前面才做了这么多步骤。

请看下图的红线,就是检测出来的角度,为177度(Hough代码在下面)。



7、利用旋转算法,旋转刚才粗略提取的车牌位置(旋转代码在下面),尽管旋转后的车牌有些锯齿,但是已经能够保证水平,就可以使用水平投影和垂直投影了


这是旋转后的车牌,有些锯齿出现,由于图像分辨率较低,就没有用差值运算。


8、精确提取车牌



9、正常分割字符



10、识别结果



由于正弦余弦运算,计算量比较大,这里进行一部分优化,就是正弦余弦计算用数组代替。

生成正弦,余弦数组的的代码如下:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <math.h>  
  5.   
  6. int main(void)  
  7. {  
  8.     char buf[20];  
  9.     int i;  
  10.     float p;  
  11.     float k;  
  12.     FILE *fcos;  
  13.     FILE *fsin;  
  14.       
  15.     fcos = fopen(".\\cos.txt""wb");  
  16.     fsin = fopen(".\\sin.txt""wb");  
  17.       
  18.     if(fcos == NULL || fsin == NULL)  
  19.     {  
  20.         printf("open error\n");  
  21.         exit(-1);  
  22.     }  
  23.   
  24.   
  25.     i = 0;  
  26.   
  27.     for(i = 0; i <= 180; i++)  
  28.     {  
  29.         k = 3.1415926 * i / 180.0;  
  30.         p = cos(k);  
  31.           
  32.                   
  33.         if((i%16 == 0))  
  34.             fwrite("\n",strlen("\n"),1,fcos);  
  35.           
  36.         sprintf(buf,"%f, ", p);  
  37.         fwrite(buf,strlen(buf),1,fcos);  
  38.   
  39.     }  
  40.   
  41.     for(i = 0; i <= 180; i++)  
  42.     {  
  43.         k = 3.1415926 * i / 180.0;  
  44.         p = sin(k);  
  45.           
  46.                   
  47.         if((i%16 == 0))  
  48.             fwrite("\n",strlen("\n"),1,fsin);  
  49.           
  50.         sprintf(buf,"%f, ", p);  
  51.         fwrite(buf,strlen(buf),1,fsin);  
  52.   
  53.     }  
  54.     fclose(fcos);  
  55.     fclose(fsin);  
  56.     return 0;  
  57. }  

生成数组为:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. float carCos[] = {  
  2. 1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195, 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627, 0.978148, 0.974370, 0.970296, 0.965926,   
  3. 0.961262, 0.956305, 0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505, 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620, 0.866025, 0.857167,   
  4. 0.848048, 0.838671, 0.829038, 0.819152, 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710, 0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,   
  5. 0.669131, 0.656059, 0.642788, 0.629320, 0.615662, 0.601815, 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038, 0.500000, 0.484810, 0.469472, 0.453991,   
  6. 0.438371, 0.422618, 0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568, 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951, 0.207912, 0.190809,   
  7. 0.173648, 0.156434, 0.139173, 0.121869, 0.104528, 0.087156, 0.069757, 0.052336, 0.034900, 0.017452, 0.000000, -0.017452, -0.034899, -0.052336, -0.069756, -0.087156,   
  8. -0.104528, -0.121869, -0.139173, -0.156434, -0.173648, -0.190809, -0.207912, -0.224951, -0.241922, -0.258819, -0.275637, -0.292372, -0.309017, -0.325568, -0.342020, -0.358368,   
  9. -0.374607, -0.390731, -0.406737, -0.422618, -0.438371, -0.453990, -0.469472, -0.484810, -0.500000, -0.515038, -0.529919, -0.544639, -0.559193, -0.573576, -0.587785, -0.601815,   
  10. -0.615661, -0.629320, -0.642788, -0.656059, -0.669131, -0.681998, -0.694658, -0.707107, -0.719340, -0.731354, -0.743145, -0.754710, -0.766044, -0.777146, -0.788011, -0.798635,   
  11. -0.809017, -0.819152, -0.829038, -0.838671, -0.848048, -0.857167, -0.866025, -0.874620, -0.882948, -0.891007, -0.898794, -0.906308, -0.913545, -0.920505, -0.927184, -0.933580,   
  12. -0.939693, -0.945519, -0.951056, -0.956305, -0.961262, -0.965926, -0.970296, -0.974370, -0.978148, -0.981627, -0.984808, -0.987688, -0.990268, -0.992546, -0.994522, -0.996195,   
  13. -0.997564, -0.998630, -0.999391, -0.999848, -1.000000  
  14. };  
  15.   
  16. float carSin[] = {  
  17. 0.000000, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156, 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809, 0.207912, 0.224951, 0.241922, 0.258819,   
  18. 0.275637, 0.292372, 0.309017, 0.325568, 0.342020, 0.358368, 0.374607, 0.390731, 0.406737, 0.422618, 0.438371, 0.453990, 0.469472, 0.484810, 0.500000, 0.515038,   
  19. 0.529919, 0.544639, 0.559193, 0.573576, 0.587785, 0.601815, 0.615661, 0.629320, 0.642788, 0.656059, 0.669131, 0.681998, 0.694658, 0.707107, 0.719340, 0.731354,   
  20. 0.743145, 0.754710, 0.766044, 0.777146, 0.788011, 0.798635, 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167, 0.866025, 0.874620, 0.882948, 0.891007,   
  21. 0.898794, 0.906308, 0.913545, 0.920505, 0.927184, 0.933580, 0.939693, 0.945519, 0.951056, 0.956305, 0.961262, 0.965926, 0.970296, 0.974370, 0.978148, 0.981627,   
  22. 0.984808, 0.987688, 0.990268, 0.992546, 0.994522, 0.996195, 0.997564, 0.998630, 0.999391, 0.999848, 1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,   
  23. 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627, 0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305, 0.951057, 0.945519, 0.939693, 0.933580,   
  24. 0.927184, 0.920505, 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620, 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152, 0.809017, 0.798636,   
  25. 0.788011, 0.777146, 0.766044, 0.754710, 0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998, 0.669131, 0.656059, 0.642788, 0.629320, 0.615662, 0.601815,   
  26. 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038, 0.500000, 0.484810, 0.469472, 0.453991, 0.438371, 0.422618, 0.406737, 0.390731, 0.374607, 0.358368,   
  27. 0.342020, 0.325568, 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951, 0.207912, 0.190809, 0.173648, 0.156435, 0.139173, 0.121869, 0.104529, 0.087156,   
  28. 0.069757, 0.052336, 0.034900, 0.017452, 0.000000  
  29. };  


旋转RGB图像的主要函数:

image: 图像数据

iRotateAngle: 要旋转的角度

width, height:原始图像的宽度,高度

lwidth,lheight:旋转后图像的宽度,高度

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. unsigned char *RotateRGB(unsigned char *image, float iRotateAngle,int width,int height,int &lwidth,int &lheight)  
  2. {  
  3.   
  4.     int i,j,k,m,n;   
  5.     long    lNewWidth;  
  6.     long    lNewHeight;  
  7.     float gray;  
  8.     long    i0;  
  9.     long    j0;  
  10.     float   fRotateAngle;  
  11.     float   fSina, fCosa;  
  12.     float   fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;  
  13.     float   fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;  
  14.   
  15.     float   f1,f2;  
  16.   
  17.   
  18.     if(iRotateAngle >= 0)  
  19.     {  
  20.         fSina = (float)carSin[(int)iRotateAngle];  
  21.         fCosa = (float)carCos[(int)iRotateAngle];  
  22.     }  
  23.     else  
  24.     {  
  25.         fSina = 0 - (float)carSin[0 -(int)iRotateAngle];  
  26.         fCosa = (float)carCos[0 - (int)iRotateAngle];  
  27.     }  
  28.   
  29.     fSrcX1 = (float) (- (width  - 1) / 2);  
  30.     fSrcY1 = (float) (  (height - 1) / 2);  
  31.     fSrcX2 = (float) (  (width  - 1) / 2);  
  32.     fSrcY2 = (float) (  (height - 1) / 2);  
  33.     fSrcX3 = (float) (- (width  - 1) / 2);  
  34.     fSrcY3 = (float) (- (height - 1) / 2);  
  35.     fSrcX4 = (float) (  (width  - 1) / 2);  
  36.     fSrcY4 = (float) (- (height - 1) / 2);  
  37.       
  38.   
  39.     fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;  
  40.     fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;  
  41.     fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;  
  42.     fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;  
  43.     fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;  
  44.     fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;  
  45.     fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;  
  46.     fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;  
  47.   
  48.     lNewWidth  = (long) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);  
  49.   
  50.     lNewHeight = (long) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);  
  51.     unsigned char *temp=myMalloc(lNewHeight*lNewWidth*3,0,0);  
  52.   
  53.     f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina  
  54.         + 0.5 * (width  - 1));  
  55.     f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa  
  56.         + 0.5 * (height - 1));  
  57.   
  58.     for(i = 0; i < lNewHeight; i++)  
  59.     {  
  60.         for(m=0,j = 0;j < lNewWidth,m<lNewWidth*3;m+=3,j++)  
  61.         {  
  62.             i0 = (long) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5);  
  63.             j0 = (long) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5);  
  64.               
  65.             if( (j0 >= 0) && (j0 < width) && (i0 >= 0) && (i0 < height))  
  66.             {  
  67.                  n=i0 * width * 3 + j0 * 3;  
  68.                  *(temp + lNewWidth * i * 3 + m + 1) = *(image + n + 1);  
  69.                  *(temp + lNewWidth * i * 3 + m + 2) = *(image + n + 2);  
  70.                  *(temp + lNewWidth * i * 3 + m) = *(image + n);  
  71.             }  
  72.             else  
  73.             {  
  74.                  *(temp + lNewWidth * i*3+ m+1)=0;  
  75.                  *(temp + lNewWidth * i*3+ m+2)=0;  
  76.                  *(temp + lNewWidth * i*3+ m)=0;  
  77.             }  
  78.         }  
  79.     }  
  80.   
  81.     lwidth = lNewWidth;  
  82.     lheight = lNewHeight;  
  83.   
  84.     return temp;  
  85.       
  86. }  

Hough变化的主要函数

返回值Kmax,就是检测到最长直线的角度,就是车牌的倾斜角度。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int hough(unsigned char *srcBmp,int width,int height)  
  2. {  
  3.     int kmax=0;  
  4.     int pmax=0;  
  5.     int yuzhi=0;  
  6.     int i,j,k,m,n,p;  
  7.     int mp = (int) (sqrt(width*width + height*height)+1);  
  8.     int ma = 180;//180  
  9.     int ap;  
  10.     int npp[180][1000];  
  11.     for(i=0;i<180;i++)  
  12.         for(j=0;j<1000;j++)  
  13.         npp[i][j]=0;  
  14.           
  15.     for(i = 0;i < height;i++)  
  16.         for(j = 0; j < width;j++)  
  17.         {  
  18.             if(srcBmp[i * width + j]==255)  
  19.             {   
  20.                 for(k = 0; k < ma; k++)  
  21.                 {  
  22.                     p=(int)(i * carCos[k] + j * carSin[k]);  
  23.                     p=(int)(p/2 + mp/2);  
  24.                     npp[k][p]=npp[k][p]++;  
  25.                 }   
  26.             }  
  27.         }  
  28.         kmax=0;  
  29.         pmax=0;  
  30.         n=0;  
  31.         for(i = 0; i < ma; i++)  
  32.             for(j = 0; j < mp; j++)  
  33.             {  
  34.                 if(npp[i][j] > yuzhi)  
  35.                 {  
  36.                     yuzhi=npp[i][j];  
  37.                     kmax=i;  
  38.                     pmax=j;  
  39.                 }  
  40.             }  
  41.             for(i = 0; i < height;i++)  
  42.                 for(j = 0; j < width;j++)  
  43.                 {  
  44.                     if(srcBmp[i*width+j]==255)  
  45.                     {   
  46.                         p=(int)(i*carCos[kmax] + j *carSin[kmax]);  
  47.                         p=(int)(p/2+mp/2);  
  48. #if defined(DISPLAYDEBUG)  
  49.                         if(p==pmax)  
  50.                         putpixel(j,i,RGB(255,0,0));  
  51. #endif  
  52.                     }  
  53.                 }  
  54.                 return kmax;  
  55. }  

网址:http://blog.csdn.net/liujia2100/article/details/26989939
0 0
原创粉丝点击