搜档网
当前位置:搜档网 › 基于opencv2.0的车牌检测与字符分割的代码

基于opencv2.0的车牌检测与字符分割的代码

基于opencv2.0的车牌检测与字符分割的代码
基于opencv2.0的车牌检测与字符分割的代码

本程序主要实现的是车牌的定位与检测

主要是利用申继龙论文里面的方法

1、采集得到的图像

2、把RGB图像转换成HSI彩色图像

3、利用设定的H、S阈值得到二值图像

4、对二值图像水平投影获得候选区域

5、对候选区域的HSI图像边缘检测

*/

#include "stdafx.h"

#include "opencv2/opencv.hpp"

#include "opencv2/objdetect/objdetect.hpp"

#include "opencv2/features2d/features2d.hpp"

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/calib3d/calib3d.hpp"

#include "opencv2/nonfree/nonfree.hpp"

#include "opencv2/nonfree/features2d.hpp"

#include "opencv2/imgproc/imgproc_c.h"

#include "opencv2/legacy/legacy.hpp"

#include "opencv2/legacy/compat.hpp"

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

using namespace cv;

#define pi 3.14159265

IplImage* srcImage=NULL;//存储原图片

IplImage*srcImage1=NULL;//存储原始图片的副本

IplImage* HSI=NULL;

static IplImage* grayImage=NULL;//存储原图片灰度图

static double posdouble=0.0;

IplImage* channelOneImage=NULL;

IplImage* channelTwoImage=NULL;

IplImage* channelThreeImage=NULL;

IplImage* plateImage=NULL;//存储车牌图像

IplImage* grayPlateImage=NULL;//存储车牌灰度图像

vectorcharacterImageList;//存储7个车牌字符图像的容器vectorxList;//存储7个车牌字符的起始和结束位置

vector>keyPointsList;//存储车牌字符特征点的集合vectordescriptorsMatList;//存储每一个车牌字符的特征点描述子矩阵vector> contours;//用来存储经过闭开操作处理后的车牌轮廓double GetH(int r,int g,int b)

{

double H=0;//H分量

double fenZi=1/2.0*((r-g)+(r-b));

double sq=pow(double(r-b),2)+(r-b)*(g-b);

double fenMu=sqrt(sq);

H=acos(fenZi/fenMu)*180/pi;

if(b>g)

{

H=360-H;

}

return H;

}

double GetS(int r,int g,int b)

