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

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

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

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

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

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

1.Sobel滤波器

2.阈值操作(Threshold operation)

3.形态学闭运算(close morphologic operation)

4.mask of one filled area

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

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

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


第一步:分割

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

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

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

 如果我们不使用噪声滤去方法,我们会得到大量的垂直边缘造成错误的检测。来找垂直边缘,我们使用了Sobel滤波器并找到水平一阶导数(horizontal derivative).这个导数是一个数学函数帮助我们找到图像中的垂直边缘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(找轮廓)函数区分。最后一个函数使用不同的方法检索二值图像中的轮廓可得到不同的结果。我们需要得到不同层次(any hierarchical relationship)的外部轮廓和任意多边形逼近: 

  

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

     

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

       Romove patch that has no inside limits of aspect ratio and area-----剔除不符合长宽比和面积限制的轮廓。

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

       


      

Spain car plate size--------西班牙汽车牌的尺寸 52*11 长宽比为4.7272

Set a min and max area,all other pathes are discarded -----设置区域的最大值和最小值,其他的对丢弃掉

Get only patches that match to a respect ratio------只获取符合(respect)比例的轮廓

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

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

     

retrieve/检索

For better rect cropping for each possible box ----为了对每个可能是车牌的“盒体”进行更好的矩形剪切

Make floodfill algorithm because the plate has white back ground 使用洪水填充算法主要是因为有白色的背景

And then we can retrieve more clearly the contour box --然后我们就可以得到更清楚的轮廓框

Get the min size between width and height-----获取长和宽的最小值

Initialize rand and get 5 points around center for flood fill---初始化随机数并获取中心附近的五个点用于洪水填充算法

Initialize floodfill parameters and variables  初始化洪水填充参数和变量


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

      

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

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

高位:可以是0或者以下值的结合:CV_FLOODFILL_FIXED_RANGE AND CV_FLOODFILL_MASK_ONLY.

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

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


Check new floodfill mask match for a correct patch 验证新的洪水掩膜图像为了区分是否含有正确的牌照

Get all points detected for minimal rotated rect 获取所有的被检测到的点构建最小旋转矩形

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


 Get rotation matrix---获取旋转矩阵

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

Create and rotate image ---------旋转并生成图像

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

   

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



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,OpenCV是一个开源计算机视觉和机器学习软件库,用于开发图像和视频处理应用程序。通过使用OpenCV,您可以读取摄像头并显示实时图像,打开视频文件或摄像头文件,并获取视频的相关信息,例如帧宽度、帧高度、帧率和总帧数。 对于学习OpenCV,你可以按照以下步骤进行: 1. 安装OpenCV库:在开始学习OpenCV之前,您需要从OpenCV官方网站下载和安装OpenCV库。根据您的操作系统和编程语言选择合适的版本。 2. 学习基本概念:熟悉OpenCV的基本概念和术语,例如图像和视频的加载、显示、保存以及常用的图像处理操作,如滤波、边缘检测和特征提取等。 3. 掌握OpenCV函数和类:深入了解OpenCV提供的函数和类,例如cv::Mat用于图像和矩阵操作,cv::VideoCapture用于读取和处理视频,以及cv::imshow和cv::waitKey等用于显示图像的函数。 4. 实践项目:通过完成一些实践项目来应用您所学到的知识。例如,利用OpenCV实现人脸检测、目标追踪、图像识别等。 5. 学习资料和资源:查找和阅读OpenCV的官方文档、教程和示例代码,参与开源社区讨论和交流,加入相关的论坛和邮件列表等。 总结起来,学习OpenCV包括安装OpenCV库、学习基本概念、掌握OpenCV函数和类、实践项目以及查找和阅读相关资料和资源。通过不断实践和学习,您将能够更好地理解和应用OpenCV库来开发图像和视频处理应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值