OpenCV图像处理车牌检测与定位应用

这两天在做关于车牌识别的实验,用了几种方式:

1.车牌颜色分布(HSV空间,YCrCb空间的没有颜色分布图谱,无法实验);利用HSV的H通道,效果一般,受环境影响大。

[cpp]  view plain copy
  1. #include "highgui.h"  
  2. #include "cv.h"  
  3. #include <stdio.h>     
  4. #include <math.h>    
  5. #include <string>  
  6. #include<iostream>  
  7. using namespace std;  
  8.   
  9. CvPoint Point;  
  10. IplImage* img=0;  
  11. // skin region location using rgb limitation  
  12. void SkinRGB(IplImage* rgb,IplImage* _dst)  
  13. {  
  14.     assert(rgb->nChannels==3&& _dst->nChannels==3);  
  15.   
  16.     static const int R=2;  
  17.     static const int G=1;  
  18.     static const int B=0;  
  19.   
  20.     IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  21.     cvZero(dst);  
  22.   
  23.     for (int h=0;h<rgb->height;h++) {  
  24.         unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;  
  25.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  26.         for (int w=0;w<rgb->width;w++) {  
  27.             if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&  
  28.                 prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15/*&& 
  29.                 !(prgb[R]>170&&prgb[G]>170&&prgb[B]>170)*/)||//uniform illumination   
  30.                 (prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&  
  31.                 abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B])//lateral illumination  
  32.                 ) {  
  33.                     memcpy(pdst,prgb,3);  
  34.             }             
  35.             prgb+=3;  
  36.             pdst+=3;  
  37.         }  
  38.     }  
  39.     cvCopyImage(dst,_dst);  
  40.     cvReleaseImage(&dst);  
  41. }  
  42. // skin detection in rg space  
  43. void cvSkinRG(IplImage* rgb,IplImage* gray)  
  44. {  
  45.     assert(rgb->nChannels==3&&gray->nChannels==1);  
  46.       
  47.     const int R=2;  
  48.     const int G=1;  
  49.     const int B=0;  
  50.   
  51.     double Aup=-1.8423;  
  52.     double Bup=1.5294;  
  53.     double Cup=0.0422;  
  54.     double Adown=-0.7279;  
  55.     double Bdown=0.6066;  
  56.     double Cdown=0.1766;  
  57.     for (int h=0;h<rgb->height;h++) {  
  58.         unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;  
  59.         unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;  
  60.         for (int w=0;w<rgb->width;w++)   
  61.         {  
  62.             int s=pRGB[R]+pRGB[G]+pRGB[B];  
  63.             double r=(double)pRGB[R]/s;  
  64.             double g=(double)pRGB[G]/s;  
  65.             double Gup=Aup*r*r+Bup*r+Cup;  
  66.             double Gdown=Adown*r*r+Bdown*r+Cdown;  
  67.             double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);  
  68.             if (g<Gup && g>Gdown && Wr>0.004)  
  69.             {  
  70.                 *pGray=255;  
  71.             }  
  72.             else  
  73.             {   
  74.                 *pGray=0;  
  75.             }  
  76.             pGray++;  
  77.             pRGB+=3;  
  78.         }  
  79.     }  
  80.   
  81. }  
  82. // implementation of otsu algorithm  
  83. // author: onezeros#yahoo.cn  
  84. // reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB  
  85. void cvThresholdOtsu(IplImage* src, IplImage* dst)  
  86. {  
  87.     int height=src->height;  
  88.     int width=src->width;  
  89.   
  90.     //histogram  
  91.     float histogram[256]={0};  
  92.     for(int i=0;i<height;i++) {  
  93.         unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;  
  94.         for(int j=0;j<width;j++) {  
  95.             histogram[*p++]++;  
  96.         }  
  97.     }  
  98.     //normalize histogram  
  99.     int size=height*width;  
  100.     for(int i=0;i<256;i++) {  
  101.         histogram[i]=histogram[i]/size;  
  102.     }  
  103.   
  104.     //average pixel value  
  105.     float avgValue=0;  
  106.     for(int i=0;i<256;i++) {  
  107.         avgValue+=i*histogram[i];  
  108.     }  
  109.   
  110.     int threshold;    
  111.     float maxVariance=0;  
  112.     float w=0,u=0;  
  113.     for(int i=0;i<256;i++) {  
  114.         w+=histogram[i];  
  115.         u+=i*histogram[i];  
  116.   
  117.         float t=avgValue*w-u;  
  118.         float variance=t*t/(w*(1-w));  
  119.         if(variance>maxVariance) {  
  120.             maxVariance=variance;  
  121.             threshold=i;  
  122.         }  
  123.     }  
  124.   
  125.     cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);  
  126. }  
  127.   
  128. void cvSkinOtsu(IplImage* src, IplImage* dst)  
  129. {  
  130.     assert(dst->nChannels==1&& src->nChannels==3);  
  131.   
  132.     IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
  133.     IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  134.     cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
  135.     cvSplit(ycrcb,0,cr,0,0);  
  136.   
  137.     cvThresholdOtsu(cr,cr);  
  138.     cvCopyImage(cr,dst);  
  139.     cvReleaseImage(&cr);  
  140.     cvReleaseImage(&ycrcb);  
  141. }  
  142.   
  143. void cvSkinYUV(IplImage* src,IplImage* dst)  
  144. {  
  145.     IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
  146.     //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  147.     //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);  
  148.     cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
  149.     //cvSplit(ycrcb,0,cr,cb,0);  
  150.   
  151.     static const int Cb=2;  
  152.     static const int Cr=1;  
  153.     static const int Y=0;  
  154.   
  155.     //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  156.     cvZero(dst);  
  157.   
  158.     for (int h=0;h<src->height;h++) {  
  159.         unsigned char* pycrcb=(unsigned char*)ycrcb->imageData+h*ycrcb->widthStep;  
  160.         unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;  
  161.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  162.         for (int w=0;w<src->width;w++) {  
  163.             if ((pycrcb[Cr]<=126||pycrcb[Cr]>=130)&&(pycrcb[Cb]<=126||pycrcb[Cb]>=130))  
  164.             {  
  165.                     memcpy(pdst,psrc,3);  
  166.             }  
  167.             pycrcb+=3;  
  168.             psrc+=3;  
  169.             pdst+=3;  
  170.         }  
  171.     }  
  172.     //cvCopyImage(dst,_dst);  
  173.     //cvReleaseImage(&dst);  
  174. }  
  175.   
  176. void cvSkinHSV(IplImage* src,IplImage* dst)  
  177. {  
  178.     IplImage* hsv=cvCreateImage(cvGetSize(src),8,3);  
  179.     //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  180.     //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);  
  181.     cvCvtColor(src,hsv,CV_BGR2HSV);  
  182.     //cvSplit(ycrcb,0,cr,cb,0);  
  183.   
  184.     static const int V=2;  
  185.     static const int S=1;  
  186.     static const int H=0;  
  187.   
  188.     //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  189.     cvZero(dst);  
  190.   
  191.     for (int h=0;h<src->height;h++) {  
  192.         unsigned char* phsv=(unsigned char*)hsv->imageData+h*hsv->widthStep;  
  193.         unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;  
  194.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  195.         for (int w=0;w<src->width;w++) {  
  196.             if (phsv[H]>=90&&phsv[H]<=135)  
  197.             {  
  198.                     memcpy(pdst,psrc,3);  
  199.             }  
  200.             phsv+=3;  
  201.             psrc+=3;  
  202.             pdst+=3;  
  203.         }  
  204.     }  
  205.     //cvCopyImage(dst,_dst);  
  206.     //cvReleaseImage(&dst);  
  207. }  
  208.   
  209. void on_mouse(int event,int x,int y,int flags,void* param )    
  210. {    
  211.      switch(event)    
  212.      {    
  213.      case CV_EVENT_LBUTTONUP:    
  214.          {    
  215.              Point=cvPoint(x,y);    
  216.          }    
  217.             cvCircle(img,Point,1,CV_RGB(255,0,0),1);  
  218.             CvScalar HSV=cvGet2D(img,x,y);  
  219.             cout<<"H:"<<HSV.val[0]<<"\t S:"<<HSV.val[1]<<"\t V:"<<HSV.val[2]<<endl;   
  220.          break;    
  221.      }    
  222.     
  223. //printf("( %d, %d) ",x,y);    
  224. //printf("The Event is : %d ",event);    
  225. //printf("The flags is : %d ",flags);    
  226. //printf("The param is : %d\n",param);    
  227. }  
  228. int main()  
  229. {     
  230.       
  231.     IplImage* img0= cvLoadImage("D:/image/car/00.jpg"); //随便放一张jpg图片在D盘或另行设置目录  
  232.     img=cvCreateImage(cvSize(400,300),8,3);  
  233.     cvResize(img0,img);  
  234.     IplImage* dstRGB=cvCreateImage(cvGetSize(img),8,3);  
  235.     IplImage* dstRG=cvCreateImage(cvGetSize(img),8,1);  
  236.     IplImage* dst_crotsu=cvCreateImage(cvGetSize(img),8,1);  
  237.     IplImage* dst_YUV=cvCreateImage(cvGetSize(img),8,3);  
  238.     IplImage* dst_HSV=cvCreateImage(cvGetSize(img),8,3);  
  239.   
  240.   
  241.     cvNamedWindow("inputimage", CV_WINDOW_AUTOSIZE);  
  242.     cvShowImage("inputimage", img);  
  243.     cvWaitKey(0);  
  244.     /* 
  245.     SkinRGB(img,dstRGB); 
  246.     cvNamedWindow("outputimage1", CV_WINDOW_AUTOSIZE); 
  247.     cvShowImage("outputimage1", dstRGB); 
  248.     cvWaitKey(0); 
  249.     cvSkinRG(img,dstRG); 
  250.     cvNamedWindow("outputimage2", CV_WINDOW_AUTOSIZE); 
  251.     cvShowImage("outputimage2", dstRG); 
  252.     cvWaitKey(0); 
  253.     cvSkinOtsu(img,dst_crotsu); 
  254.     cvNamedWindow("outputimage3", CV_WINDOW_AUTOSIZE); 
  255.     cvShowImage("outputimage3", dst_crotsu); 
  256.     cvWaitKey(0); 
  257.      
  258.     cvSkinYUV(img,dst_YUV); 
  259.     cvNamedWindow("outputimage4", CV_WINDOW_AUTOSIZE); 
  260.     cvShowImage("outputimage4", dst_YUV); 
  261.     //cvSaveImage("D:/skin04.jpg",dst_YUV); 
  262.     cvWaitKey(0); 
  263.     */  
  264.     cvSkinHSV(img,dst_HSV);  
  265.     cvNamedWindow("outputimage5", CV_WINDOW_AUTOSIZE);  
  266.     cvShowImage("outputimage5", dst_HSV);  
  267.     cvSaveImage("D:/image/car/car00.jpg",dst_HSV);  
  268.     cvWaitKey(0);  
  269.       
  270.     return 0;  
  271. }  

