基于OpenCV的车牌定位方法

    最近一直在研究车牌识别,看到一篇论文《基于opencv的车牌定位方法》,正好前段时间学习了opencv,于是将文中思想学成代码,得以实现。需要解释的是:主要思想不是本人的,我的工作只是翻译成了代码。
论文可到http://www.cqvip.com/QK/95033X/201308/46713489.html 下载
编译环境:opencv2.4.6+vs2012
简介:
根据车牌的颜色特征,将原图像分别在HSV颜色空间和RGB颜色空间下处理得到两幅二值图像,基于HSV空间下二值图像的特点根据水平投影和垂直投影将车牌定位出来。该方法有一定的局限性,代码适用于蓝底白字的车牌。
代码如下:也可到http://download.csdn.net/detail/yuansanwan123/6988317下载

#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
#include 
int myOtsu(const IplImage *frame) //大津法求阈值   
{ 
#define GrayScale 256   //frame灰度级   
    int width = frame->width;  
    int height = frame->height;  
    int pixelCount[GrayScale]={0};  
    float pixelPro[GrayScale]={0};  
    int i, j, pixelSum = width * height, threshold = 0;  
    uchar* data = (uchar*)frame->imageData;  
  
    //统计每个灰度级中像素的个数   
    for(i = 0; i < height; i++)  
    {  
        for(j = 0;j < width;j++)  
        {  
            pixelCount[(int)data[i * width + j]]++;  
        }  
    }  
  
    //计算每个灰度级的像素数目占整幅图像的比例   
    for(i = 0; i < GrayScale; i++)  
    {  
        pixelPro[i] = (float)pixelCount[i] / pixelSum;  
    }  
  
    //遍历灰度级[0,255],寻找合适的threshold   
    float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;  
    for(i = 0; i < GrayScale; i++)  
    {  
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;  
        for(j = 0; j < GrayScale; j++)  
        {  
            if(j <= i)   //背景部分   
            {  
                w0 += pixelPro[j];  
                u0tmp += j * pixelPro[j];  
            }  
            else   //前景部分   
            {  
                w1 += pixelPro[j];  
                u1tmp += j * pixelPro[j];  
            }  
        }  
        u0 = u0tmp / w0;  
        u1 = u1tmp / w1;  
        deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) ;  
        if(deltaTmp > deltaMax)  
        {  
            deltaMax = deltaTmp;  
            threshold = i;  
        }  
    }  
    return threshold;  
}
int main()
{
	IplImage *imgSrc=cvLoadImage("F:\\carlicense\\2.jpg");
	IplImage *imgH,*imgS,*imgV,*imgHSV,*imgGray;
	imgHSV=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,3);
	imgH=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	imgS=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	imgV=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	cvCvtColor(imgSrc,imgHSV,CV_BGR2HSV);
	cvSplit(imgHSV,imgH,imgS,imgV,0);
	cvInRangeS(imgH,cvScalar(94,0,0,0),cvScalar(115,0,0,0),imgH);
	cvInRangeS(imgS,cvScalar(90,0,0,0),cvScalar(255,0,0,0),imgS);
	cvInRangeS(imgV,cvScalar(36,0,0,0),cvScalar(255,0,0,0),imgV);
	IplImage *imgTemp,*imgHsvBinnary;
	imgTemp=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	imgHsvBinnary=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	cvAnd(imgH,imgS,imgTemp);
	cvAnd(imgTemp,imgV,imgHsvBinnary);
	//形态学去噪
	//定义结构元素
	IplConvKernel *element=0;
	int values[2]={255,255};
	int rows=2,cols=1,anchor_x=0,anchor_y=1;
	element = cvCreateStructuringElementEx(cols,rows,anchor_x,anchor_y,CV_SHAPE_CUSTOM,values);
	//膨胀腐蚀
	cvDilate(imgHsvBinnary,imgHsvBinnary,element,1);
	cvErode(imgHsvBinnary,imgHsvBinnary,element,1);
	cvNamedWindow("imgh1");
	cvShowImage("imgh1",imgHsvBinnary);
	imgGray=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	cvCvtColor(imgSrc,imgGray,CV_RGB2GRAY);
	IplImage *imgRgbBinnary;
	imgRgbBinnary=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,1);
	int Thresold=myOtsu(imgGray);//求阈值
	cvThreshold(imgGray,imgRgbBinnary,Thresold,255,CV_THRESH_OTSU);
	cvNamedWindow("imgh2");
	cvShowImage("imgh2",imgRgbBinnary);
	
	//车牌定位
	//行定位
	int hop_num=10;//字符连续跳变次数的阈值
	int num=0;//计算跳变的次数
	int begin=0;//跳变是否开始
	int mark_Row[2]={0},k=0;//标记车牌的开始行与结束行
	for(int i=imgSrc->height-1;i>=0;i--)
	{
		num=0;
		for(int j=0;jwidth-1;j++)
		{
			if(cvGet2D(imgHsvBinnary,i,j).val[0]!=cvGet2D(imgHsvBinnary,i,j+1).val[0])
			   {
					num++;
			   }
		}
		if(num>hop_num)
			{
				mark_Row[k]=i;
				k++;
				if(k>1)
					k=1;
		     }
	}
	std::cout <<"mark=  " <<  mark_Row[0] << "    " << mark_Row[1];
	cvLine(imgSrc,cvPoint(0,mark_Row[0]),cvPoint(imgSrc->width,mark_Row[0]),CV_RGB(255,255,0));
	cvLine(imgSrc,cvPoint(0,mark_Row[1]),cvPoint(imgSrc->width,mark_Row[1]),CV_RGB(255,255,0));
	//列定位
	int mark_col[2]={0},num_col=0,k_col=0;
	int a[100]={0},Thresold_col=10;
	for(int j=0;jwidth;j++)
	{
		num_col=0;
    	for(int i=mark_Row[1];i0)
				num_col++;
				if(num_col>Thresold_col)
				{
					mark_col[k_col]=j;
					k_col++;
					if(k_col>1)
						k_col=1;
				}
	}
	int i=0;
	cvLine(imgSrc,cvPoint(mark_col[0],0),cvPoint(mark_col[0],imgSrc->height),CV_RGB(255,0,0));
	cvLine(imgSrc,cvPoint(mark_col[1],0),cvPoint(mark_col[1],imgSrc->height),CV_RGB(255,0,0));
	IplImage *imgLicense;
	int license_Width=(mark_col[1]-mark_col[0])/4*4;
	int license_Height =mark_Row[0]-mark_Row[1];
	
	cvSetImageROI(imgSrc,cvRect(mark_col[0],mark_Row[1],license_Width,license_Height));
	imgLicense=cvCreateImage(cvGetSize(imgSrc),imgSrc->depth,imgSrc->nChannels);
	cvCopy(imgSrc,imgLicense,0);
	cvResetImageROI(imgSrc);
	cvNamedWindow("license");
	cvShowImage("license",imgLicense);
	cvNamedWindow("src");
	cvShowImage("src",imgSrc);
	cvWaitKey(0);
	return 0;
}
运行结果:


          基于OpenCV的车牌定位方法_第1张图片
                        原图像



基于OpenCV的车牌定位方法_第2张图片

                                                                  

                                                                                           运行结果


  


你可能感兴趣的:(opencv,机枪手opencv)