最近在看车牌识别相关领域的论文,自己也试验了一些开源的代码,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); }
第一步的结果:纹理图片
第二步结果:顺序为:黑色点、蓝色点、白色点、黄色点
第三步结果:顺序为:蓝白特征对点、黄黑特征点对、黑白特征点对
而论文里边的处理结果确实很好,不知道在转HSV图片,以及各颜色分量的范围是如何确定的...按论文里边的范围得到的结果是不行的~~~~