2.Canny+Hough;效果也不好,但学习了hough变换的有关内容。

[cpp]  view plain copy
  1. #include <cv.h>  
  2. #include <highgui.h>  
  3. #include <math.h>  
  4.    
  5. int main(int argc, char** argv)  
  6. {  
  7.     const char* filename = argc >= 2 ? argv[1] : "D:/image/car/car04.jpg";  
  8.     IplImage* src = cvLoadImage( filename, 0 );  
  9.     cvDilate(src,src);  
  10.     IplImage* dst;  
  11.     IplImage* color_dst;  
  12.     CvMemStorage* storage = cvCreateMemStorage(0);  
  13.     CvSeq* lines = 0;  
  14.     int i;  
  15.    
  16.     if( !src )  
  17.         return -1;  
  18.    
  19.     dst = cvCreateImage( cvGetSize(src), 8, 1 );  
  20.     color_dst = cvCreateImage( cvGetSize(src), 8, 3 );  
  21.    
  22.     cvCanny( src, dst, 50, 150, 3 );  
  23.     cvCvtColor( dst, color_dst, CV_GRAY2BGR );  
  24.       
  25. #if 0  
  26.     lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100, 0, 0 );  
  27.    
  28.     for( i = 0; i < MIN(lines->total,100); i++ )  
  29.     {  
  30.         float* line = (float*)cvGetSeqElem(lines,i);  
  31.         float rho = line[0];  
  32.         float theta = line[1];  
  33.         CvPoint pt1, pt2;  
  34.         double a = cos(theta), b = sin(theta);  
  35.         double x0 = a*rho, y0 = b*rho;  
  36.         pt1.x = cvRound(x0 + 1000*(-b));  
  37.         pt1.y = cvRound(y0 + 1000*(a));  
  38.         pt2.x = cvRound(x0 - 1000*(-b));  
  39.         pt2.y = cvRound(y0 - 1000*(a));  
  40.         cvLine( color_dst, pt1, pt2, CV_RGB(255,0,0), 3, CV_AA, 0 );  
  41.     }  
  42. #else  
  43.       
  44.     lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 5, 3 );  
  45.     for( i = 0; i < lines->total; i++ )  
  46.     {  
  47.         CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);  
  48.         cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );  
  49.     }  
  50. //#endif  
  51.     cvNamedWindow( "Source", 1 );  
  52.     cvShowImage( "Source", src );  
  53.    
  54.     cvNamedWindow( "Hough", 1 );  
  55.     cvShowImage( "Hough", color_dst );  
  56.    
  57.     cvWaitKey(0);  
  58.    
  59.     return 0;  
  60. }  

