900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【OpenCV学习笔记】【教程翻译】三( 车牌检测之区域分割)

【OpenCV学习笔记】【教程翻译】三( 车牌检测之区域分割)

时间:2021-02-22 10:10:02

相关推荐

【OpenCV学习笔记】【教程翻译】三( 车牌检测之区域分割)

在这一步,我们检测当前帧中的所有板状物体(plate不一定是车牌)。我们将这项工作分成两部分:区域分割和分割部分的分类。这里我们没有提特征步骤是因为我们把图像块作为一个矢量特征。

在第一步(分割),我们使用了不同的滤波器(高斯模糊,Sobel滤波,阈值滤波)和形态学(morphological)运算,轮廓(contour)算法,用于检索(retrieve)可能含有板状物体的表单域(validation)。

在第二部分(分类),我们应用了支持向量机(SVM)分类器对每个图像块(即我们的特征)。

在开始我们主要任务之前,我们训练了两个不同的类—有板状物体和没有板状物体。我们用的图片是在车的前方2-4米处拍摄的800个像素宽的彩色图像。这些要求对于保证分割的正确性是至关重要的。我们可以做一个多尺度的算法进行检测。

下面的图片中显示了车牌检测中涉及的所有过程:

1.Sobel滤波器

2.阈值操作(Thresholdoperation)

3.形态学闭运算(closemorphologicoperation)

4.maskofonefilledarea

5.检测到的可能是车牌区域用红色标记(特征图片)

6.SVM分类后检测出的车牌

下面的依次对应上面的六个操作:

第一步:分割

图像分割是将图像划分成多个图像块的过程。这种处理过程是为了简化图像的分析和方便后面的特征提取。

假定图像是从正面拍摄的,车牌没有旋转,也没有透射失真,那么车牌的分割的一个重要的特征就是大量的垂直边缘像素点。在分割的第一步,这个特征可以用来排除没有垂直边缘的区域。

在找垂直边缘之前,我们需要把彩色图像转换为灰度图像,(因为在这个任务中彩色的图像对我们没有帮助),去掉由相机和其他环境(ambient)产生的可能的噪声。我们使用5*5的高斯模糊(blur模糊/污迹)去除噪声

如果我们不使用噪声滤去方法,我们会得到大量的垂直边缘造成错误的检测。来找垂直边缘,我们使用了Sobel滤波器并找到水平一阶导数(horizontalderivative).这个导数是一个数学函数帮助我们找到图像中的垂直边缘。Sobel函数在OpenCV中的定义是:

这里,ddepth是目标图像的深度,xorder是对x的导数的阶数,yorder是对y的导数的阶数。ksize是内核的大小(值为1,3,5,7)。scale是一个可选的参数对于计算导数值,delta是一个可选的值添加到结果中。bordertype是像素插值(interpolation)的方法。

对于我们的例子,我们使用xoder=1,yorder=0,ksize=3

Sobel滤波之后,我们使用一个阈值滤波器获取一个二值图像,阈值是通过Otsu法/最大类间差法(大津法)获得。大津法需要一个深度为8的输入图像,并且大津法自动确定最佳的阈值:

在定义threshold函数的大津法时,如果我们结构参数赋值为CV_THRESH_OSTU,则阈值参数可以被忽略(即可用CV_THRESH_OSTU代替阈值)。

注意:当CV_THRESH_OTSU的值被定义了,阈值函数返回的是大津法得到的最佳阈值。

应用形态学的闭运算,我们可以去掉每个垂直边缘线的空白区域,连接有大量边缘的区域。在这一步中,我们可能得到包含车牌的区域。

首先我们定义结构元素用在形态学运算中,我们使用getStructurngElement函数来定义一个17*3的矩形结构元素,矩形结构元素的大小可能因图片的不同而不同。

在形态学操作中使用这个矩形结构元素,使用函数morphologyEx

应用这些函数之后,我们得到了图片中的一些可能包含车牌的区域,但是大部分的区域是不含有车牌的。这些区域可以通过连通区域分析或者使用findContour(找轮廓)函数区分。最后一个函数使用不同的方法检索二值图像中的轮廓可得到不同的结果。我们只需要得到不同层次(anyhierarchicalrelationship)的外部轮廓和任意多边形逼近:

对于每个被检测到的轮廓,提取最小面积的外接矩形,OpenCV提供了实现这个功能的minAreaRect函数,这个函数返回一个旋转的矩形类叫RotateRect。然后对每个轮廓使用矢量(vector)迭代器(iterator),我们可以得到旋转矩形并可以对区域进行分类之前来做一些基础(preliminary)的验证(validation):

Starttoiteratetoeachcontourfound----------开始iterate(重复,反复声明,只因为这些轮廓早已经找出来了,下面主要是剔除不合适的)已经找到的每个轮廓。

