学习OpenCV——车牌检测(定位)

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

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

转载自:http://blog.csdn.net/sangni007/article/details/7444470

  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. }  
#include "highgui.h"
#include "cv.h"
#include <stdio.h>   
#include <math.h>  
#include <string>
#include<iostream>
using namespace std;

CvPoint Point;
IplImage* img=0;
// skin region location using rgb limitation
void SkinRGB(IplImage* rgb,IplImage* _dst)
{
	assert(rgb->nChannels==3&& _dst->nChannels==3);

	static const int R=2;
	static const int G=1;
	static const int B=0;

	IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);
	cvZero(dst);

	for (int h=0;h<rgb->height;h++) {
		unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;
		unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;
		for (int w=0;w<rgb->width;w++) {
			if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&
				prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15/*&&
				!(prgb[R]>170&&prgb[G]>170&&prgb[B]>170)*/)||//uniform illumination 
				(prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&
				abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B])//lateral illumination
				) {
					memcpy(pdst,prgb,3);
			}			
			prgb+=3;
			pdst+=3;
		}
	}
	cvCopyImage(dst,_dst);
	cvReleaseImage(&dst);
}
// skin detection in rg space
void cvSkinRG(IplImage* rgb,IplImage* gray)
{
	assert(rgb->nChannels==3&&gray->nChannels==1);
	
	const int R=2;
	const int G=1;
	const int B=0;

	double Aup=-1.8423;
	double Bup=1.5294;
	double Cup=0.0422;
	double Adown=-0.7279;
	double Bdown=0.6066;
	double Cdown=0.1766;
	for (int h=0;h<rgb->height;h++) {
		unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;
		unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;
		for (int w=0;w<rgb->width;w++) 
		{
			int s=pRGB[R]+pRGB[G]+pRGB[B];
			double r=(double)pRGB[R]/s;
			double g=(double)pRGB[G]/s;
			double Gup=Aup*r*r+Bup*r+Cup;
			double Gdown=Adown*r*r+Bdown*r+Cdown;
			double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);
			if (g<Gup && g>Gdown && Wr>0.004)
			{
				*pGray=255;
			}
			else
			{ 
				*pGray=0;
			}
			pGray++;
			pRGB+=3;
		}
	}

}
// implementation of otsu algorithm
// author: onezeros#yahoo.cn
// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB
void cvThresholdOtsu(IplImage* src, IplImage* dst)
{
	int height=src->height;
	int width=src->width;

	//histogram
	float histogram[256]={0};
	for(int i=0;i<height;i++) {
		unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;
		for(int j=0;j<width;j++) {
			histogram[*p++]++;
		}
	}
	//normalize histogram
	int size=height*width;
	for(int i=0;i<256;i++) {
		histogram[i]=histogram[i]/size;
	}

	//average pixel value
	float avgValue=0;
	for(int i=0;i<256;i++) {
		avgValue+=i*histogram[i];
	}

	int threshold;	
	float maxVariance=0;
	float w=0,u=0;
	for(int i=0;i<256;i++) {
		w+=histogram[i];
		u+=i*histogram[i];

		float t=avgValue*w-u;
		float variance=t*t/(w*(1-w));
		if(variance>maxVariance) {
			maxVariance=variance;
			threshold=i;
		}
	}

	cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);
}

void cvSkinOtsu(IplImage* src, IplImage* dst)
{
	assert(dst->nChannels==1&& src->nChannels==3);

	IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);
	IplImage* cr=cvCreateImage(cvGetSize(src),8,1);
	cvCvtColor(src,ycrcb,CV_BGR2YCrCb);
	cvSplit(ycrcb,0,cr,0,0);

	cvThresholdOtsu(cr,cr);
	cvCopyImage(cr,dst);
	cvReleaseImage(&cr);
	cvReleaseImage(&ycrcb);
}

