实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究

最近在看车牌识别相关领域的论文,自己也试验了一些开源的代码,opencv自带的找四边形的程序等等,感觉效果都不好。在车牌识别中,关键的是车牌定位,决定了车牌识别的准确率,目前研究比较多的也就是基于颜色、边缘、纹理的车牌定位方法,看了几篇论文,有一篇硕士论文叫《汽车牌照识别系统中车牌定位与校正及字符分割的研究》,南航的一位同学的硕士毕业论文,想实现其中的车牌定位算法。可以去网上搜索该论文,在道客巴巴上有。

论文中车牌定位的算法分为九步,我只实现了前三步,觉得不行,具体的一些实现代码如下:

/////////////////////////////////////////////////////////////////////////////
//1. 确定纹理特征点
////////////////////////////////////////////////////////////////////////////
int cal_texture_point(IplImage * src,IplImage * dst)
{
	if(NULL == src || NULL == dst)
		return 1;

	IplImage * tempImage = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	
	uchar * data = (uchar *)src->imageData;
	uchar * result = (uchar *)tempImage->imageData;

	int width = src->width;
	int height = src->height;

	for(int i = 0;i < src->height;i++)
		for (int j = 0;j < src->width ;j++)
		{
			if(j == 0)
				result[i * src->widthStep + j] = abs(int(data[i * src->widthStep + j]) - int(data[i * src->widthStep + j + 1]));			
			else if(j == width - 1)
				result[i * src->widthStep + j] = abs(int(data[i * src->widthStep + j]) - int(data[i * src->widthStep + j - 1]));
			else
				result[i * src->widthStep + j] = abs(int(data[i * src->widthStep + j]) - int(data[i * src->widthStep + j + 1]))
							+ abs(int(data[i * src->widthStep + j]) - int(data[i * src->widthStep + j - 1]));
		}
	
	cvCopy(tempImage,dst);
	cvReleaseImage(&tempImage);
	
	return 0;
}
//////////////////////////////////////////////////////////////////////////
//2.计算颜色边缘点
//
//
//////////////////////////////////////////////////////////////////////////
int cal_color_edge(IplImage * src,IplImage * bwImage,IplImage * blue,IplImage * white,IplImage * yellow,IplImage * black)
{
	if(NULL == src)
		return 1;

	int width = src->width;
	int height = src->height;
	//计算HSV分量
	int k1,k2,r,g,b,h;
	float s,v;

	cvZero(blue);
	cvZero(white);
	cvZero(yellow);
	cvZero(black);

	uchar * data = (uchar *)src->imageData;

	uchar * blueD = (uchar *)blue->imageData;
	uchar * whiteD = (uchar *)white->imageData;
	uchar * yellowD = (uchar *)yellow->imageData;
	uchar * blackD = (uchar *)black->imageData;
	uchar * bwDate = (uchar *)bwImage->imageData;
	for (int i = 0;i < height;i++)
	{
		for (int j = 0;j < width;j++)
		{
			if(bwDate[i * bwImage->widthStep + j] == 0)
				continue;

			r = (int)data[i * src->widthStep + j];
			k1 = r;
			k2 = r;

			g = (int)data[i * src->widthStep + j + 1];
			if(k1 < g)k1 = g;
			if(k2 > g)k2 = g;
			b = (int)data[i * src->widthStep + j + 2];
			if(k1 < b)k1 = b;
			if(k2 > b)k2 = b;

			//计算hsv分量
			v = 1.0 * (k1 + k2) / 2 / 255;

			if(v == 0 || k1 == k2)
				s = 0;
			else if(v > 0.5)
				s = 1.0 * (k1 - k2) / (2 - 2 * v);
			else if(v <= 0.5)
				s = 1.0 * (k1 - k2) / (2 * v);

			if(s != 0 && k1 == r)
			{
				if(g >= b)
					h = 1.0 * (g - b) / (k1 - k2) * 60;
				else
					h = 1.0 * (g - b) / (k1 - k2) * 60 + 360;
			}
			else if(s != 0 && k1 == g)
				h = 1.0 * (b - r) / (k1 - k2) * 60 + 120;
			else if(s != 0 && k1 == b)
				h = 1.0 * (r - g) / (k1 - k2) * 60 + 240;
			else if(k1 == k2)
				h = 0;

			if(h > 200 && h < 250 && s > 0.1 && v > 0.1)
				blueD[i * blue->widthStep + j] = 255;
			else if(h > 20 && h < 50 && s > 0.1 && v > 0.35)
				yellowD[i * blue->widthStep + j] = 255;
			else if(h == 0 && s ==0 && v < 0.35)
				blackD[i * blue->widthStep + j] = 255;
			else if(v > 0.5 && s < 0.1)
				whiteD[i * blue->widthStep + j] = 255;
		}
	}

	return 0;
}


