最近一直在研究车牌识别,看到一篇论文《基于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;
}
运行结果:
运行结果