void cvSkinYUV(IplImage* src,IplImage* dst)
{
	IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);
	//IplImage* cr=cvCreateImage(cvGetSize(src),8,1);
	//IplImage* cb=cvCreateImage(cvGetSize(src),8,1);
	cvCvtColor(src,ycrcb,CV_BGR2YCrCb);
	//cvSplit(ycrcb,0,cr,cb,0);

	static const int Cb=2;
	static const int Cr=1;
	static const int Y=0;

	//IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);
	cvZero(dst);

	for (int h=0;h<src->height;h++) {
		unsigned char* pycrcb=(unsigned char*)ycrcb->imageData+h*ycrcb->widthStep;
		unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;
		unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;
		for (int w=0;w<src->width;w++) {
			if ((pycrcb[Cr]<=126||pycrcb[Cr]>=130)&&(pycrcb[Cb]<=126||pycrcb[Cb]>=130))
			{
					memcpy(pdst,psrc,3);
			}
			pycrcb+=3;
			psrc+=3;
			pdst+=3;
		}
	}
	//cvCopyImage(dst,_dst);
	//cvReleaseImage(&dst);
}

void cvSkinHSV(IplImage* src,IplImage* dst)
{
	IplImage* hsv=cvCreateImage(cvGetSize(src),8,3);
	//IplImage* cr=cvCreateImage(cvGetSize(src),8,1);
	//IplImage* cb=cvCreateImage(cvGetSize(src),8,1);
	cvCvtColor(src,hsv,CV_BGR2HSV);
	//cvSplit(ycrcb,0,cr,cb,0);

	static const int V=2;
	static const int S=1;
	static const int H=0;

	//IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);
	cvZero(dst);

	for (int h=0;h<src->height;h++) {
		unsigned char* phsv=(unsigned char*)hsv->imageData+h*hsv->widthStep;
		unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;
		unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;
		for (int w=0;w<src->width;w++) {
			if (phsv[H]>=90&&phsv[H]<=135)
			{
					memcpy(pdst,psrc,3);
			}
			phsv+=3;
			psrc+=3;
			pdst+=3;
		}
	}
	//cvCopyImage(dst,_dst);
	//cvReleaseImage(&dst);
}

void on_mouse(int event,int x,int y,int flags,void* param )  
{  
	 switch(event)  
     {  
	 case CV_EVENT_LBUTTONUP:  
         {  
             Point=cvPoint(x,y);  
         }  
			cvCircle(img,Point,1,CV_RGB(255,0,0),1);
			CvScalar HSV=cvGet2D(img,x,y);
			cout<<"H:"<<HSV.val[0]<<"\t S:"<<HSV.val[1]<<"\t V:"<<HSV.val[2]<<endl; 
         break;  
     }  
  
//printf("( %d, %d) ",x,y);  
//printf("The Event is : %d ",event);  
//printf("The flags is : %d ",flags);  
//printf("The param is : %d\n",param);  
}
int main()
{   
	
    IplImage* img0= cvLoadImage("D:/image/car/00.jpg"); //随便放一张jpg图片在D盘或另行设置目录
	img=cvCreateImage(cvSize(400,300),8,3);
	cvResize(img0,img);
	IplImage* dstRGB=cvCreateImage(cvGetSize(img),8,3);
	IplImage* dstRG=cvCreateImage(cvGetSize(img),8,1);
	IplImage* dst_crotsu=cvCreateImage(cvGetSize(img),8,1);
	IplImage* dst_YUV=cvCreateImage(cvGetSize(img),8,3);
	IplImage* dst_HSV=cvCreateImage(cvGetSize(img),8,3);


    cvNamedWindow("inputimage", CV_WINDOW_AUTOSIZE);
    cvShowImage("inputimage", img);
    cvWaitKey(0);
	/*
	SkinRGB(img,dstRGB);
	cvNamedWindow("outputimage1", CV_WINDOW_AUTOSIZE);
    cvShowImage("outputimage1", dstRGB);
    cvWaitKey(0);
	cvSkinRG(img,dstRG);
	cvNamedWindow("outputimage2", CV_WINDOW_AUTOSIZE);
    cvShowImage("outputimage2", dstRG);
	cvWaitKey(0);
	cvSkinOtsu(img,dst_crotsu);
	cvNamedWindow("outputimage3", CV_WINDOW_AUTOSIZE);
    cvShowImage("outputimage3", dst_crotsu);
	cvWaitKey(0);
	
	cvSkinYUV(img,dst_YUV);
	cvNamedWindow("outputimage4", CV_WINDOW_AUTOSIZE);
    cvShowImage("outputimage4", dst_YUV);
	//cvSaveImage("D:/skin04.jpg",dst_YUV);
	cvWaitKey(0);
	*/
	cvSkinHSV(img,dst_HSV);
	cvNamedWindow("outputimage5", CV_WINDOW_AUTOSIZE);
    cvShowImage("outputimage5", dst_HSV);
	cvSaveImage("D:/image/car/car00.jpg",dst_HSV);
	cvWaitKey(0);
	
    return 0;
}


 

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

 

  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. }  