//////////////////////////////////////////////////////////////////////////
//3. 计算三种颜色对特征点
//蓝白、黄黑、白黑特征点对
//例如:如果(i,j)点为蓝色点,对于(i,j)左右两侧的四个像素点,一旦其中一个点有白色像素,则记为蓝白像素点;
//同样白色点左右四个点有蓝色点也记为蓝白特征点对
//////////////////////////////////////////////////////////////////////////
int cal_color_point(IplImage * blue,IplImage * white,IplImage * yellow,IplImage * black,
					IplImage * b_w_image,IplImage * y_b_image,IplImage * w_b_image)
{
	int width = blue->width;
	int height = blue->height;

	cvZero(b_w_image);
	cvZero(y_b_image);
	cvZero(w_b_image);;

	uchar * blueD = (uchar *)blue->imageData;
	uchar * whiteD = (uchar *)white->imageData;
	uchar * yellowD = (uchar *)yellow->imageData;
	uchar * blackD = (uchar *)black->imageData;

	uchar * y_b_data = (uchar *)y_b_image->imageData;
	uchar * b_w_data = (uchar *)b_w_image->imageData;
	uchar * w_b_data = (uchar *)w_b_image->imageData;
	for (int i = 0;i < height;i++)
	{
		for (int j = 2;j < width - 2;j++)
		{
			//计算蓝白点
			if(blueD[i * blue->widthStep + j] == 255)
			{
				for (int k = j - 2;k <= j + 2;k++)
				{
					if(whiteD[i * blue->widthStep + k] == 255)
						b_w_data[i * blue->widthStep + j] = 255;
				}
			}
			
			//计算蓝白点和白黑点
			if(whiteD[i * blue->widthStep + j] == 255)
			{
				for (int k = j - 2;k <= j + 2;k++)
				{
					if(blueD[i * blue->widthStep + k] == 255)
						b_w_data[i * blue->widthStep + j] = 255;
					if(blackD[i * blue->widthStep + k] == 255)
						w_b_data[i * blue->widthStep + j] = 255;
				}
			}
			//计算黄黑点
			if(yellowD[i * blue->widthStep + j] == 255)
			{
				for (int k = j - 2;k <= j + 2;k++)
				{
					if(blackD[i * blue->widthStep + k] == 255)
						y_b_data[i * blue->widthStep + j] = 255;
				}
			}

			//计算黄黑点和白黑点
			if(blackD[i * blue->widthStep + j] == 255)
			{
				for (int k = j - 2;k <= j + 2;k++)
				{
					if(yellowD[i * blue->widthStep + k] == 255)
						y_b_data[i * blue->widthStep + j] = 255;
					if(whiteD[i * blue->widthStep + k] == 255)
						w_b_data[i * blue->widthStep + j] = 255;
				}
			}
		}
	}

	return 0;
}


函数调用代码如下:

void main()
{
IplImage * image = 0;
	IplImage * gray = 0;
	IplImage * bwImage = 0;

	//计算颜色点
	IplImage * blueImage;
	IplImage * yImage;
	IplImage * wImage;
	IplImage * blackImage;

	//计算颜色点对
	IplImage * bandwImage;//蓝白特征点对
	IplImage * yandbImage;//黄黑特征点对
	IplImage * wandbImage;//白黑特征点对
image = cvLoadImage(files[i].c_str(),CV_LOAD_IMAGE_COLOR);
		blueImage = cvCreateImage(cvSize(image->width,image->height),8,1);
		yImage = cvCreateImage(cvSize(image->width,image->height),8,1);
		wImage = cvCreateImage(cvSize(image->width,image->height),8,1);
		blackImage = cvCreateImage(cvSize(image->width,image->height),8,1);

		bandwImage = cvCreateImage(cvSize(image->width,image->height),8,1);
		yandbImage = cvCreateImage(cvSize(image->width,image->height),8,1);
		wandbImage = cvCreateImage(cvSize(image->width,image->height),8,1);

		gray = cvCreateImage(cvSize(image->width,image->height),8,1);
		bwImage = cvCreateImage(cvSize(image->width,image->height),8,1);

		cvCvtColor(image,gray,CV_BGR2GRAY);
		
		//1.计算纹理图像===============================
		cal_texture_point(gray,gray);
		//二值化纹理图片保存至bwImage
		cvThreshold(gray,bwImage,0,255,CV_THRESH_OTSU);

		//2.计算颜色特征点=============================
		cal_color_edge(image,bwImage,blueImage,wImage,yImage,blackImage);
	
		//3.计算颜色对特征点===========================
		cal_color_point(blueImage,wImage,yImage,blackImage,bandwImage,yandbImage,wandbImage);

cvReleaseImage(&image);
		cvReleaseImage(&gray);
		cvReleaseImage(&bwImage);
		cvReleaseImage(&blueImage);
		cvReleaseImage(&wImage);
		cvReleaseImage(&yImage);
		cvReleaseImage(&blackImage);
}


原图:

实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究_第1张图片
结果图片为:

第一步的结果:纹理图片

实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究_第2张图片

第二步结果:顺序为:黑色点、蓝色点、白色点、黄色点

 实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究_第3张图片   实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究_第4张图片  

第三步结果:顺序为:蓝白特征对点、黄黑特征点对、黑白特征点对

实现-汽车牌照识别系统中车牌定位与校正及字符分割的研究_第5张图片  

而论文里边的处理结果确实很好,不知道在转HSV图片,以及各颜色分量的范围是如何确定的...按论文里边的范围得到的结果是不行的~~~~


你可能感兴趣的:(C++,图像处理,车牌识别,车牌定位)