{

double s=0;//S分量

int min=r;

if(g

{

min=g;

if(b

{

min=b;

}

}

else

{

if(b

{

min=b;

}

}

s=1-3.0*min/((r+g+b)*1.0);

return s;

}

double GetI(int r,int g,int b)

{

double i=0.0;

i=1/3.0*(r+g+b);

i=i/255.0;

return i;

}

//通过公式来直接求H的值然后对H分量进行处理

void doHByMath(IplImage* eleImage)

{

int width=eleImage->width;

int height=eleImage->height;

for(int col=0;col

{

uchar* ptr=(uchar*)(eleImage->imageData+col*eleImage->widthStep);//

uchar* ptrGray=(uchar*)(grayImage->imageData+col*grayImage->widthStep);//

for(int row=0;row

{

int b=ptr[3*row];

int g=ptr[3*row+1];

int r=ptr[3*row+2];

double H=GetH(r,g,b);

double S=GetS(r,g,b);

double I=GetI(r,g,b);

if(H>=190&&H<=255&&S>0.3)

{

ptrGray[row]=255;

}

else

{

ptrGray[row]=0;

}

if(I<0.25&&S<0.4)

{

ptrGray[row]=0;

}

}

}

cvShowImage("H分量处理后的图像",grayImage);

//考虑H分量处理后就提取尽量多的有用的区域

vector>contours;

Mat mtx = grayImage;//把IplImage类型转换成Mat类型

findContours(mtx,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);

Mat result(mtx.size(),CV_8U,Scalar(255));

drawContours(result,contours,-1,Scalar(0),2);

imshow("轮廓图",result);

}

//以下代买判断是否为蓝色像素点

//返回0代表是白色点

//返回1代表是蓝色点

int IsBlueOrWhite(IplImage* image,int col,int row)

{

CvScalar s;

s = cvGet2D(image, col,row);

int b=s.val[0];

int g=s.val[1];

int r=s.val[2];

double H=GetH(r,g,b);

double S=GetS(r,g,b);

double I=GetI(r,g,b);

if(H>=190&&H<=255&&S>0.3)

{

return 1;

}

/*if(I<255&&S>0)

{

}*/

/*double grayLevel = r * 0.299 + g * 0.587 + b * 0.114;

if (grayLevel >= 200)

{

return 0;

}*/

bool

flagWhite2=(I>=0.95)||(I>=0.81&&I<0.95&&S<(18.0/180.0))||(I>=0.61&&I<=0.8&&S<(20.0/18 0.0))||(I>=0.61&&I<=0.8&&S<(20.0/180.0))||(I>=0.51&&I<=0.6&&S<(30.0/180.0));

bool flagWhite1=(S<=0.3&&I>=0.6);

if(flagWhite1||flagWhite2)

{

return 0;

}

return 2;

}

int IsBlueOrWhite(int col,int row)

{

return IsBlueOrWhite(srcImage,col,row);

}

bool IsEdgeOrNot(int col,int row)

{

int flag00=IsBlueOrWhite(col-1,row-1);

int flag10=IsBlueOrWhite(col,row-1);

int flag20=IsBlueOrWhite(col+1,row-1);

int flag01=IsBlueOrWhite(col-1,row);

int flag11=IsBlueOrWhite(col,row);

int flag21=IsBlueOrWhite(col+1,row);

int flag02=IsBlueOrWhite(col-1,row+1);

int flag12=IsBlueOrWhite(col,row+1);

int flag22=IsBlueOrWhite(col+1,row+1);

if(flag00==1&&flag10==1&&flag20==1)

{

if(flag02==0&&flag12==0&&flag22==0)

{

return true;//是蓝白边缘

}

}

if(flag00==0&&flag10==0&&flag20==0)

{

if(flag02==1&&flag12==1&&flag22==1)

{

return true;//是蓝白边缘

}

}

return false;

}

//对是蓝白边缘的一个处理

void doIsEdge(int col ,int row)

{

cvSet2D(grayImage, col-1,row,cvScalar(255));

cvSet2D(grayImage, col,row,cvScalar(255));

cvSet2D(grayImage, col+1,row,cvScalar(255));

cvSet2D(grayImage, col-1,row-1,cvScalar(0));

cvSet2D(grayImage, col,row-1,cvScalar(0));

cvSet2D(grayImage, col+1,row-1,cvScalar(0));

cvSet2D(grayImage, col-1,row+1,cvScalar(0));

cvSet2D(grayImage, col,row+1,cvScalar(0));

cvSet2D(grayImage, col+1,row+1,cvScalar(0));

}

//对不是蓝白边缘的处理

void doNotEdge(int col,int row)

{

cvSet2D(grayImage, col-1,row,cvScalar(0));

cvSet2D(grayImage, col,row,cvScalar(0));

cvSet2D(grayImage, col+1,row,cvScalar(0));

cvSet2D(grayImage, col-1,row-1,cvScalar(0));

cvSet2D(grayImage, col,row-1,cvScalar(0));

cvSet2D(grayImage, col+1,row-1,cvScalar(0));

cvSet2D(grayImage, col-1,row+1,cvScalar(0));

cvSet2D(grayImage, col,row+1,cvScalar(0));

cvSet2D(grayImage, col+1,row+1,cvScalar(0));

}

//边缘检测代码

//检测蓝白边缘

//通过构造3*3窗口

void EdgeDetection()

{

int width=srcImage->width;

int height=srcImage->height;

for(int col=1;col

{

for(int row=1;row

{

//判断是否为蓝白边缘

if(IsEdgeOrNot(col,row))

{

//设置3*3窗口中间一列的所有值为1 其他列为0

doIsEdge(col,row);

}

else

{

//设置3*3窗口中所有元素的值为0

doNotEdge(col,row);

}

}

}

cvShowImage("蓝白边缘检测后的车辆图像",grayImage);

}

//这个函数主要是实现提取每一个字符的sift特征

//在提取sift特征我们先对每一个字符图片做尺寸的归一化处理

void ExtractSiftFeature()

{

Mat image11= imread("C:/Users/wzafxj/Desktop/车牌车标识别论文/车牌识别论文集锦/字符模板/字符模板/G.bmp",0);

SurfFeatureDetector surf(5000);//特征点选取的hessian 阈值为3000

SurfDescriptorExtractor surfDesc;//SurfDescriptorExtractor是提取特征向量的描述子

Mat descriptors;

vector keypoints;//存储每个车牌字符的surf特征点

CvSize size=cvSize(41,82);

CvSize cvsize11=cvSize(30,62);

resize(image11,image11,cvsize11);

vector matches;

DescriptorMatcher *pMatcher = new FlannBasedMatcher; // 使用Flann匹配算法

vector keypoints11;

surf.detect(image11,keypoints11);//这里是利用surf算法检测关键点

Mat descriptors11;

https://www.sodocs.net/doc/34330735.html,pute(image11,keypoints11,descriptors11);

imshow("moban",image11);

IplImage* pDstImage = cvCreateImage(size, grayPlateImage->depth, grayPlateImage->nChannels);

for(int i=0;i

{

cvResize(characterImageList[i],pDstImage,CV_INTER_AREA);

Mat image=pDstImage;

imshow("hahh",image);

surf.detect(image,keypoints);//这里是利用surf算法检测关键点

keyPointsList.push_back(keypoints);

//接下来提取surf特征点

https://www.sodocs.net/doc/34330735.html,pute(image,keypoints,descriptors);

descriptorsMatList.push_back(descriptors);

pMatcher->match(descriptors11, descriptors, matches);

Mat imageMatches;

drawMatches(image11,keypoints11, // 1st image and its keypoints

image,keypoints, // 2nd image and its keypoints

matches, // the matches

imageMatches, // the image produced

Scalar(255,255,255)); // color of the lines

string winName="WN"+i;

imshow(winName,imageMatches);

}

}

//显示已经分割出来的车牌字符

void ShowSeparatedCharacterImage()

{

if(characterImageList.size()>0)

{

for (int i=0;i

{

const char* windowName="识别出来的车牌字符"+i;//注意这里前面必须得加const

//否则会报错因为"识别出来的车牌字符" 是常量字符不能赋给不是常量的字符

cvNamedWindow(windowName,1);

cvShowImage(windowName,characterImageList[i]);

}

}

}

//根据xList里面存储的14个值来对

void CharacterSegmentation()

{

int height=grayPlateImage->height;

IplImage* characterSegImage=NULL;//定义一个临时存储字符图片

CvRect roiGrayPlate;

CvRect roiCharacter;

for(int i=0;i

{

int x1=xList[i];

int x2=xList[i+1];

int width=x2-x1;

characterSegImage=cvCreateImage(cvSize(width,height),grayPlateImage->depth,grayPlateI mage->nChannels);

roiGrayPlate=cvRect(x1,0,width,height);

cvSetImageROI(grayPlateImage,roiGrayPlate);

roiCharacter=cvRect(0,0,width,height);

cvSetImageROI(characterSegImage,roiCharacter);

cvCopy(grayPlateImage,characterSegImage);

cvResetImageROI(characterSegImage);

cvResetImageROI(grayPlateImage);

characterImageList.push_back(characterSegImage);

}

//接下来就是对提取出来的字符进行sift特征提取,并且标准库中的字符模板进行sift 特征匹配,以达到字符识别的目的

//不过进行上面的操作之前我们先把这七个字符显示出来再说

ShowSeparatedCharacterImage();

//接下来是对分割出来的车牌特征进行sift特征提取

//ExtractSiftFeature();

}

//对字符为白色、背景为黑色的车牌做垂直投影

//以此来达到字符分割的目的

bool VerticalProjectionToPlateImage(IplImage* grayPlateImage)

{

IplImage* paintx=cvCreateImage( cvGetSize(grayPlateImage),IPL_DEPTH_8U, 1 );

cvZero(paintx);

int* v=new int[grayPlateImage->width];

memset(v,0,grayPlateImage->width*4); //作用是在一段内存块中填充某个给定的值,它是

对较大的结构体或数组进行清零操作的一种最快方法

int x,y;

CvScalar s,t;

//再次提醒对于图像来说坐标原点是在图像的左上角

//我们定义一个容器来存储车牌字符的每一个起始位置和结束位置

//是这样的容器里面的第一个值是第一个字符的起始位置

//第二个值既是第一个字符的结束位置,依次类推

//但是第二个字符过后的14个像素单位里面可能出现字符点,我们不能提取,这个点就是车牌字符中的那个点

//在字符的检测中,如果x2-x1的长度超过了20,我们就默认这个字符的检测已经结束,就是说已经检测出来这个字符了

//注意除了第二个字符和第三个字符之间的距离超过了14个像素点之多外呢,其他每两个字符之间的距离应该也至少有2个像素

//因此我们在取值的时候一定要注意到这个问题比如2 22 27 47 60 80 81 101 102 122 123 143 146 166 167

//仔细观察60 80 81 中的81的取值不对应该跨两个像素点再去取应该取83 也就是xList的size()为双数的时候要进行判断

//可惜我们还是没有考虑字符“1”的情形

//通过仔细观察我们字符“1”它的高度至少超过30像素它的宽度在5左右主要是它离它后面的一个字符的距离有10像素左右

bool flag1=false;

bool flag2=false;

int count=0;

int x1=0;

int x2=0;

int countPoint=0;//设置这个是为了对中间因为有一个. 而存在8个多像素没有字符出现的情况所以我们设置一个这个来判断

int countOne=0;//用来对字符‘1’的处理

bool flagOne=false;//也是用来对字符1的处理

bool flagoneOut=false;//为true 代表字符'1'出现了

for(x=3;xwidth;x++)

{

int countCol=0;

for(y=0;yheight;y++)

{

s=cvGet2D(grayPlateImage,y,x);

if(s.val[0]==0)

v[x]++;

if(s.val[0]==255)

{

countCol++;

}

}

if(xList.size()==4)

{

countPoint++;

}

if(countCol>0&&flag1==false)

{

if(countPoint>0&&countPoint<12)

{

//对中间出现"." 的处理

}

else

{

if(xList.size()!=0&&xList.size()%2==0)

{

if(xList.size()>0)

{

//xList.back()获得容器的最后一个元素

if(x-xList.back()<2)

{

}

else

{

xList.push_back(x);

flag1=true;

}

}

}

else

{

xList.push_back(x);

flag1=true;

}

}

}

if(flag1==true)

{

if(countPoint>0&&countPoint<12)

{

//对中间出现"." 的处理

}

else

{

//如果字符'1' 出现在最后一个位子我们就没有处理的必要了

if(xList.size()<=12)

{

if(countCol>0)

{

flagOne==true;

countOne=0;

}

if(countCol==0&&flagOne==false)

{

countOne++;//如果countOne的值达到10左右(单位像素)且已不再countPoint处理的范围也就是已经过了中间的那个点

}

if(countOne>=12)

{

flagOne==true;

countOne=0;

//代表很有可能这个字符是1

flagoneOut=true;//代表是字符1出现了

}

}

}

}

if(countCol>0||(countCol==0&&count<20))

{

if(countPoint>0&&countPoint<12)

{

//对中间出现"." 的处理

}

else

{

//在这里我们加入一个字符1的处理

if(flagoneOut==true)

{

count=0;

flag1=false;

flagoneOut=false;

xList.push_back(x);

}

else

{

if(count<20)

{

if(flag1==true)

{

count++;//对于一个字符来讲必须等到起始位置记录了,才让count的值++

}

}

else

{

count=0;

flag1=false;

xList.push_back(x);

}

}

}

}

else

{

if(countPoint>0&&countPoint<12)

{

//对中间出现"." 的处理

}

else

{

count=0;

flag1=false;

xList.push_back(x);

}

}

}

//当xList里面存储的值的个数为13个(本来7个字符应该存储14个)的话,则把grayPlateImage->width存储到Xlist里面

if(xList.size()<13)

return false;

if(xList.size()==13)

{

xList.push_back(grayPlateImage->width);

}

if(xList.size()==15)

{

xList.pop_back();//删除容器的最后一个元素

}

for(x=0;xwidth;x++)

{

for(y=0;y

{

t.val[0]=255;

cvSet2D(paintx,y,x,t);

}

}

cvShowImage("车牌垂直积分投影",paintx);

//到这一步xList里面存储的是14个值每两个值代表的是一个字符元素的起始位置和结束位置

//接下来的操作就是我们利用这14个值来分割出字符来

CharacterSegmentation();

}

//这里是对图像进行任意角度倾斜的函数,angel表示要旋转的角度

//clockwise传递过来的值如果是为true则顺时针旋转,为false逆时针旋转

IplImage* rotateImage(IplImage* src, int angle, bool clockwise)

{

angle = abs(angle) % 180;

if (angle > 90)

{

angle = 90 - (angle % 90);

}

IplImage* dst = NULL;

int width =

(double)(src->height * sin(angle * CV_PI / 180.0)) +

(double)(src->width * cos(angle * CV_PI / 180.0 )) + 1;

int height =

(double)(src->height * cos(angle * CV_PI / 180.0)) +

(double)(src->width * sin(angle * CV_PI / 180.0 )) + 1;

int tempLength = sqrt((double)src->width * src->width + src->height * src->height) + 10;

int tempX = (tempLength + 1) / 2 - src->width / 2;

int tempY = (tempLength + 1) / 2 - src->height / 2; //这里的tempX和tempY指的是图像的中心像素点

int flag = -1;

dst = cvCreateImage(cvSize(width, height), src->depth, src->nChannels);

cvZero(dst);

IplImage* temp = cvCreateImage(cvSize(tempLength, tempLength), src->depth, src->nChannels); //图像temp并没有多大的实际含义,

//只不过是说把src图像size稍微扩大一点

//内容和src完全一样

cvZero(temp);

cvSetImageROI(temp, cvRect(tempX, tempY, src->width, src->height));

cvCopy(src, temp, NULL);

cvResetImageROI(temp);

if (clockwise)

flag = 1;

float m[6];

int w = temp->width;

int h = temp->height;

m[0] = (float) cos(flag * angle * CV_PI / 180.);

m[1] = (float) sin(flag * angle * CV_PI / 180.);

m[3] = -m[1];

m[4] = m[0];

// 将旋转中心移至图像中间

m[2] = w * 0.5f;

m[5] = h * 0.5f;

//

CvMat M = cvMat(2, 3, CV_32F, m); //M是一个3 ×2 变换矩阵[A|b]

//m0 m1 m2

// m3 m4 m5

//变换公式如下

//dst(x + width(dst) / 2,y + height(dst) / 2)=

//(m0x+m1y+b1,m3x+m4y+b2)

cvGetQuadrangleSubPix(temp, dst, &M); //提取象素四边形,使用子象素精度dst提取的是一个四边形

cvReleaseImage(&temp);

return dst;

}

//获得车牌的倾斜角度然后校正

//定义一个容器存储所有的countCol

vector countColVector;

struct maxTotalColAndAngel

{

int maxTotalCol;

int angel;

};

vector maxTotalColAndAngelVector;

bool less_second(const maxTotalColAndAngel m1, maxTotalColAndAngel m2) { return m1.maxTotalCol < m2.maxTotalCol;

}

bool GetAngleAndRotate(IplImage* _image)

{

IplImage* dstImage=NULL;

//假定车牌的旋转角度控制在30度的范围之内

bool _direction=false;//true代表顺时针

int _actualAngle=0;//存储最后得到的旋转角度

CvScalar s;

int maxCount=0;//存储最大的那个投影值

bool changeDirection=false;

int flag=-2;//-1代表的是往一开始设定的相反的方向旋转1代表的是旋转的方向是对的但是已经过了最大值

int Xnum=0;

//这里我们可以先做下canny二值化来减少计算量

for(int _angle=0;_angle<=30;_angle+=5)

{

dstImage=rotateImage(_image,_angle,_direction);

for(int x=dstImage->width-1;x>=0;x--)

{

int countCol=0;

for(int y=0;yheight;y++)

{

s=cvGet2D(dstImage,y,x);

//ptr[row]=0;

if(s.val[0]>0)

{

countCol++;

}

}

if(countCol>0)

{

countColVector.push_back(countCol);

}

}

sort(countColVector.begin(),countColVector.end());

maxTotalColAndAngel _colandangel={0,0};

_colandangel.angel=_angle;

for (int i=countColVector.size()-1;i>=countColVector.size()-2;i--)

{

_colandangel.maxTotalCol+=countColVector[i];

}

if(changeDirection==false&&_angle==5&&_colandangel.maxTotalCol<=maxTotalColAndA ngelVector[0].maxTotalCol)

{

maxTotalColAndAngelVector.clear();

changeDirection=true;

_direction=!_direction;

_angle=-5;

continue;

}

maxTotalColAndAngelVector.push_back(_colandangel);

countColVector.clear();//以便下次存储数据

}

sort(maxTotalColAndAngelVector.begin(),maxTotalColAndAngelVector.end(),less_second);

_actualAngle=maxTotalColAndAngelVector[maxTotalColAndAngelVector.size()-1].angel;

dstImage=rotateImage(_image,_actualAngle,_direction);

//在maxTotalColAndAngelVector[maxTotalColAndAngelVector.size()-1].angel的正负5度之内寻找旋转角度的精确值

if(_actualAngle>0)

{

maxTotalColAndAngelVector.clear();

for (int _angleDetail=_actualAngle-5;_angleDetail<=_actualAngle+5;_angleDetail++)

{

dstImage=rotateImage(_image,_angleDetail,_direction);

for(int x=dstImage->width-1;x>=0;x--)

{

int countCol=0;

for(int y=0;yheight;y++)

{

s=cvGet2D(dstImage,y,x);

//ptr[row]=0;

if(s.val[0]>0)

{

countCol++;

}

}

if(countCol>0)

{

countColVector.push_back(countCol);

}

}

sort(countColVector.begin(),countColVector.end());

maxTotalColAndAngel _colandangel={0,0};

_colandangel.angel=_angleDetail;

for (int i=countColVector.size()-1;i>=countColVector.size()-2;i--)

{

_colandangel.maxTotalCol+=countColVector[i];

}

maxTotalColAndAngelVector.push_back(_colandangel);

countColVector.clear();//以便下次存储数据

}

sort(maxTotalColAndAngelVector.begin(),maxTotalColAndAngelVector.end(),less_second);

_actualAngle=maxTotalColAndAngelVector[maxTotalColAndAngelVector.size()-1].angel;

dstImage=rotateImage(_image,_actualAngle,_direction);

}

imshow("旋转后的车牌图像",(Mat)dstImage);//这里只是水平旋转的结果

//我们把这个水平旋转的角度传给原始的车脸图像,对车脸图像进行旋转

IplImage* srcDst=rotateImage(srcImage,_actualAngle,_direction);

imshow("车脸图片的旋转",(Mat)srcDst);

//下面还要加一个垂直旋转

CvSize cvsize=cvSize(172,60);

IplImage*plateImage2=cvCreateImage(cvsize,dstImage->depth,dstImage->nChannels); CvRect roiSrc =cvRect(dstImage->width/2-86,dstImage->height/2-30,172,60); cvSetImageROI(dstImage, roiSrc);

CvRect roiPlate=cvRect(0,0,172,60);

cvSetImageROI(plateImage2,roiPlate);

cvCopy(dstImage,plateImage2);

cvResetImageROI(dstImage);

cvResetImageROI(plateImage2);

imshow("裁剪后的图像",(Mat)plateImage2);//去除一些边边框框

//我们最好在这里对plateImage2进行垂直旋转

//对经过处理后的车牌进行垂直投影处理

grayPlateImage=plateImage2;

bool flagYN=VerticalProjectionToPlateImage(plateImage2);

if(flagYN==false)

return false;

}

//对提取出来的车牌图像的一个处理

//把字符设置成白色

//把背景设置成黑色

bool DoWithPlateImage()

{

//首先把PlateImage进行灰度化处理

grayPlateImage=cvCreateImage(cvGetSize(plateImage),8,1);

cvCvtColor(plateImage,grayPlateImage,CV_RGB2GRAY);

for(int col=0;colheight;col++)

{

uchar* ptr=(uchar*)(grayPlateImage->imageData+col*grayPlateImage->widthStep);

for(int row=0;rowwidth;row++)

{

int flag=IsBlueOrWhite(plateImage,col,row);////flag为0代表是白色点flag为1代表是蓝色点

if(flag==1||flag==2)

{

ptr[row]=0;

}

else

{

ptr[row]=255;

}

}

}

//做一个开操作和闭操作

cvShowImage("经处理后的车牌图像",grayPlateImage);

//我们最好对车牌定一个统一的尺寸

CvSize cvsize=cvSize(175,70);

IplImage* pDstImage = cvCreateImage(cvsize, grayPlateImage->depth, grayPlateImage->nChannels);

cvResize(grayPlateImage, pDstImage, CV_INTER_AREA ); //象素关系重采样当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于CV_INTER_NN 方法grayPlateImage=pDstImage;

cvShowImage("插值后的车牌灰度图像",grayPlateImage); //显示CV_INTER_AREA 插值后的图像发现图像变模糊了

//这里我们加一个车牌倾斜校正的函数

//主要是要确定倾斜的角度到底是多少,这里可以采用hough变换或者是radon变换但是这两种变换对车牌的要求比较高,要有边框的的车牌图像

//这里我们采用旋转投影的办法,就是把车牌图像在间隔1度或者5度旋转,然后水平倾斜就在水平方向上进行投影看下投影值哪个最大,最大的那个旋转角度就是车牌的倾斜角度

//关键的关键是如何确定这个旋转角度,我们的思路是看车牌图像的最后一行的投影值,如果这个投影值最大,说明对应的旋转角度就是车牌的倾斜角度

bool flagYN=GetAngleAndRotate(grayPlateImage);//获得车牌倾斜角度并且进行旋转操作

if(flagYN==false)

return false;

//CvSize cvsize2=cvSize(172,64);

//IplImage*plateImage2=cvCreateImage(cvsize2,grayPlateImage->depth,grayPlateImage->n Channels);

//CvRect roiSrc =cvRect(grayPlateImage->width/2-86,grayPlateImage->height/2-32,172,64);

//cvSetImageROI(grayPlateImage, roiSrc);

基于matlab车牌的定位与分割识别程序概要

基于Matlab的车牌定位与分割 经典算法 I=imread('car.jpg'); %读取图像 figure(); subplot(3,2,1),imshow(I), title('原始图像'); I1=rgb2gray(I);%转化为灰度图像 subplot(3,2,2),imshow(I1),title('灰度图像'); I2=edge(I1,'robert',0.09,'both');%采用robert算子进行边缘检测subplot(3,2,3),imshow(I2),title('边缘检测后图像');

se=[1;1;1]; %线型结构元素 I3=imerode(I2,se); %腐蚀图像 subplot(3,2,4),imshow(I3),title('腐蚀后边缘图像'); se=strel('rectangle',[25,25]); 矩形结构元素 I4=imclose(I3,se);%图像聚类、填充图像 subplot(3,2,5),imshow(I4),title('填充后图像');

I5=bwareaopen(I4,2000);%去除聚团灰度值小于2000的部分subplot(3,2,6),imshow(I5),title('形态滤波后图像'); [y,x,z]=size(I5); I6=double(I5); Y1=zeros(y,1); for i=1:y for j=1:x

if(I6(i,j,1)==1) Y1(i,1)= Y1(i,1)+1; end end end [temp MaxY]=max(Y1); figure(); subplot(3,2,1),plot(0:y-1,Y1),title('行方向像素点灰度值累计和'),xlabel('行值'),ylabel('像素'); %求的车牌的行起始位置和终止位置 PY1=MaxY; while ((Y1(PY1,1)>=50)&&(PY1>1)) PY1=PY1-1; end PY2=MaxY; while ((Y1(PY2,1)>=50)&&(PY2

车牌识别地matlab程序

( 附录 车牌识别程序 clear ; close all; %Step1 获取图像装入待处理彩色图像并显示原始图像 Scolor = imread('');%imread函数读取图像文件 %将彩色图像转换为黑白并显示 Sgray = rgb2gray(Scolor);%rgb2gray转换成灰度图 " figure,imshow(Scolor),title('原始彩色图像');%figure命令同时显示两幅图 figure,imshow(Sgray),title('原始黑白图像'); %Step2 图像预处理对Sgray 原始黑白图像进行开操作得到图像背景s=strel('disk',13);%strel函数 Bgray=imopen(Sgray,s);%打开sgray s图像 figure,imshow(Bgray);title('背景图像');%输出背景图像 %用原始图像与背景图像作减法,增强图像 Egray=imsubtract(Sgray,Bgray);%两幅图相减 ¥ figure,imshow(Egray);title('增强黑白图像');%输出黑白图像 %Step3 取得最佳阈值,将图像二值化 fmax1=double(max(max(Egray)));%egray的最大值并输出双精度型 fmin1=double(min(min(Egray)));%egray的最小值并输出双精度型 level=(fmax1-(fmax1-fmin1)/3)/255;%获得最佳阈值 bw22=im2bw(Egray,level);%转换图像为二进制图像 bw2=double(bw22); %Step4 对得到二值图像作开闭操作进行滤波 、 figure,imshow(bw2);title('图像二值化');%得到二值图像 grd=edge(bw2,'canny')%用canny算子识别强度图像中的边界

车牌定位

本人的毕设收集资料 a.一些算法 1.基于纹理特征的车牌定位法 车辆图像随拍摄环境的变化而不同,然而车辆牌照具有不因外部条件变化而改变的特征。车牌内有多个基本成水平排列的字符,字符和牌照底在灰度值上存在跳变,因而车牌这个矩形区域(包括边缘)有丰富的边缘存在,呈现出规则的纹理特征。在传统的基于灰度分割技术上,这些特征为车牌定位研究提供了切实可行的依据。基于纹理分析的方法利用车牌区域内字符纹理丰富的特征定位车牌,它对于光照偏弱、偏强、不均匀性、牌照倾斜和变形等情况不敏感。但该方法应用于背景复杂的图像时,容易把一些纹理分布较丰富的非车牌区域定位进来,产生包含车牌在内的车牌候选区域,这是纹理分析方法的缺陷。 2.基于神经网络的定位算法 利用神经网络来定位车牌是一类较为常见的方法。本算法的基本步骤和各模块的功能如下:(1)神经网络训练模块:收集一定数量的车牌图像样本,归一化后输入至BP神经网络进行训练,达到预定的正确率后,训练结束。本模块将获得一个对车牌敏感的BP神经网络。 (2)图像预处理模块:提取车牌前,对图像进行预处理;抑制噪声,提高图片质量。 (3)车牌定位模块:利用训练好的神经网络在图像中搜索车牌区域,定位车牌。 本方法的特点是从车牌区域特征来判别牌照,因此在搜索时会重点考虑以下表面特征(如边缘、对比度、纹理等)而忽视图像区域的内容。有用信号的特征有时会误导搜索,如果因为定位模块忽视了非牌照区域包含的车牌特征信号点,将这些区域送入后续步骤将会影响车牌字符识别。 3基于特征统计的车牌定位 基于特征统计的车牌定位利用车牌区域的结构特征和字符纹理特征。车牌区域字符笔划变化含有丰富的边缘信息。对整幅汽车图像进行边缘检测,车牌区域相对于其它非车牌区域含有更多的细节信息。对边缘图像进行行或列扫描,该行或列灰度值跳变的次数明显不同非车牌区域的行或列,即基于特征统计的车牌定位方法。此方法分为两个部分:粗定位和精确定位。1.粗定位: 粗定位是从车牌边缘检测后的图像中找出含有车牌的区域,并把它提取出来,考虑到车牌区域中存在大量笔画边缘点集,当线段扫描到车牌区域时,£会大于某个阈值,这样就能初步找到横穿车牌区域的线段,然后以此线段为起点,上下平移扫描,利用车牌区域横向积分投影的连续性特征,定出车牌的上下边。在定位出上下边的同时,利用车牌白点数目占据主导的特点,用一定宽度的矩形,从左往右扫描。粗定位具体做法是用一个比估计车牌小的矩形遍历整个边缘二值图,则落在该矩形内白色的点最多的位置就是车牌区域的大致位置。2.精确定位: 车牌颜色主要分为:蓝底白字、黄底黑字、黑底白字,白底黑字四种。相同号码不同颜色组合的车牌不是同一个车牌,所以颜色信息在车牌定位的过程中相当重要。本文在精确定位时结合车牌的长宽信息、颜色信息,根据车牌颜色(蓝、白、黄、黑4种)像素占候选车牌区域所有像素的比例来确定哪个是车牌部分,由此得到准确的车牌区域。 具体思想如下:对粗定位中提取的区域进行研究,如果此区域蓝、黑、黄色中哪种颜色较多,则认为蓝底色牌照、黑底色牌照、黄底色牌照,剩余的车牌为白底色军车和武警车牌照等。每个颜色的RGB有一定的范围比例,如蓝色的RGB各值中蓝色分量最大,并且蓝色红色分量的比值大于门限Tb;黑色的RGB各值相差不大,它们与其它颜色的RGB值相比是很小的值,且小于门限Tbl;黄色的RGB各分量依次减小,而且蓝色分量远小于其它两色。设图像中像素的红

车牌图像定位与识别

专业综合实验报告----数字图像处理 专业:电子信息工程 班级: : 学号: 指导教师:

2014年7月18日 车牌图像定位与识别 一、设计目的 利用matlab实现车牌识别系统,熟悉matlab应用软件的基础知识,利用其解决数字信号处理的实际应用问题,从而加深对理论知识的掌握,巩固理论课上知识的同时,加强实践能力的提高,理论联系实践,提高自身的动手能力。同时不断的调试程序也提高了自己独立编程水平,并在实践中不断完善理论基础,有助于自身综合能力的提高。 二、设计内容和要求 车牌识别系统应包含图像获取、图像处理、图像分割、字符识别、数据库管理等几个部分,能够完成复杂背景下汽车牌照的定位分割以及牌照字符的自动识别。这里,只要求对给定的彩色车牌图像变换成灰度图像,用阈值化技术进行字符与背景的分离,再提取牌照图像。 三、设计步骤 1.打开计算机,启动MATLAB程序; 2.调入给定的车牌图像,并按要求进行图像处理; 3.记录和整理设计报告 四、设计所需设备及软件 计算机一台;移动式存储器;MATLAB软件。 五、设计过程 车辆牌照识别整个系统主要是由车牌定位和字符分割识别两部分组成,其中车牌定位又可以分为图像预处理及边缘提取模块和牌照的定位及分割模块;字符识别可以分为字符分割和单个字符识别两个模块。 (一)对图像进行图像转换、图像增强和边缘检测等

1.载入车牌图像: 原图 2.将彩图转换为灰度图并绘制直方图: 灰度图 灰度直方图 3.用roberts 算子进行边缘检测: 图像中车辆牌照是具有比较显著特征的一块图象区域,这此特征表现在:近似水平的矩形区域;其中字符串都是按水平方向排列的;在整体图象中的位置较为固定。正是由于牌照图象的这些特点,再经过适当的图象变换,它在整幅中可以明显地呈现出其边缘。边缘提取是较经典的算法,此处边缘的提取采用的是

车牌的定位与字符分割报告

车牌的定位与分割 实验报告 一实验目的 针对交通智能系统所拍摄的汽车图片,利用设定的算法流程,完成对汽车车牌部分的定位,分割车牌部分,并完成字符的分割,以便于系统的后续分析及处理。 二实验原理 详见《车牌的定位与字符分割》论文。 三概述 1一般流程 车牌自动识别技术大体可分为四个步骤:图像预处理、车牌定位与分割、车牌字符的分割和车牌字符识别。而这四个步骤又可归结为两大部分:车牌分割和车牌字符识别。 图1-1为车牌自动识别技术的一般流程图。 2本实验的流程 (1)图像预处理:图像去噪 (2)车牌的定位:垂直边缘检测(多次)形态学处理的粗定位

合并邻近区域结合车牌先验知识的精确定位 (3)车牌预处理:车牌直方图均衡化倾斜校正判定(蓝底白字或者黄底黑字)归一化、二值化 (4)字符的分割:垂直投影取分割阈值确定各个字符的左右界限(结合字符宽度、间隔等先验知识)分割字符 四实验过程 4.1图像预处理 4.1.1图像去噪 一般的去噪方法有:空间域上的均值滤波和中值滤波;频率域上的巴特沃斯滤波器。图4-1是各滤波器处理椒盐噪声的效果。 a.被椒盐噪声污染的图片 b.均值滤波的效果图 c.中值滤波的效果图 d.BLPF的效果图 图4-1 各滤波器处理椒盐噪声的仿真 可见,中值滤波对椒盐噪声的处理效果极好,而一般所拍摄的图片上最多的便是孤立的污点,所以此处以中值滤波为主进行去噪。图4-2是采用中值滤波处理实际汽车图片的效果。

a.原始图像 b.灰度图像 c.中值滤波后的图像 图4-2 中值滤波处理实际汽车图片的效果 很显然,经过中值滤波后去除了原图上的部分污点。 4.1.2图像复原 由于通常情况下都不知道点扩展函数,所以我们采用基于盲解卷积的图像复原策略。 图4-3~4-7图是函数进行盲解卷积的实验结果,其中图4-3是图像cameraman 的模糊图像。 图4-3 模糊图像 在盲解卷积处理中,选择适当大小的矩阵对恢复图像的效果很重要。PSF的大小比PSF的值更重要,所以首先指定一个有代表性的全1矩阵作为初始PSF。恢复的图像如图4-4所示,初始PSF如图4-5所示。

车牌识别(字符切割)大作业

图像处理技术

目录一.引言 (1) 二.目的和意义 (1) 三.设计原理 (1) 四.字符分割程序 (2) 五.结果 (4) 六.测试代码 (5) 七.系统的不足 (5) 八.总结 (5) 九.心得体会 (5) 十.致谢 (6) 十一.参考文献 (6)

一.引言 随着人们生活水平的不断提高,机动车辆数量大幅度增加,与之相配套的高速公路,城市路网及停车场越来越多,显著提高了人们对交通控制方面的要求。由于计算机技术的发展,信息处理水平的提高使智能交通系统成为世界交通领域研究的重要课题。其中车牌识别是智能交通系统的重要组成部分。车牌识别系统能够自动、实时地检测车辆、识别汽车车牌,从而监控车辆的收费、闯关、欠费以及各种舞弊现象。本系统为基于蓝色车牌的车牌识别系统,它能够识别非蓝色车辆的蓝底白字车牌。该系统通过车牌提取、车牌定位、预处理、字符分割、字符识别五个模块组成车牌识别系统。 二.目的和意义 通过对车牌识别系统的研究,自己开发小型车牌识别系统,虽有一定的局限性与不完整性,但可以使自己更加的熟悉MATLAB语言,激发对研究的兴趣,拓宽知识面,为自己以后的研究打下基础。在提升自身科研能力的同时,还能提高团队合作精神,清楚团队成员的分工,协调成员间的工作,为今后的团队合作研究积累经验。 三.设计原理 字符分割在此系统中有着承前启后的作用。它在前期车牌定位的基础上进行字符的分割,然后利用分割的结果进行字符的识别。字符识别的算法很多,应为车牌字符间间隔较大,不会出现字符粘连的情况,所以此处采用的方法为寻找连续有文字的块,若长度大于某阈值,则认为组成该块有两个字符,需要分割。一般分割出来的字符要进行进

基于Matlab的车牌自动识别技术研究与实现(基于Matlab的车牌二值化、阈值分割)

学位申请人: 指导教师: 学科专业: 软件工程 学位类别: 工学学士 2012年 06月 题目: 基于Matlab 的车牌二值化、阈值分割

西安工业大学毕业设计(论文)任务书 院(系) 计算机学院 专业 软件工程 班 080605 姓名 陈章权 学号 080605101 1.毕业设计(论文)题目: 基于Matlab 车牌自动识别技术的研究与实现 2.题目背景和意义: 车牌识别是现代智能交通系统中的重要组成部分之一,应用十分广泛。 它以数字图像处理、模式识别、计算机视觉等技术基础,对摄像机所拍摄的车辆图像或者视 频序列进行分析,得到每一辆汽车唯一的车牌号码,从而完成识别过程。通过一些后续处理 手段可以实现停车场收费管理、交通流量控制指标测量,车辆定位,汽车防盗,高速公路超 速自动化监管等等功能。对于维护交通安全和城市治安,防止交通堵塞,实现交通自动化管 理有着现实的意义。 3.设计(论文)的主要内容: 要求学生使用Matlab 工具对车牌识别进行开发。 主要研究内容包括: (1)图像数据采集和预处理 (2)二值化研究 (3)系统实现和效果评价 4.设计的基本要求及进度安排(含起始时间、设计地点):要求熟悉数字图像处理的基本知 识,熟悉matlab 编程 毕业设计的进度安排如下: 1~3周:准备所需资料,详细设计,开题报告,准备开题答辩。 4~12周:完成界面设计开发,详细设计,编程及调试。 13~15周:系统测试。 16~17周:书写毕业设计论文。 18周:改进完善,提交毕业论文,准备答辩。 5.毕业设计(论文)的工作量要求: ① 实验(时数)*或实习(天数): 18周 ② 图纸(幅面和张数)*: 无 ③ 其他要求: 毕业论文不少于15000字。 指导教师签名: 年 月 日 学生签名: 年 月 日 系(教研室)主任审批: 年 月 日 说明:1本表一式二份,一份由学生装订入附件册,一份教师自留。 2 带*项可根据学科特点选填。 毕I-2

基于垂直投影法的车牌字符分割算法设计

毕业论文(设计) 学院: 计算机科学学院 专业: 软件工程年级: 题目:基于垂直投影法的车牌字符分割算法设计学生姓名: 学号: 指导教师姓名: 职称: 年月

XXXX大学本科毕业论文(设计)原创性声明 本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。本人完全意识到本声明的法律后果由本人承担。 作者签名:年月日 目录 摘要 (1)

Abstract (1) 第一章绪论 (1) 1.1车牌识别技术的背景 (1) 1.2 车牌识别系统的工作原理 (2) 1.3 国内外研究 (3) 1.4 本文主要内容 (3) 第二章基本理论介绍 (3) 2.1 数字图像处理技术 (3) 2.1.1 bmp位图 (4) 2.1.2 RGB编码方式 (4) 2.1.3二值图像 (4) 2.1.4 Otsu算法 (4) 2.1.5灰度图像 (5) 2.1.6 中值滤波 (5) 第三章车牌图像的预处理 (5) 3.1车牌图像的灰度化 (5) 3.2车牌图像的二值化 (5) 3.3 去噪处理 (6) 3.3.1去除车牌边框 (7) 3.3.2去除车牌图像中的圆点 (8) 第四章车牌字符分割算法 (8) 4.1传统垂直投影的车牌字符分割算法 (8) 4.2 改进的垂直投影的车牌字符分割算法 (9) 第五章系统实现 (10) 第六章总结与展望 (13) 6.1 总结 (13) 6.2 展望 (13) 致谢 (14) 参考文献 (15)

基于垂直投影法的车牌字符分割算法设计 摘要:车牌识别系统在现代社会有着广泛应用,而车牌字符分割是其中的一项关键技术。本文针对车牌字符分割算法做了较为深入的研究。首先,要想正确的分割车牌图像,必须得到质量较好的车牌二值化图像。所以,本文对车牌字符分割的预处理部分进行较为深入的研究,尤其是车牌图像二值化后的去噪处理。传统投影法对车牌图像要求比较高,容易受到噪声的影响,从而造成分割字符的粘连与断裂。针对传统投影法的不足,文章提出一种基于垂直投影法的改进的字符分割算法,该算法可以有效地识别车牌字符。该方法抗干扰能力较强,能有效的减少字符粘连与断裂,分割准确度较高。 关键词:车牌识别;二值化;字符分割;垂直投影法 Vertical projection-based license plate character segmentation algorithm design Abstract:License plate recognition system has a wide range of applications in modern society, the license plate character segmentation is a key technology. In this paper, the license plate character segmentation algorithm to do a more in-depth study. First of all, in order to correct segmentation of license plate image must be of good quality license plate binary image. So more in-depth study of the pre-processing part of the license plate character segmentation, especially after the license plate image binarization denoising. Traditional projection on the license plate image requires relatively high, easily affected by noise, resulting in a split character adhesion and fracture. For the lack of traditional projection method, the paper presents a segmentation algorithm based on the improvement of the vertical projection of the characters, the algorithm can effectively identify the license plate character. Strong anti-interference ability of the method, which can effectively reduce the character adhesion and fracture, split high degree of accuracy. Keywords License Plate Recognition; binarization ;Character segmentation; Vertical projection 第一章绪论 随着世界经济的快速发展,以及汽车制造技术的提高,使得汽车迅速成为人们日常生活中的一个必需品。这造成全球的汽车数量猛增,而随之也导致城市的交通压力越来越大,城市的交通状况也因此得到了更多的关注。如何有效地对交通进行管理,也成为各国政府和相关部门所关注的焦点和热点。针对这些问题,人们开始将计算机技术、通信技术、计算机网络技术和自动化信息处理等很多新的科学技术用于交通道路的监视和管理系统,以此提高车辆管理和运输的效率。它主要是通过对过往车辆实施检测,提取有关的交通数据来达到对交通的监控、管理和指挥。车牌自动识别技术[1]是指能够检测到受监控路面的车辆并自动提取车辆车牌信息(含汉字字符、英文字母、阿拉伯数字及号牌颜色)进行处理与识别的技术。它以计算机技术、图像处理技术、模糊识别技术为基础,建立运动车辆的特征模型,识别车辆特征,如号牌、车型、颜色等,并着重解决高速车辆图像的获取及清晰度问题。本文是在以往的车牌分割算法[2]的基础上介绍了车牌识别技术中的一种字符分割算法,该算法是针对一种已有的字符分割算法(投影法)的改进性研究。 1.1车牌识别技术的背景 随着21 世纪经济全球化和信息时代的到来,迅猛发展的计算机技术、通信技术和计算机网络技术,水平不断提高的自动化信息处理技术在人们社会活动和生活的各个领域得到广泛应用。同时,高速度、高效率的生活节奏,使汽车普及成为必然趋势。伴随着世界各国汽车数量的增加,城市的交通状况越来越受到人们的重视。如何有效地进行交通管理日益成为各国政府相关部门所关注的焦点。针对这一问题,

车牌图像分割matlab代码

图像分割matlab代码 作者:佚名发布时间:2010-1-1 阅读次数:498 字体大小: 【小】【中】【大】 % This is a program for extracting objects from an image. Written for vehicle number plate segmentation and extraction % Authors : Jeny Rajan, Chandrashekar P S % U can use attached test image for testing % input - give the image file name as input. eg :- car3.jpg clc; clear all; k=input('Enter the file name','s'); % input image; color image im=imread(k); im1=rgb2gray(im); im1=medfilt2(im1,[3 3]); %Median filtering the image to remove noise% BW = edge(im1,'sobel'); %finding edges [imx,imy]=size(BW); msk=[0 0 0 0 0; 0 1 1 1 0; 0 1 1 1 0; 0 1 1 1 0; 0 0 0 0 0;]; B=conv2(double(BW),double(msk)); %Smoothing image to reduce the number of connected components L = bwlabel(B,8);% Calculating connected components mx=max(max(L)) % There will be mx connected components.Here U can give a value between 1 and mx for L or in a loop you can extract all connected components % If you are using the attached car image, by giving 17,18,19,22,27,28 to L you can extract the number plate completely. [r,c] = find(L==17); rc = [r c]; [sx sy]=size(rc);

基于matlab的车牌识别(含子程序)

基于matlab的车牌识别系统 一、对车辆图像进行预处理 1.载入车牌图像: function [d]=main(jpg) [filename, pathname] = uigetfile({'*.jpg', 'JPEG 文件(*.jpg)'}); if(filename == 0), return, end global FILENAME %定义全局变量 FILENAME = [pathname filename]; I=imread(FILENAME); figure(1),imshow(I);title('原图像');%将车牌的原图显示出来结果如下:

2.将彩图转换为灰度图并绘制直方图: I1=rgb2gray(I);%将彩图转换为灰度图 figure(2),subplot(1,2,1),imshow(I1);title('灰度图像'); figure(2),subplot(1,2,2),imhist(I1);title('灰度图直方图');%绘制灰度图的直方图结果如下所示: 3. 用roberts算子进行边缘检测: I2=edge(I1,'roberts',0.18,'both');%选择阈值0.18,用roberts算子进行边缘检测 figure(3),imshow(I2);title('roberts 算子边缘检测图像'); 结果如下:

4.图像实施腐蚀操作: se=[1;1;1]; I3=imerode(I2,se);%对图像实施腐蚀操作,即膨胀的反操作figure(4),imshow(I3);title('腐蚀后图像'); 5.平滑图像 se=strel('rectangle',[25,25]);%构造结构元素以正方形构造一个se

车牌识别系统需求分析模板

车牌识别系统需求分析文档 车牌识别系统需求分析小组 组长:**** 组员:**** **** **** ****

目录 1 引言..................................................... 错误!未定义书签。 编写目的................................................. 错误!未定义书签。 背景..................................................... 错误!未定义书签。 定义..................................................... 错误!未定义书签。 参考资料................................................. 错误!未定义书签。 2 任务概述................................................... 错误!未定义书签。 目标..................................................... 错误!未定义书签。 用户的特点............................................... 错误!未定义书签。 假定和约束............................................... 错误!未定义书签。 3 用例分析(或数据流程分析) ................................... 错误!未定义书签。 系统Actor分析........................................... 错误!未定义书签。 系统用例描述............................................. 错误!未定义书签。 4 动态行为模型............................................... 错误!未定义书签。 5 系统流程分析............................................... 错误!未定义书签。 6 系统开发及运行环境规定..................................... 错误!未定义书签。 7 小结..................................................... 错误!未定义书签。

基于opencv2.0的车牌检测与字符分割的代码

本程序主要实现的是车牌的定位与检测 主要是利用申继龙论文里面的方法 1、采集得到的图像 2、把RGB图像转换成HSI彩色图像 3、利用设定的H、S阈值得到二值图像 4、对二值图像水平投影获得候选区域 5、对候选区域的HSI图像边缘检测 */ #include "stdafx.h" #include "opencv2/opencv.hpp" #include "opencv2/objdetect/objdetect.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/nonfree/features2d.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/legacy/legacy.hpp" #include "opencv2/legacy/compat.hpp" #include #include #include #include #include #include #include #include #include using namespace std; using namespace cv; #define pi 3.14159265 IplImage* srcImage=NULL;//存储原图片 IplImage*srcImage1=NULL;//存储原始图片的副本 IplImage* HSI=NULL; static IplImage* grayImage=NULL;//存储原图片灰度图 static double posdouble=0.0; IplImage* channelOneImage=NULL; IplImage* channelTwoImage=NULL; IplImage* channelThreeImage=NULL; IplImage* plateImage=NULL;//存储车牌图像 IplImage* grayPlateImage=NULL;//存储车牌灰度图像 vectorcharacterImageList;//存储7个车牌字符图像的容器vectorxList;//存储7个车牌字符的起始和结束位置

(完整word版)字符分割

在车牌自动识别系统中最重要的指标是字符的识别率,对字符识别的准确率直接影响了系统的性能。字符识别部分由车牌图像的二值化、滤波、字符分割、字符大小规一化、汉字、字母和数字识别等模块组成。这一周我主要学习了字符分割模块的有关内容。 车牌字符分割的任务就是把多行或多字符图像中的每个字符从整个图像中分割出来,使其成为单个字符图像,为下一步将标准的单个字符输入到字符识别模块做准备。字符分割是字符识别的基础,字符分割的质量直接影响到字符识别的效果。字符分割之前,首先要进行图像的二值化,然后再进行字符分割,从而分割出一个个具体的二值图表示的字符图像点阵,作为单字识别的输入数据。由于文本图像不但包括了组成文本的一个个字符,而且包含了字符行间距与字符间的空白,甚至还会带有各种标点符号,这就需要采用一定的处理技术将文本中的一个个字符切分出来,形成单个字符的点阵,以便进行字符识别。车牌字符分割的原理主要是利用车牌字符自身的一些特点如规则整齐的排列、字符之间有一定的间隔、字符的宽高比例固定等等,对车牌区域进行垂直方向的投影,利用字与字之间的空白间隙在图像行垂直投影上形成的空白间隙将单个汉字的图像切割开来。 4.2投影分割 投影分割方法的原理是首先将车牌图像转换为二值图像(设白色为1,黑色为0),然后将车牌像素灰度值按垂直方向累加,即所谓的垂直投影。由于车牌中字符之间的灰度值通常为O,因此,投影图将会在字符之间形成谷底,或者说在字符处形成波峰(一种特殊的波峰)。通过寻找两个波峰之间的谷点,将其作为字符分割的位置,完成字符的分割。投影分割法的具体步骤如下: (1)先自下而上对图像进逐行扫描直至遇到第一个白色象素点。记录下来,然后再由上而下对图像进行逐行扫描直到找到第一个白色象素点,这样,就找到图像大致的高度范围。(2)在这个高度范围之内再自左向右逐行扫描,遇到第一个白色象素时认为是字符分割的起始位置,然后继续扫描,直至遇到没有白色象素的列,则认为是这个字符分割结束。然后继续按照上述的方法扫描,直至图像的最右端,就得到每个字符比较精确的宽度范围。(3)在已知的每个字符比较精确的宽度范围内,按照(1)的方法,分别进行自上而下和自下而上的逐行扫描来获得每个字符精确的高度范围。投影分割的方法比较常用,主要是针对在车牌定位、图像预处理后比较规则的车牌图像。它的优点是程序逻辑设计简单,循环执行功能单一,便于设计和操作,程序执行时间短。缺点是由于车牌图像通常会有噪声,产生字符的断裂和交叠等情况,在投影时字符之间的谷底会受到很大影响,造成谷底不明显,严重时谷底会消失,造成字符分割误差甚至错误,最终影响字符的识别。因此该方法对车牌字符的断裂和交叠问题,解决得不很理想。 4.3基于聚类分析的字符分割 基于聚类分析的字符分割原理是按照属于同一个字符的像素构成一个连通域的原则,再结合牌照字符的高度、间距的固定比例关系等先验知识,来分割车牌图像中的字符。其具体算法步骤为: (1) 以等于车牌图像宽度七分之一的阈值‘对车牌图像按行进行逐行扫描,如果有线段的长度大于‘就可以认为是牌照的上下边框,再以等于车牌图像高度五分之三的阈值Z:对车牌图像按列进行逐列扫描,如果有线段的长度大于厶,则认为是车牌的左右边框。因此可除去车牌边框部分。 (2)根据车牌字符的先验知识,在预处理好的车牌图像上预设7个类中心。设置类中心可以采用程序提示给定坐标值的方法,也可以采用给予固定坐标值的方法。 (3)自下向上对图像进行逐行扫描,每扫描到一个白色象素时,都要与上述每个类已获得的每个(白色)象素比较距离d,找到与该象素距离最近的已获得象素点,并认为这两个象素属于同一类,即属于同一字符。距离d取两个象素点:彳(x,Y)扫描得到的当前象素,曰O,),)

车牌识别系统是如何实现的

车牌识别系统是如何实现的 智能交通中一个重要的技术就是车牌识别技术,对于拍到的车辆图像或录像,如果能够准确及时的返回车牌的号码,这样即方便了车辆管理,又可以及时对违章车辆进行处罚,同时由于识别的即时性和准确性,这一系统在军事上也有极其重要的意义。车牌自动识别技术自提出以来,受到了人们的广泛关注,它可以应用于公路和桥梁收费站、公路流量观测站、城市监控系统、港口和机场、停车场、以及军事要塞的入口等车牌认证实际交通系统中,以提高交通系统的车辆监控和管理的自动化程度。由于其在智能化交通控制管理中发挥着越来越重要的作用,目前西方发达国家的科研工作者对其进行广泛的研究,目前己有众多的算法,一般的车牌识别系统总体构架图恤口图所示,经过这些年的研究,有些已应用于交叉路口、车库管理、路口收费、高速公路等场合。但是由于需适应各种复杂背景,加之要识别的车辆种类繁多,颜色变化多端,以及检测时要适应不同天气变化导致的不同光照条件。因此,目前的系统都或多或少地存在着一些问题。随着计算机性能的提高和理论技术的发展,这种技术必将日趋成熟。以下对我们设计的车牌自动识别系统的构成作简单介绍。 一个完整的车牌自动识别系统通常由图像采集,车牌定位,车牌牌字符分割和车牌字符识别部分组成。 车牌自动识别系统是一个以微处理器为核心,基于图像处理、模式识别等技术的高度智能的电子系统,这个系统主要有摄像头、视频采集接口、辅助照明装置、计算机和识别软件组成。 在自然光较暗或夜间影响识别效果时,自动开启辅助照明装置提供摄像光源。当车辆通过关卡,经过车体位置传感器的敏感区域时,传感器发送一个信号给图像采集控制部分。采集控制部分控制摄像机采集一幅汽车图像送至图像预处理模块,由预处理模块对输入图像进行预处理后送入计算机内。计算机内的软件模块从输入图像中找到牌照的位置,对牌照作字

基于matlab的车牌字符分割

《多媒体通信技术》课程报告 专业通信与信息系统 学号 姓名 任课教师

基于matlab的车牌字符分割 摘要:本文利用投影分割的方法对车牌字符进行分割,并利用模板匹配的方法进行字符识别,在图像进行预处理后的基础上,利用对车牌图像分块扫描的方法对车牌图像去边框处理,在去边框的基础上对每个字符进行分割,得到单个字符。关键字:字符;预处理;分割 1、引言 智能交通系统(intelligent transportation system,ITS)的发展现今对社会生活、国民经济和城市建设产生积极而深远的影响,我国已经将其列为优先发展的高技术产业化重点领域[1]。车牌识别系统(1icense plate recognition,IJR)是目前交通部门十分重要的科研课题之一,它主要包括车牌定位、字符分割和字符识别三部分,字符分割和字符识别是最后的关键环节。本文主要通过运用投影分割的方法对车牌进行字符分割并利用模板匹配的方法对车牌字符进行识别。2、图像预处理 图像预处理是对输入的图像进行一系列变换处理,使之成为符合字符识别模块要求的图像。图像预处理环节对于最终识别的正确率有很大影响,由于图像本身受到各种自然因素或设备因素的影响,图像的清晰度往往不是很理想,有时还会带有较明显的图像噪声。若不对图像进行预处理,这些噪声将给后续的识别模块带来严重影响,最终可能造成识别错误。因此,预处理的好坏一定程度上影响到字符识别的正确率。图像预处理首先需要将待识别的字符从输入的灰度图中分离出来。最常用的方法就是图像二值化。 2.1图像的灰度化

就是将彩色图像转化为具有256个灰度级的黑白图像,灰度图像只保留图像的亮度信息,去除了色彩信息,就像我们平时看到的黑白照片,它的亮度由暗到明,而且亮度变化是连续的。图像灰度化后可以使处理运算量大大减少,这样处理过程就变得更加简单和省时。在灰度图像中,通常将亮度划分成0到255共256个级别,0最暗,255最亮。 图2-1 灰度化的图像 2.2 图像的阈值化处理 所谓图像二值化就是指将灰度图转化为只含有两种灰度值的图像,一种为背景,另一种为待识别的字符,本文采用动态阈值法将图像二值化:如果输入图像较暗或者车牌较脏,如果采用固定的阈值将图像进行二值化,生成的二值图会非常黑或者有很多噪声。二值化有很多方法,主要为P片法或者峰谷法。本文采用的是P片法,阈值的大小的设定基于以下假设:由于现有车牌绝大部分为蓝底白字或者黄底黑字车牌,设理想的车牌平均包含大约60%的蓝/黄色像素和40%的白/黑色像素。首先,将图像二值化,计算出黑色和白色像素的比例,将它和期望值进行比较。从而算出新的阈值,直到近似等于期望值为止[2]。图1为理想状态下车牌原图片和的阈值化图片。 图2-2-1 阈值化的图像 图像经过上述步骤处理后,已经从带有噪声的灰度图像转变为符合识别要求的图像。该图像为只包含两种灰度值的二值图像,并且具有统一尺寸。而且在预处理环节中,已最大限度地去除了输入图像中的噪声,在保持字符原本信息不丢失的前提下,把待识别的字符从背景中成功地分离出来。 3 车牌的去边框处理

汽车车牌定位识别概述

快速标牌定位识别 指导老师:洪占勇,王标 成员:刘超,纪奕博 合肥工业大学仪器科学与光电工程学院本科部 二〇一一年八月

摘要 智能交通管理系统已成为当前交通管理发展的重要方向, 作为智能交通系统关键部分的车牌识别系统,有着广泛的应用前景。但是,传统的车辆牌照识别大多是以计算机硬件平台和DSP处理器为核心来实现的,相比较而言,DSP适合串行算法,软件更改容易,开发难度低。而FPGA则适合并行算法,而且随着深亚微米FPGA技术的发展,FPGA 的容量以达到千万门级,运行速度远远高于目前最快的DSP,其应用的研究也越来越受到重视,但开发难度较高。但Xilinx公司所提供的系统级建模工具System Generator,在很多方面拓展了MathWorks公司的Simulink平台,提供了设个硬件设计的DSP建模环境,可以加速、简化FPGA的DSP系统级硬件设计,这也必将成为未来流行的FPGA开发技术之一。 本文首先介绍了车辆牌照定位识别的产生背景和基本概念,回顾了近年来国内外研究动态和现状。接着指出了牌照识别的重要性,在使用MathWorks公司的simulink平台的基础上搭建的System Generator 模型,提出了车辆牌照定位识别系统及其整体设计方案。在方案中,着重介绍了车牌定位识别的流程、算法及其在simulink平台上实现的过程,同时也详细介绍了系统软硬件接口的作用。方案中主要包括系统流程图,每个模块的主要功能和结构,数据处理的流程和算法,输入输出信号的说明以及关键的时序和状态。在文章的最后,给出了本系统算法中拟采用的System Generator模型和总结。 由于本系统利用了System Generator建模工具和MathWorks公司的

车牌定位分割识别程序

附录A %主函数 function [d]=main(jpg) close all clc I=imread('car1.jpg'); figure(1),imshow(I);title('原图') I1=rgb2gray(I); %将RGB图形或色图矩阵转换成灰度图 figure(2),subplot(1,2,1),imshow(I1);title('灰度图'); figure(2),subplot(1,2,2),imhist(I1);title('灰度图直方图'); I2=edge(I1,'robert',0.15,'both');%提取I1的边缘,利用robert算子 figure(3),imshow(I2);title('robert算子边缘检测') se=[1;1;1]; %结构矩阵,用于图像的腐蚀 I3=imerode(I2,se);%以图像I2和结构元素SE为参数调用imerode函数进行腐蚀操作 figure(4),imshow(I3);title('腐蚀后图像'); se=strel('rectangle',[25,25]); I4=imclose(I3,se); %形态学中的闭运算,se为结构元素 figure(5),imshow(I4);title('平滑图像的轮廓'); I5=bwareaopen(I4,2000); figure(6),imshow(I5);title('从对象中移除小对象'); [y,x,z]=size(I5); %读取I5的大小,行列页 myI=double(I5); %将I5元素转为double型 tic %计时开始 Blue_y=zeros(y,1); %给蓝色像素个数赋初始值0 for i=1:y for j=1:x % 这两行是循环,先行,再列 if(myI(i,j,1)==1) % 如果I5第一页中的元素为1的话,则是蓝色像素 Blue_y(i,1)= Blue_y(i,1)+1;%蓝色像素点统计 end end end

相关主题