#include <cv.h>
#include <highgui.h>
#include <math.h>
 
int main(int argc, char** argv)
{
    const char* filename = argc >= 2 ? argv[1] : "D:/image/car/car04.jpg";
    IplImage* src = cvLoadImage( filename, 0 );
	cvDilate(src,src);
    IplImage* dst;
    IplImage* color_dst;
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* lines = 0;
    int i;
 
    if( !src )
        return -1;
 
    dst = cvCreateImage( cvGetSize(src), 8, 1 );
    color_dst = cvCreateImage( cvGetSize(src), 8, 3 );
 
    cvCanny( src, dst, 50, 150, 3 );
    cvCvtColor( dst, color_dst, CV_GRAY2BGR );
	
#if 0
    lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100, 0, 0 );
 
    for( i = 0; i < MIN(lines->total,100); i++ )
    {
        float* line = (float*)cvGetSeqElem(lines,i);
        float rho = line[0];
        float theta = line[1];
        CvPoint pt1, pt2;
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;
        pt1.x = cvRound(x0 + 1000*(-b));
        pt1.y = cvRound(y0 + 1000*(a));
        pt2.x = cvRound(x0 - 1000*(-b));
        pt2.y = cvRound(y0 - 1000*(a));
        cvLine( color_dst, pt1, pt2, CV_RGB(255,0,0), 3, CV_AA, 0 );
    }
#else
	
    lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 5, 3 );
    for( i = 0; i < lines->total; i++ )
    {
        CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
        cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );
    }
//#endif
    cvNamedWindow( "Source", 1 );
    cvShowImage( "Source", src );
 
    cvNamedWindow( "Hough", 1 );
    cvShowImage( "Hough", color_dst );
 
    cvWaitKey(0);
 
    return 0;
}


 

 

3.Coutour检测;效果勉强。

 

  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. }  
#include "cv.h"
#include "highgui.h"
#include <cxcore.h>
#include <stdio.h>
 
int BinarizeImageByOTSU (IplImage * src)
{ 
	assert(src != NULL);
 
	//get the ROI
	CvRect rect = cvGetImageROI(src);
 
	//information of the source image
	int x = rect.x;
	int y = rect.y;
	int width = rect.width; 
	int height = rect.height;
	int ws = src->widthStep;
 
	int thresholdValue=1;//阈值
	int ihist [256] ; // 图像直方图, 256个点
	int i, j, k,n, n1, n2, Color=0;
	double m1, m2, sum, csum, fmax, sb;
	memset (ihist, 0, sizeof (ihist)) ; // 对直方图置 零...
 
	for (i=y;i< y+height;i++) // 生成直方图
	{ 
		int mul =  i*ws;
		for (j=x;j<x+width;j++)
		{ 
			//Color=Point (i,j) ;
			Color = (int)(unsigned char)*(src->imageData + mul+ j);
			ihist [Color] +=1;
		}
	}
	sum=csum=0.0;
	n=0;
	for (k = 0; k <= 255; k++)
	{ 
		sum+= (double) k* (double) ihist [k] ; // x*f (x) 质量矩
		n +=ihist [k]; //f (x) 质量
	}
	// do the otsu global thresholding method
	fmax = - 1.0;
	n1 = 0;
	for (k=0;k<255;k++) 
	{
		n1+=ihist [k] ;
		if (! n1)
		{ 
			continue; 
		}
		n2=n- n1;
		if (n2==0) 
		{
			break;
		}
		csum+= (double) k*ihist [k] ;
		m1=csum/ n1;
		m2= (sum- csum) /n2;
		sb = ( double) n1* ( double) n2* ( m1 - m2) * (m1- m2) ;
 
		if (sb>fmax) 
		{
			fmax=sb;
			thresholdValue=k;
		}
	}
 
	//binarize the image 
	cvThreshold( src, src ,thresholdValue, 255, CV_THRESH_BINARY ); 
	return 0;
} 
 