3.Coutour检测;效果勉强。

[cpp]  view plain copy
  1. #include "cv.h"  
  2. #include "highgui.h"  
  3. #include <cxcore.h>  
  4. #include <stdio.h>  
  5.    
  6. int BinarizeImageByOTSU (IplImage * src)  
  7. {   
  8.     assert(src != NULL);  
  9.    
  10.     //get the ROI  
  11.     CvRect rect = cvGetImageROI(src);  
  12.    
  13.     //information of the source image  
  14.     int x = rect.x;  
  15.     int y = rect.y;  
  16.     int width = rect.width;   
  17.     int height = rect.height;  
  18.     int ws = src->widthStep;  
  19.    
  20.     int thresholdValue=1;//阈值  
  21.     int ihist [256] ; // 图像直方图, 256个点  
  22.     int i, j, k,n, n1, n2, Color=0;  
  23.     double m1, m2, sum, csum, fmax, sb;  
  24.     memset (ihist, 0, sizeof (ihist)) ; // 对直方图置 零...  
  25.    
  26.     for (i=y;i< y+height;i++) // 生成直方图  
  27.     {   
  28.         int mul =  i*ws;  
  29.         for (j=x;j<x+width;j++)  
  30.         {   
  31.             //Color=Point (i,j) ;  
  32.             Color = (int)(unsigned char)*(src->imageData + mul+ j);  
  33.             ihist [Color] +=1;  
  34.         }  
  35.     }  
  36.     sum=csum=0.0;  
  37.     n=0;  
  38.     for (k = 0; k <= 255; k++)  
  39.     {   
  40.         sum+= (double) k* (double) ihist [k] ; // x*f (x) 质量矩  
  41.         n +=ihist [k]; //f (x) 质量  
  42.     }  
  43.     // do the otsu global thresholding method  
  44.     fmax = - 1.0;  
  45.     n1 = 0;  
  46.     for (k=0;k<255;k++)   
  47.     {  
  48.         n1+=ihist [k] ;  
  49.         if (! n1)  
  50.         {   
  51.             continue;   
  52.         }  
  53.         n2=n- n1;  
  54.         if (n2==0)   
  55.         {  
  56.             break;  
  57.         }  
  58.         csum+= (double) k*ihist [k] ;  
  59.         m1=csum/ n1;  
  60.         m2= (sum- csum) /n2;  
  61.         sb = ( double) n1* ( double) n2* ( m1 - m2) * (m1- m2) ;  
  62.    
  63.         if (sb>fmax)   
  64.         {  
  65.             fmax=sb;  
  66.             thresholdValue=k;  
  67.         }  
  68.     }  
  69.    
  70.     //binarize the image   
  71.     cvThreshold( src, src ,thresholdValue, 255, CV_THRESH_BINARY );   
  72.     return 0;  
  73. }   
  74.    
  75. int main( int argc, char* argv[])  
  76. {  
  77.     IplImage* src;  
  78.     if((src=cvLoadImage("D:/image/car/05sobel.jpg", 0)))//载入图像  
  79.     {  
  80.         //为轮廓显示图像申请空间,3通道图像,以便用彩色显示  
  81.         IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3);  
  82.         //创建内存块,将该块设置成默认值,当前默认大小为64k  
  83.         CvMemStorage* storage = cvCreateMemStorage(0);  
  84.         //可动态增长元素序列  
  85.         CvSeq* contour = 0;  
  86.         //对图像进行自适二值化  
  87.         BinarizeImageByOTSU(src);  
  88.         //图像膨胀  
  89.         cvDilate(src,src);  
  90.         //图像腐蚀  
  91.         cvErode(src,src);  
  92.         //显示源图像的二值图  
  93.         cvNamedWindow( "Source", 1 );  
  94.         cvShowImage( "Source", src );  
  95.         //在二值图像中寻找轮廓  
  96.         cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );  
  97.         cvZero( dst );//清空数组  
  98.         cvCvtColor(src,dst,CV_GRAY2BGR);  
  99.         //目标轮廓最小下限  
  100.         int mix_area = 2500;  
  101.         //目标轮廓最大上限  
  102.         int max_area = 3500;  
  103.         //可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器  
  104.         CvScalar color = CV_RGB( 255, 0, 0);  
  105.         //在图像中绘制外部和内部的轮廓  
  106.         for( ; contour != 0; contour = contour->h_next)  
  107.         {  
  108.             //取得轮廓的最小矩形  
  109.             CvRect aRect = cvBoundingRect( contour, 1 );  
  110.             //取得矩形的面积  
  111.             int tmparea=aRect.height*aRect.height;  
  112.             //用车牌的形态做判断  
  113.             if (((double)aRect.width/(double)aRect.height>3)  
  114.                 && ((double)aRect.width/(double)aRect.height<6))  
  115.             {  
  116.                 cvRectangle(dst,cvPoint(aRect.x,aRect.y),cvPoint(aRect.x+aRect.width ,aRect.y+aRect.height),color,2);  
  117.                 //cvDrawContours( dst, contour, color, color, -1, 1, 8 );  
  118.             }  
  119.         }  
  120.    
  121.         cvNamedWindow( "Components", 1 );  
  122.         cvShowImage( "Components", dst );  
  123.         cvWaitKey(0);     
  124.         cvDestroyWindow("Components");  
  125.         cvReleaseImage(&dst);  
  126.         cvDestroyWindow("Source");  
  127.         cvReleaseImage(&src);  
  128.    
  129.         return 0;  
  130.     }     
  131.     return 1;  
  132. }  