Romovepatchthathasnoinsidelimitsofaspectratioandarea-----剔除不符合长宽比和面积限制的轮廓。

我们基于长高比和面积对区域进行了基本的验证。我们只考虑长高比大约(approximately)为520/110=4.727272(板的宽度除以板的高度),伴随着40%的误差,板的高度大约有15个像素到125个像素。这些值的计算主要依赖于图片的大小和相机的位置:

Spaincarplatesize--------西班牙汽车牌的尺寸52*11长宽比为4.7272

Setaminandmaxarea,allotherpathesarediscarded-----设置区域的最大值和最小值,其他的对丢弃掉

Getonlypatchesthatmatchtoarespectratio------只获取符合(respect)比例的轮廓

车牌的白色背景特性提高了我们的识别效果,所有的车牌都具有相同的背景颜色,我们可以使用泛洪填充算法来实现旋转矩形的精确剪切(cropping=剪切,剪齐)。剪切车牌的第一步是在最后旋转矩形的中心获取一些种子。然后根据板的宽和高(取最小的)获取最小的板的尺寸,接着在轮廓中心的周围随机产生种子。

我们想要选择白色的区域,那我们需要一些种子接触到至少一个白色的像素。然后对于每个种子,我们使用floodFill函数来绘制出一个新的掩膜图像(maskimage)来存储新的剪切区域(closetcroppingregion)。

retrieve/检索

Forbetterrectcroppingforeachpossiblebox----为了对每个可能是车牌的“盒体”进行更好的矩形剪切

Makefloodfillalgorithmbecausetheplatehaswhitebackground使用洪水填充算法主要是因为有白色的背景

Andthenwecanretrievemoreclearlythecontourbox--然后我们就可以得到更清楚的轮廓框

Gettheminsizebetweenwidthandheight-----获取长和宽的最小值

Initializerandandget5pointsaroundcenterforfloodfill---初始化随机数并获取中心附近的五个点用于洪水填充算法

Initializefloodfillparametersandvariables初始化洪水填充参数和变量

洪水函数从一个种子开始,填充连通区域为一定的颜色,将图像变成了掩膜图像。设置在填充像素和相邻像素或者种子像素之间设置最大亮度/颜色的差异。

newVal是新的填充颜色,参数loDiff和upDiff是分别是要填充的像素和相邻像素或种子像素底部最大亮度差和顶部最大亮度差或者颜色差。Flag是参数高位和低位的组合。

地位:在函数中,这些包含着连接值,值为4(缺省)或者8,连通性决定着像素的周围那些像素需要考虑进去。

高位:可以是0或者以下值的结合:CV_FLOODFILL_FIXED_RANGEANDCV_FLOODFILL_MASK_ONLY.

CV_FLOODFILL_FIXED_RANGE设置当前像素和种子像素之间的差异,CV_FLOODFILL_MASK_ONLY只会掩膜图像而不会改变图像本身。

一旦我们获得了剪切的掩膜图像,我们就可以获取掩膜图像点的最小外接矩形并再次检测有效的大小。对于每个掩膜图像,通过白色像素获取位置,然后用minAreaRect函数获取剪切的区域。

Checknewfloodfillmaskmatchforacorrectpatch验证新的洪水掩膜图像为了区分是否含有正确的牌照

Getallpointsdetectedforminimalrotatedrect获取所有的被检测到的点构建最小旋转矩形

现在分割过程完成了,我们找到有效的区域。我们可以分割每个被检测出来的区域。我们需要注意高度的问题,因为旋转类可以返回并旋转90度。所以我们需要检查一下矩形的方向。如果r<1,则旋转90度。

Getrotationmatrix---获取旋转矩阵

有了旋转矩阵,现在我们可以对输入的图像进行仿射变换(affinetransformation)(仿射变换是一种几何变换,以平行线对平行线),对应的函数是warpAffine函数,在这个函数中主要有输入图像,目标图像,变换矩阵,输出尺寸(在本例中输入和输出的尺寸相同)和所用的插值方式(interpolation)。Wecandefinethebordermethodandbordervalueifneeded:

Createandrotateimage---------旋转并生成图像

我们旋转图像之后,我们用getRectSubPix函数截取图像。它以一个点为中心,按照给定的宽和高的比例截取并复制一副图片。如果图片被旋转了,我们需要改变使用C++swap(交换)函数改变宽和高的尺寸。

裁剪的图像并不适合用于训练和分类,因为他们的尺寸是不一样的。而且每张图片包含着不同的光照信息,这也增加了它们的相对差异。为了解决这个问题,我们将图片的尺寸设置成相同的宽和高,并应用亮度直方图均衡化。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。