int main( int argc, char* argv[])
{
	IplImage* src;
	if((src=cvLoadImage("D:/image/car/05sobel.jpg", 0)))//载入图像
	{
		//为轮廓显示图像申请空间,3通道图像,以便用彩色显示
		IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3);
		//创建内存块,将该块设置成默认值,当前默认大小为64k
		CvMemStorage* storage = cvCreateMemStorage(0);
		//可动态增长元素序列
		CvSeq* contour = 0;
		//对图像进行自适二值化
		BinarizeImageByOTSU(src);
		//图像膨胀
		cvDilate(src,src);
		//图像腐蚀
		cvErode(src,src);
		//显示源图像的二值图
		cvNamedWindow( "Source", 1 );
		cvShowImage( "Source", src );
		//在二值图像中寻找轮廓
		cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
		cvZero( dst );//清空数组
		cvCvtColor(src,dst,CV_GRAY2BGR);
		//目标轮廓最小下限
		int mix_area = 2500;
		//目标轮廓最大上限
		int max_area = 3500;
		//可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器
		CvScalar color = CV_RGB( 255, 0, 0);
		//在图像中绘制外部和内部的轮廓
		for( ; contour != 0; contour = contour->h_next)
		{
			//取得轮廓的最小矩形
			CvRect aRect = cvBoundingRect( contour, 1 );
			//取得矩形的面积
			int tmparea=aRect.height*aRect.height;
			//用车牌的形态做判断
			if (((double)aRect.width/(double)aRect.height>3)
				&& ((double)aRect.width/(double)aRect.height<6))
			{
				cvRectangle(dst,cvPoint(aRect.x,aRect.y),cvPoint(aRect.x+aRect.width ,aRect.y+aRect.height),color,2);
				//cvDrawContours( dst, contour, color, color, -1, 1, 8 );
			}
		}
 
		cvNamedWindow( "Components", 1 );
		cvShowImage( "Components", dst );
		cvWaitKey(0);	
		cvDestroyWindow("Components");
		cvReleaseImage(&dst);
		cvDestroyWindow("Source");
		cvReleaseImage(&src);
 
		return 0;
	}	
	return 1;
}


 

 

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

 

  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  
#ifdef _CH_
#pragma package <opencv>
#endif

#ifndef _EiC
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#endif

int thresh = 50;
IplImage* img = 0;
IplImage* img0 = 0;
CvMemStorage* storage =  cvCreateMemStorage(0);
CvPoint pt[4];
const char* wndname = "Square Detection Demo";

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2 
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
    double dx1 = pt1->x - pt0->x;
    double dy1 = pt1->y - pt0->y;
    double dx2 = pt2->x - pt0->x;
    double dy2 = pt2->y - pt0->y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// returns sequence of squares detected on the image.