4.Squares方式:Canny||Threshold+cvFindContours+cvApproxPoly;效果一般

[cpp]  view plain copy
  1. #ifdef _CH_  
  2. #pragma package <opencv>  
  3. #endif  
  4.   
  5. #ifndef _EiC  
  6. #include "cv.h"  
  7. #include "highgui.h"  
  8. #include <stdio.h>  
  9. #include <math.h>  
  10. #include <string.h>  
  11. #endif  
  12.   
  13. int thresh = 50;  
  14. IplImage* img = 0;  
  15. IplImage* img0 = 0;  
  16. CvMemStorage* storage =  cvCreateMemStorage(0);  
  17. CvPoint pt[4];  
  18. const char* wndname = "Square Detection Demo";  
  19.   
  20. // helper function:  
  21. // finds a cosine of angle between vectors  
  22. // from pt0->pt1 and from pt0->pt2   
  23. double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )  
  24. {  
  25.     double dx1 = pt1->x - pt0->x;  
  26.     double dy1 = pt1->y - pt0->y;  
  27.     double dx2 = pt2->x - pt0->x;  
  28.     double dy2 = pt2->y - pt0->y;  
  29.     return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);  
  30. }  
  31.   
  32. // returns sequence of squares detected on the image.  
  33. //返回图像中的四边形序列  
  34. // the sequence is stored in the specified memory storage  
  35. //序列存储在特定的storage中  
  36. CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )  
  37. {  
  38.       
  39.     CvSeq* contours;  
  40.     int i, c, l, N = 11;  
  41.     CvSize sz = cvSize( img->width & -2, img->height & -2 );  
  42.     IplImage* timg = cvCloneImage( img ); // make a copy of input image复制输入图像  
  43.     IplImage* gray = cvCreateImage( sz, 8, 1 );   
  44.     IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );//尺度减小为1/2  
  45.     IplImage* tgray;  
  46.     CvSeq* result;  
  47.     double s, t;  
  48.     // create empty sequence that will contain points -  
  49.     // 4 points per square (the square's vertices)  
  50.     //建立一个空序列存储每个四边形的四个顶点  
  51.     CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );  
  52.       
  53.     // select the maximum ROI in the image  
  54.     // with the width and height divisible by 2  
  55.     //设定timg的ROI为最大值()  
  56.     cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));  
  57.       
  58.     // down-scale and upscale the image to filter out the noise  
  59.     //金字塔方式升和降来滤波去除噪声  
  60.     //cvPyrDown( timg, pyr, 7 );  
  61.     //cvPyrUp( pyr, timg, 7 );  
  62.     tgray = cvCreateImage( sz, 8, 1 );  
  63.       
  64.     // find squares in every color plane of the image  
  65.     //寻找每个通道的四边形  
  66.     for( c = 0; c < 3; c++ )  
  67.     {  
  68.         // extract the c-th color plane  
  69.         //提取第c个通道  
  70.         cvSetImageCOI( timg, c+1 );  
  71.         cvCopy( timg, tgray, 0 );  
  72.           
  73.         // try several threshold levels  
  74.         //尝试每个阈值等级  
  75.         for( l = 0; l < N; l++ )  
  76.         {  
  77.             // hack: use Canny instead of zero threshold level.  
  78.             // Canny helps to catch squares with gradient shading     
  79.             //Canny代替零阈值,Canny通过梯度变化程度大来寻找四边形  
  80.   
  81.             if( l == 0 )  
  82.             {  
  83.                 // apply Canny. Take the upper threshold from slider  
  84.                 // and set the lower to 0 (which forces edges merging)  
  85.                 // l=0使用Canny  
  86.                 cvCanny( tgray, gray,60, 180, 3 );  
  87.                 //   
  88.                 // dilate canny output to remove potential  
  89.                 // holes between edge segments   
  90.                 cvDilate( gray, gray, 0, 1 );  
  91.             }  
  92.             else  
  93.             {  
  94.                 // apply threshold if l!=0:  
  95.                 // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0  
  96.                 //cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );  
  97.                 cvThreshold( tgray, gray, 50, 255, CV_THRESH_BINARY );  
  98.             }  
  99.               
  100.             // find contours and store them all as a list  
  101.             cvFindContours( gray, storage, &contours, sizeof(CvContour),  
  102.                 CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );  
  103.               
  104.             // test each contour  
  105.             while( contours )  
  106.             {  
  107.                 // approximate contour with accuracy proportional  
  108.                 // to the contour perimeter  
  109.                 //用指定精度逼近多边形曲线   
  110.                 result = cvApproxPoly( contours, sizeof(CvContour), storage,  
  111.                     CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );  
  112.                 // square contours should have 4 vertices after approximation  
  113.                 // relatively large area (to filter out noisy contours)  
  114.                 // and be convex.  
  115.                 // Note: absolute value of an area is used because  
  116.                 // area may be positive or negative - in accordance with the  
  117.                 // contour orientation  
  118.                 if( result->total == 4 &&  
  119.                     fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&   //cvContourArea计算整个轮廓或部分轮廓的面积   
  120.                     cvCheckContourConvexity(result) )                   //CheckContourConvexity  
  121.                 {  
  122.                     s = 0;  
  123.                       
  124.                     for( i = 0; i < 5; i++ )  
  125.                     {  
  126.                         // find minimum angle between joint  
  127.                         // edges (maximum of cosine)  
  128.                         if( i >= 2 )  
  129.                         {  
  130.                             t = fabs(angle(  
  131.                             (CvPoint*)cvGetSeqElem( result, i ),  
  132.                             (CvPoint*)cvGetSeqElem( result, i-2 ),  
  133.                             (CvPoint*)cvGetSeqElem( result, i-1 )));  
  134.                             s = s > t ? s : t;  
  135.                         }  
  136.                     }  
  137.                       
  138.                     // if cosines of all angles are small  
  139.                     // (all angles are ~90 degree) then write quandrange  
  140.                     // vertices to resultant sequence   
  141.                     if( s < 0.3 )  
  142.                         for( i = 0; i < 4; i++ )  
  143.                             cvSeqPush( squares,  
  144.                                 (CvPoint*)cvGetSeqElem( result, i ));  
  145.                 }  
  146.                   
  147.                 // take the next contour  
  148.                 contours = contours->h_next;  
  149.             }  
  150.         }  
  151.     }  
  152.       
  153.     // release all the temporary images  
  154.     cvReleaseImage( &gray );  
  155.     cvReleaseImage( &pyr );  
  156.     cvReleaseImage( &tgray );  
  157.     cvReleaseImage( &timg );  
  158.       
  159.     return squares;  
  160. }  
  161.   
  162.   
  163. // the function draws all the squares in the image  
  164. void drawSquares( IplImage* img, CvSeq* squares )  
  165. {  
  166.     CvSeqReader reader;  
  167.     IplImage* cpy = cvCloneImage( img );  
  168.     int i;  
  169.       
  170.     // initialize reader of the sequence  
  171.     cvStartReadSeq( squares, &reader, 0 );  
  172.       
  173.     // read 4 sequence elements at a time (all vertices of a square)  
  174.     for( i = 0; i < squares->total; i += 4 )  
  175.     {  
  176.         CvPoint* rect = pt;  
  177.         int count = 4;  
  178.           
  179.         // read 4 vertices  
  180.         memcpy( pt, reader.ptr, squares->elem_size );  
  181.         CV_NEXT_SEQ_ELEM( squares->elem_size, reader );  
  182.         memcpy( pt + 1, reader.ptr, squares->elem_size );  
  183.         CV_NEXT_SEQ_ELEM( squares->elem_size, reader );  
  184.         memcpy( pt + 2, reader.ptr, squares->elem_size );  
  185.         CV_NEXT_SEQ_ELEM( squares->elem_size, reader );  
  186.         memcpy( pt + 3, reader.ptr, squares->elem_size );  
  187.         CV_NEXT_SEQ_ELEM( squares->elem_size, reader );  
  188.           
  189.         // draw the square as a closed polyline   
  190.         cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );  
  191.     }  
  192.       
  193.     // show the resultant image  
  194.     cvShowImage( wndname, cpy );  
  195.     cvReleaseImage( &cpy );  
  196. }  
  197.   
  198.   
  199. void on_trackbar( int a )  
  200. {  
  201.     if( img )  
  202.         drawSquares( img, findSquares4( img, storage ) );  
  203. }  
  204. //char* names[] = { "D:/image/car/00.jpg", "D:/image/car/01.jpg", "D:/image/car/02.jpg",  
  205. //                  "D:/image/car/03.jpg", "D:/image/car/04.jpg", "D:/image/car/05.jpg", 0 };  
  206. //char* names[] = { "D:/image/car/car00.jpg", "D:/image/car/car01.jpg", "D:/image/car/car02.jpg",  
  207. //                  "D:/image/car/car03.jpg", "D:/image/car/car04.jpg", "D:/image/car/car05.jpg", 0 };  
  208. //char* names[] = { "D:/image/car/00sobel.jpg", "D:/image/car/01sobel.jpg", "D:/image/car/02sobel.jpg",  
  209. //                "D:/image/car/03sobel.jpg", "D:/image/car/04sobel.jpg", "D:/image/car/05sobel.jpg", 0 };  
  210. char* names[] = { "D:/image/car/06sobel_normal.jpg",   
  211.                   "D:/image/car/0sobel_normal.jpg",  
  212.                   "D:/image/car/08sobel_normal.jpg",  
  213.                   "D:/image/car/09sobel_normal.jpg",   
  214.                   "D:/image/car/10sobel_normal.jpg",  
  215.                   "D:/image/car/11sobel_normal.jpg",  
  216.                   "D:/image/car/12sobel_normal.jpg",   
  217.                   "D:/image/car/13sobel_normal.jpg",  
  218.                   "D:/image/car/14sobel_normal.jpg",  
  219.                   "D:/image/car/15sobel_normal.jpg",   
  220.                   "D:/image/car/16sobel_normal.jpg",  
  221.                   "D:/image/car/17sobel_normal.jpg",  
  222.                   "D:/image/car/18sobel_normal.jpg",   
  223.                   "D:/image/car/19sobel_normal.jpg",  
  224.                   "D:/image/car/20sobel_normal.jpg",  
  225.                   "D:/image/car/21sobel_normal.jpg",   
  226.                   "D:/image/car/22sobel_normal.jpg",  
  227.                   "D:/image/car/23sobel_normal.jpg",  
  228.                   "D:/image/car/00sobel_normal.jpg",   
  229.                   "D:/image/car/01sobel_normal.jpg",  
  230.                   "D:/image/car/02sobel_normal.jpg",  
  231.                   "D:/image/car/03sobel_normal.jpg",   
  232.                   "D:/image/car/04sobel_normal.jpg",  
  233.                   "D:/image/car/05sobel_normal.jpg",  
  234.                   0 };  
  235. int main(int argc, char** argv)  
  236. {  
  237.     int i, c;  
  238.     // create memory storage that will contain all the dynamic data  
  239.     storage = cvCreateMemStorage(0);  
  240.   
  241.     for( i = 0; names[i] != 0; i++ )  
  242.     {  
  243.         // load i-th image  
  244.         img0 = cvLoadImage( names[i], 1 );  
  245.         if( !img0 )  
  246.         {  
  247.             printf("Couldn't load %s/n", names[i] );  
  248.             continue;  
  249.         }  
  250.         img = cvCloneImage( img0 );  
  251.           
  252.         // create window and a trackbar (slider) with parent "image" and set callback  
  253.         // (the slider regulates upper threshold, passed to Canny edge detector)   
  254.         cvNamedWindow( wndname,0 );  
  255.         cvCreateTrackbar( "canny thresh", wndname, &thresh, 1000, on_trackbar );  
  256.           
  257.         // force the image processing  
  258.         on_trackbar(0);  
  259.         // wait for key.  
  260.         // Also the function cvWaitKey takes care of event processing  
  261.         c = cvWaitKey(0);  
  262.         // release both images  
  263.         cvReleaseImage( &img );  
  264.         cvReleaseImage( &img0 );  
  265.         // clear memory storage - reset free space position  
  266.         cvClearMemStorage( storage );  
  267.         if( c == 27 )  
  268.             break;  
  269.     }  
  270.       
  271.     cvDestroyWindow( wndname );  
  272.       
  273.     return 0;  
  274. }  
  275.   
  276. #ifdef _EiC  
  277. main(1,"squares.c");  
  278. #endif  