//返回图像中的四边形序列
// the sequence is stored in the specified memory storage
//序列存储在特定的storage中
CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
{
	
    CvSeq* contours;
    int i, c, l, N = 11;
    CvSize sz = cvSize( img->width & -2, img->height & -2 );
    IplImage* timg = cvCloneImage( img ); // make a copy of input image复制输入图像
    IplImage* gray = cvCreateImage( sz, 8, 1 ); 
    IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );//尺度减小为1/2
    IplImage* tgray;
    CvSeq* result;
    double s, t;
    // create empty sequence that will contain points -
    // 4 points per square (the square's vertices)
	//建立一个空序列存储每个四边形的四个顶点
    CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
    
    // select the maximum ROI in the image
    // with the width and height divisible by 2
	//设定timg的ROI为最大值()
    cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
    
    // down-scale and upscale the image to filter out the noise
	//金字塔方式升和降来滤波去除噪声
    //cvPyrDown( timg, pyr, 7 );
    //cvPyrUp( pyr, timg, 7 );
    tgray = cvCreateImage( sz, 8, 1 );
    
    // find squares in every color plane of the image
	//寻找每个通道的四边形
    for( c = 0; c < 3; c++ )
    {
        // extract the c-th color plane
		//提取第c个通道
        cvSetImageCOI( timg, c+1 );
        cvCopy( timg, tgray, 0 );
        
        // try several threshold levels
		//尝试每个阈值等级
        for( l = 0; l < N; l++ )
        {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading   
            //Canny代替零阈值,Canny通过梯度变化程度大来寻找四边形

			if( l == 0 )
            {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
				// l=0使用Canny
                cvCanny( tgray, gray,60, 180, 3 );
				// 
                // dilate canny output to remove potential
                // holes between edge segments 
                cvDilate( gray, gray, 0, 1 );
            }
            else
            {
                // apply threshold if l!=0:
                // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                //cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
				cvThreshold( tgray, gray, 50, 255, CV_THRESH_BINARY );
            }
            
            // find contours and store them all as a list
            cvFindContours( gray, storage, &contours, sizeof(CvContour),
                CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
            
            // test each contour
            while( contours )
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
				//用指定精度逼近多边形曲线 
                result = cvApproxPoly( contours, sizeof(CvContour), storage,
                    CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if( result->total == 4 &&
                    fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&	//cvContourArea计算整个轮廓或部分轮廓的面积 
                    cvCheckContourConvexity(result) )					//CheckContourConvexity
                {
                    s = 0;
                    
                    for( i = 0; i < 5; i++ )
                    {
                        // find minimum angle between joint
                        // edges (maximum of cosine)
                        if( i >= 2 )
                        {
                            t = fabs(angle(
                            (CvPoint*)cvGetSeqElem( result, i ),
                            (CvPoint*)cvGetSeqElem( result, i-2 ),
                            (CvPoint*)cvGetSeqElem( result, i-1 )));
                            s = s > t ? s : t;
                        }
                    }
                    
                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence 
                    if( s < 0.3 )
                        for( i = 0; i < 4; i++ )
                            cvSeqPush( squares,
                                (CvPoint*)cvGetSeqElem( result, i ));
                }
                
                // take the next contour
                contours = contours->h_next;
            }
        }
    }
    
    // release all the temporary images
    cvReleaseImage( &gray );
    cvReleaseImage( &pyr );
    cvReleaseImage( &tgray );
    cvReleaseImage( &timg );
    
    return squares;
}