5.Sobel(横向求导,保留纵向纹理)+(颜色反向)+cvMorphologyEx(Close操作,IplConvKernel*(3x1)横向闭运算)+FindContours+cvBoundingRect+cvRectangle(满足一定条件)正确率65% 主要由于没有加入仿射变换或变形

[cpp]  view plain copy
  1. #include "cv.h"  
  2. #include "highgui.h"  
  3. #include "cxcore.h"  
  4. #include <stdio.h>  
  5. #include <math.h>  
  6. #include <string.h>  
  7. #include <string>  
  8. using namespace std;  
  9.   
  10.   
  11. CvPoint pt[4];  
  12. IplImage* img = 0;  
  13. IplImage* img0 = 0;  
  14. const char* wndname = "Demo";  
  15.   
  16. char* names[] = { "D:/image/car/06.jpg",   
  17.                   "D:/image/car/07.jpg",  
  18.                   "D:/image/car/08.jpg",  
  19.                   "D:/image/car/09.jpg",   
  20.                   "D:/image/car/10.jpg",  
  21.                   "D:/image/car/11.jpg",  
  22.                   "D:/image/car/12.jpg",   
  23.                   "D:/image/car/13.jpg",  
  24.                   "D:/image/car/14.jpg",  
  25.                   "D:/image/car/15.jpg",   
  26.                   "D:/image/car/16.jpg",  
  27.                   "D:/image/car/17.jpg",  
  28.                   "D:/image/car/18.jpg",   
  29.                   "D:/image/car/19.jpg",  
  30.                   "D:/image/car/20.jpg",  
  31.                   "D:/image/car/21.jpg",   
  32.                   "D:/image/car/22.jpg",  
  33.                   "D:/image/car/23.jpg",  
  34.                   "D:/image/car/00.jpg",   
  35.                   "D:/image/car/01.jpg",  
  36.                   "D:/image/car/02.jpg",  
  37.                   "D:/image/car/03.jpg",   
  38.                   "D:/image/car/04.jpg",  
  39.                   "D:/image/car/05.jpg",  
  40.                   0 };  
  41.   
  42. void FindContours(IplImage* src);  
  43.   
  44. int main(int argc, char** argv)  
  45. {  
  46.     int i;  
  47.   
  48.     for( i = 0; names[i] != 0; i++ )  
  49.     {  
  50.         // load i-th image  
  51.         img0 = cvLoadImage( names[i], 0 );  
  52.         if( !img0 )  
  53.         {  
  54.             printf("Couldn't load %s/n", names[i] );  
  55.             continue;  
  56.         }  
  57.         img=cvCreateImage(cvSize(400,300),8,1);  
  58.         IplImage* pyr=cvCreateImage(cvSize(img->width/2,img->height/2),IPL_DEPTH_8U,1);  
  59.         cvResize(img0,img);  
  60.         cvNamedWindow("input",1);  
  61.         cvShowImage("input",img);  
  62.         cvSmooth(img,img,CV_MEDIAN);  
  63.         //cvPyrDown( img, pyr, 7 );  
  64.         //cvPyrUp( pyr, img, 7 );  
  65.   
  66.   
  67.         //img = cvCloneImage( img0 );  
  68.         IplImage* imgS=cvCreateImage(cvGetSize(img),IPL_DEPTH_16S,1);  
  69.         IplImage* imgTh=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
  70.         IplImage* temp=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
  71.           
  72.   
  73.         cvSobel(img,imgS,2,0,3);  
  74.         cvNormalize(imgS,imgTh,255,0,CV_MINMAX);  
  75.   
  76.         cvNamedWindow( wndname,1);  
  77.   
  78.         cvNamedWindow("Sobel",1);  
  79.         cvShowImage("Sobel",imgTh);  
  80.   
  81.   
  82.         //cvAdaptiveThreshold(imgTh,imgTh,255,0,0,5,5);  
  83.         cvThreshold( imgTh, imgTh, 100, 255, CV_THRESH_BINARY );  
  84.           
  85.         for (int k=0; k<img->height; k++)  
  86.   
  87.             for(int j=0; j<img->width; j++)  
  88.   
  89.             {  
  90.   
  91.                 imgTh->imageData[k*img->widthStep+j] = 255 - imgTh->imageData[k*img->widthStep+j];  
  92.   
  93.             }  
  94.               
  95.         cvNamedWindow("Th",1);  
  96.         cvShowImage("Th",imgTh);  
  97.         IplConvKernel* K=cvCreateStructuringElementEx(3,1,0,0,CV_SHAPE_RECT);  
  98.         IplConvKernel* K1=cvCreateStructuringElementEx(3,3,0,0,CV_SHAPE_RECT);  
  99.           
  100.         cvMorphologyEx(imgTh,imgTh,temp,K,CV_MOP_CLOSE,10);  
  101.         cvMorphologyEx(imgTh,imgTh,temp,K1,CV_MOP_OPEN,1);  
  102.         //cvDilate(imgTh,imgTh,K,15);  
  103.         //cvErode(imgTh,imgTh,K,15);  
  104.         cvShowImage(wndname,imgTh);  
  105.         string a=names[i];  
  106.         a.insert(15,"sobel_normal");  
  107.         //cvSaveImage(a.c_str(),imgTh);  
  108.         //cvWaitKey(0);  
  109.         FindContours(imgTh);  
  110.   
  111.         //cvShowImage(wndname,imgTh);  
  112.           
  113.           
  114.   
  115.           
  116.     }  
  117. }  
  118.   
  119. void FindContours(IplImage* src)  
  120. {  
  121.     CvMemStorage* storage = cvCreateMemStorage(0);  
  122.     IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3);  
  123.     cvCvtColor(src,dst,CV_GRAY2BGR);  
  124.     CvScalar color = CV_RGB( 255, 0, 0);  
  125.     CvSeq* contours=0;  
  126.       
  127.      //建立一个空序列存储每个四边形的四个顶点  
  128.    // CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );  
  129.   
  130.     //cvFindContours( src, storage, &contours, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );//外界边界h_next 和 孔用v_next连接  
  131.     cvFindContours( src, storage, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );  
  132.      for( ; contours != 0; contours = contours->h_next)  
  133.             {  
  134.                 //使用边界框的方式  
  135.                 CvRect aRect = cvBoundingRect( contours, 1 );  
  136.                 int tmparea=aRect.height*aRect.height;  
  137.                 if (((double)aRect.width/(double)aRect.height>3)  
  138.                 && ((double)aRect.width/(double)aRect.height<6)&& tmparea>=200&&tmparea<=2500)  
  139.             {  
  140.                 cvRectangle(dst,cvPoint(aRect.x,aRect.y),cvPoint(aRect.x+aRect.width ,aRect.y+aRect.height),color,2);  
  141.                 //cvDrawContours( dst, contours, color, color, -1, 1, 8 );  
  142.             }  
  143.         }  
  144.      cvNamedWindow("contour",1);  
  145.      cvShowImage("contour",dst);  
  146.      cvWaitKey(0);  
  147.                 //多边形曲线逼近方法  
  148.                 /* 
  149.                 //用指定精度逼近多边形曲线  
  150.                 result = cvApproxPoly( contours, sizeof(CvContour), storage, 
  151.                     CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); 
  152.  
  153.                 if( result->total == 4 && 
  154.                     fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&   //cvContourArea计算整个轮廓或部分轮廓的面积  
  155.                     cvCheckContourConvexity(result) )                   //CheckContourConvexity 
  156.                 { 
  157.                 */  
  158.        
  159. }  

你可能感兴趣的:(OpenCV图像处理车牌检测与定位应用)