// the function draws all the squares in the image
void drawSquares( IplImage* img, CvSeq* squares )
{
    CvSeqReader reader;
    IplImage* cpy = cvCloneImage( img );
    int i;
    
    // initialize reader of the sequence
    cvStartReadSeq( squares, &reader, 0 );
    
    // read 4 sequence elements at a time (all vertices of a square)
    for( i = 0; i < squares->total; i += 4 )
    {
        CvPoint* rect = pt;
        int count = 4;
        
        // read 4 vertices
        memcpy( pt, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 1, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 2, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 3, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        
        // draw the square as a closed polyline 
        cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
    }
    
    // show the resultant image
    cvShowImage( wndname, cpy );
    cvReleaseImage( &cpy );
}


void on_trackbar( int a )
{
    if( img )
        drawSquares( img, findSquares4( img, storage ) );
}
//char* names[] = { "D:/image/car/00.jpg", "D:/image/car/01.jpg", "D:/image/car/02.jpg",
//                  "D:/image/car/03.jpg", "D:/image/car/04.jpg", "D:/image/car/05.jpg", 0 };
//char* names[] = { "D:/image/car/car00.jpg", "D:/image/car/car01.jpg", "D:/image/car/car02.jpg",
//                  "D:/image/car/car03.jpg", "D:/image/car/car04.jpg", "D:/image/car/car05.jpg", 0 };
//char* names[] = { "D:/image/car/00sobel.jpg", "D:/image/car/01sobel.jpg", "D:/image/car/02sobel.jpg",
//                "D:/image/car/03sobel.jpg", "D:/image/car/04sobel.jpg", "D:/image/car/05sobel.jpg", 0 };
char* names[] = { "D:/image/car/06sobel_normal.jpg", 
				  "D:/image/car/0sobel_normal.jpg",
				  "D:/image/car/08sobel_normal.jpg",
                  "D:/image/car/09sobel_normal.jpg", 
				  "D:/image/car/10sobel_normal.jpg",
				  "D:/image/car/11sobel_normal.jpg",
				  "D:/image/car/12sobel_normal.jpg", 
				  "D:/image/car/13sobel_normal.jpg",
				  "D:/image/car/14sobel_normal.jpg",
                  "D:/image/car/15sobel_normal.jpg", 
				  "D:/image/car/16sobel_normal.jpg",
				  "D:/image/car/17sobel_normal.jpg",
				  "D:/image/car/18sobel_normal.jpg", 
				  "D:/image/car/19sobel_normal.jpg",
				  "D:/image/car/20sobel_normal.jpg",
                  "D:/image/car/21sobel_normal.jpg", 
				  "D:/image/car/22sobel_normal.jpg",
				  "D:/image/car/23sobel_normal.jpg",
				  "D:/image/car/00sobel_normal.jpg", 
				  "D:/image/car/01sobel_normal.jpg",
				  "D:/image/car/02sobel_normal.jpg",
                  "D:/image/car/03sobel_normal.jpg", 
				  "D:/image/car/04sobel_normal.jpg",
				  "D:/image/car/05sobel_normal.jpg",
				  0 };
int main(int argc, char** argv)
{
    int i, c;
    // create memory storage that will contain all the dynamic data
    storage = cvCreateMemStorage(0);

    for( i = 0; names[i] != 0; i++ )
    {
        // load i-th image
        img0 = cvLoadImage( names[i], 1 );
        if( !img0 )
        {
            printf("Couldn't load %s/n", names[i] );
            continue;
        }
        img = cvCloneImage( img0 );
        
        // create window and a trackbar (slider) with parent "image" and set callback
        // (the slider regulates upper threshold, passed to Canny edge detector) 
        cvNamedWindow( wndname,0 );
        cvCreateTrackbar( "canny thresh", wndname, &thresh, 1000, on_trackbar );
        
        // force the image processing
        on_trackbar(0);
        // wait for key.
        // Also the function cvWaitKey takes care of event processing
        c = cvWaitKey(0);
        // release both images
        cvReleaseImage( &img );
        cvReleaseImage( &img0 );
        // clear memory storage - reset free space position
        cvClearMemStorage( storage );
        if( c == 27 )
            break;
    }
    
    cvDestroyWindow( wndname );
    
    return 0;
}

#ifdef _EiC
main(1,"squares.c");
#endif


 

 

5.Sobel(横向求导,保留纵向纹理)+(颜色反向)+cvMorphologyEx(Close操作,IplConvKernel*(3x1)横向闭运算)+FindContours+cvBoundingRect+cvRectangle(满足一定条件)

正确率65% 主要由于没有加入仿射变换或变形

 

  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. }  
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值