lt;深度神经网络算法>具体是怎样工作的

深度学习和神经网络的区别是什么 深度学习与神经网络有什么区别
你正在浏览: & >
深度学习和神经网络的区别是什么
深度学习和神经网络的区别是什么
两个概念实际上是互相交的,随后提出多层自动编码器深层结构,例如,卷积神经网络(Convolutional neural networks。基于深信度网(DBN)提出非监督贪心逐层训练算法,为解决深层结构相关的优化难题带来希望。此外Lecun等人提出的卷积神经网络是第一个真正多层结构学习算法,它利用空间相对关系减少参数数目以提高训练性能,简称CNNs)就是一种深度的监督学习下的机器学习模型,而深度置信网(Deep Belief Nets,简称DBNs)就是一种无监督学习下的机器学习模型。深度学习的概念源于人工神经网络的研究。含多隐层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。深度学习的概念由Hinton等人于2006年提出
两个概念实际上是互相交的,随后提出多层自动编码器深层结构,例如,卷积神经网络(Convolutional neural networks。基于深信度网(DBN)提出非监督贪心逐层训练算法,为解决深层结构相关的优化难题带来希望。此外Lecun等人提出的卷积神经网络是第一个真正多层结构学习算法,它利用空间相对关系减少参数数目以提高训练性能,简称CNNs)就是一种深度的监督学习下的机器学习模型,而深度置信网(Deep Belief Nets,简称DBNs)就是一种无监督学习下的机器学习模型。深度学习的概念源于人工神经网络的研究。含多隐层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。深度学习的概念由Hinton等人于2006年提出
输出层。  输入层 - 卷积层 -降维层 -卷积层 - 降维层 -- ,原来多层神经网络做的步骤是.... -- 隐藏层 -输出层  简单来说。其中隐藏层的层数根据需要而定,没有明确的理论推导来说明到底多少层合适。  而深度学习中最著名的卷积神经网络CNN,在原来多层神经网络的基础上,加入了特征学习部分,这部分是模仿人脑对信号处理上的分级的。具体操作就是在原来的全连接的层前面加入了部分连接的卷积层与降维层,而且加入的是一个层级、隐藏层  从广义上说深度学习的网络结构也是多层神经网络的一种。  传统意义上的多层神经网络是只有输入层:特征映射到值。特征是人工挑选。  深度学习做的步骤是 信号-&gt
深度学习与神经网络关系
最近开始学习深度学习,基本上都是zouxy09博主的文...~~~
这两个概念实际上是互相交叉的,例如,卷积神经网络(Convolutional neural netw...~~~
度学习的概念源于人工神经网络的研究。含多隐层的多层感知器就是一种深度学习结构,通过组合低层特征形成更...~~~
哦 明白过来了 BP网络中好多训练函数需要设置,学习速率lp而自适应,应该是那个速率自动调整的,不需...~~~
  机器学习是目前实现人工智能最主要的方式。输入给程序,以及程序自行学习到的规律,就是机器学习算法。...~~~
你可以把深度学习看作是神经网络的进阶版, 一个更复杂庞大的神经网络~~~
吧疃妊~~~
神经网络的学习,也就是训练过程,指的是输入层神经元接收输入信息,传递给中间层神经元,最后传递到输出层...~~~
作者:杨延生 链接:https://www.zhihu/question//...
你可能感兴趣的内容?煤层底板采动导水破坏深度计算的神经网络方法_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
煤层底板采动导水破坏深度计算的神经网络方法
&&水文地质
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢「深度神经网络」(deep neural network)具体是怎样工作的? - 知乎.mht
扫描二维码,下载文件到手机
相关文档推荐
当前文件信息
浏览:433次
下载:51次
您的VIP会员已过期,是否续费?
用户应遵守著作权法,尊重著作权人合法权益,不违法上传、存储并分享他人作品。举报邮箱:
京网文[0号 京ICP证100780号好吧,读了男神哥哥们的博客,自己写不来更好的。
附上链接:
& &&的http://blog.csdn/real_myth/article/details/;
&&笔记整理系列:http://blog.csdn/zouxy09/article/details/8775360&&;(xy)
总结些心得,写一下认识。
1.深度学习的发展
BP浅层神经网络早在20世纪80年代末期就已掀起了基于统计模型的机器学习热潮,只是BP只有一个隐层,人们对于bp没有很完整的理论推导而且调参问题不少,这样深度神经网就被搁置了。相比而言,20世纪90年代,各种各样的浅层机器学习模型相继被提出,例如支撑向量机(SVM,Support
Vector Machines)、 Boosting、最大熵方法(如LR,Logistic Regression)等。这些模型的结构基本上可以看成带有一层隐层节点(如SVM、Boosting),或没有隐层节点(如LR)。这些模型无论是在理论分析还是应用中都获得了巨大的成功。
直到2006年,加拿大多伦多大学教授、机器学习领域的泰斗Geoffrey
Hinton和他的学生RuslanSalakhutdinov在《科学》上发表了一篇文章,开启了深度学习在学术界和工业界的浪潮。这篇文章有两个主要观点:1)多隐层的人工神经网络具有优异的特征学习能力,学习得到的特征对数据有更本质的刻画,从而有利于可视化或分类;2)经网络在训逐层初始化”(layer-wise
pre-training)来有效克服,在这篇文章中,逐层初始化是通过无监督学习实现的。(摘抄自xy哥哥那里,哈)
2012年神经网络又开始崭露头角,那一年Alex
Krizhevskyj在ImageNet竞赛上(ImageNet可以算是竞赛计算机视觉领域一年一度的“奥运会”竞赛)将分类错误记录从26%降低到15%,这在当时是一个相当惊人的进步。从那时起许多公司开始将应用在他们的核心服务上,如Facebook将神经网络应用到他们的自动标注中,Google(谷歌)将其应用到图片搜索里,Amazon(亚马逊)将其应用到产品推荐服务,Pinterest将其应用到主页个性化信息流中,Instagram也将深度学习应用到它们的图像搜索中。
深度学习作为人工智能的一个方向,迅速风靡。
2011 Google Brain(内部共有10亿个节点,人脑中可是有150多亿个神经元)
2012 Google 实验室,百度研究院
2014 Facebook的DeepFace
2015 亚马逊发布了自己的机器学习平台;微软创分布式机器学习工具包
2016 谷歌人工智能算法 AlphaGo (1959年美国的塞缪尔(Samuel)就已经设计了一个下棋程序)
2.深度学习与特征提取
(1)深度学习是用来干啥的,可以理解为自动提取特征。
我理解的特征就是在各种算法中都需要做大量工作来得到训练样本的描述,并将此特征通过函数和层级结构等记录下来,将来进行测试比对。
(2)提取特征也是有故事的,表示最喜欢听故事了,(*^__^*) 嘻嘻……
据说是小猫头颅开了个小孔,然后不断在其眼前闪过不同类型、不同强弱的刺激。然后测试大脑视觉皮层细胞的响应,最后发现只有部分细胞响应。David Hubel 和Torsten Wiesel
发现了一种被称为“方向选择性细胞(Orientation Selective Cell)”的神经元细胞。当瞳孔发现了眼前的物体的边缘,而且这个边缘指向某个方向时,这种神经元细胞就会活跃。
这个启发了深度神经网络,比如我们要识别出图片中的小猫,并不需要像之前的全连接的结构,因为大量图片物体识别起来参数会相当多。我们在第一层卷积层得到的是各物体边缘特征,(接着pooling),第二个卷积层可能就得到边缘的组合或者小猫的部位碎片,...到最后就会得到诸如爪子呀,眼睛之类的高层特征啦。
& & 所谓:仿视觉皮层(多层),局部特征组合与抽象。
高层的特征是低层特征的组合,从低层到高层的特征表示越来越抽象,越来越能表现语义或者意图。
3.CNN之所以能识别图像的直观理解
核心是卷积(滤波器的概念)。
如输入的是一个32×32×3的系列像素值,(不懂参见上一篇哈),滤波器相当于人的眼睛,来提取图像的底层特征,比如滤波器大小是5×5×3的,被这个小眼睛看到的地方称作接受场或者局部感受野,所以我们的这个小眼睛需要不断的移动,对应卷积下图。
这样进行相应卷积运算(点乘再相加)就得到了一个feature map。如你想的那样我们往往需要多个滤波器,来从不同视角看物体,得到多个feature map。那为什么这样就得到物体的底层特征了呢?比如说边缘特征?
滤波器着实神奇,其实你可以想象过滤器是矩阵。都是数字,然后和输入的局部像素值相乘相加得到最终的结果。如果过滤器中大的参数值刚好摆出某一个形状,而物体中刚好也有这样的形状的话,是不是更加强效果啦?看下图就立马明白:
& & & & & & & & & & & & & & & & &
这是一个可以检测曲线的滤波器。突然想起之前学信号老见滤波器却从来不明白其中的道理,这下加深理解了,谢谢博主!
基本上在输入图像中,如果有一个形状是类似于这种滤波器的代表曲线,那么所有的乘积累加在一起会导致较大的值!现在让我们看看当我们移动我们的过滤器时会发生什么。可以看到结果值是0哦,为什么?还不明白么,因为耳朵的边缘和刚刚尾股部曲线太不同了。
这样的多个滤波器就可以在大量数据的训练下得到大量特征了不是。训练就是为了得到合适的滤波器的值,权值偏置等。自动进行特征学习就是这个道理。
4.CNN多层结构及实现技巧
(1)修正线性单元(ReLU)层
在每个卷积层后,习惯在其后马上添加一个非线性层(或激活层)。这一层的目的是将非线性引入系统,基本上是在卷积层进行线性运算(只是元素的乘法和累加)。在过去都是像tanh 或者sigmoid的线性,但研究人员发现ReLU层效果更好,因为网络训练速度能加快很多(因为计算效率)且精度没有显著差异。它也有助于缓解消失的梯度问题,这是因为网络训练较低层的速度非常缓慢,梯度通过不同的层级指数下降。ReLU层的采用的函数f(x)=
max(0,x)所有值的输入量。基本上,这一层将所有的负激活变成了0。这一层提高了模型的非线性特性,且整体网络不影响卷积层的接受场。感兴趣的还可以参看之父Geoffrey
Hinton的论文
(2)卷积和子采样pool过程:卷积过程包括:用一个可训练的滤波器fx去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map了),然后加一个偏置bx,得到卷积层Cx。子采样过程包括:每邻域四个像素求和变为一个像素,然后通过标量Wx+1加权,再增加偏置bx+1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图Sx+1。
pool的作用:首先是参数或权重的量减少了75%,从而降低了计算成本。其次,控制过度拟合。
(3)还有步长stride滤波器移动时候需要,零填充(zero padding)为了卷积之后尺寸不变,降层(Dropout Layers)防止过拟合,网络层网络不太明白(滤波器是1*1*N的卷积层)...这些概念参见的文章。
(4)这个好有用:迁移学习(Transfer Learning):比如利用已经训练好的动物识别的程序与参数(冻结),只改变最后吼类别直接相关的层,拿自己的数据微调,然后效果也不错。区别更多在于高层特征的道理~
5.分类,定位,检测,分割 &,图像级与像素级语义
图像分类任务是将输入图像识别并输入一系列的图像类别的过程,然而当我们将对象定位作为任务时,我们的工作不仅是得到一个分类标签,另外还需要划定一个对象在图像中的范围。
同样还有对象检测(分类与定位结合)任务,需要将图像中所有对象进行图像定位任务。因此,在图像中将会有多个划定范围还有多个分类标签。
最后,还有对象分割任务,对象分割任务指的是输出一个类的标签,以及输入图像中的每一个对象的轮廓。
图像级与像素级语义: 简单理解了一下,像素级分两类:语义级图像分割和边缘检测。主要是语义相同的像素被分割在同一区域。
& &&super pixel:比如识别人像各区域属于人体哪个部位。
本文已收录于以下专栏:
相关文章推荐
Deep Learning论文笔记之(二)Sparse Filtering稀疏滤波http://blog.csdn.net/zouxy09
自己平时看了一...
Deep Learning论文笔记之(五)CNN卷积神经网络代码理解http://blog.csdn.net/zouxy09
自己平时看了一些论文,但老感...
程序员升职加薪指南!还缺一个“证”!
CSDN出品,立即查看!
9.5、Convolutional Neural Networks卷积神经网络
卷积神经网络是人工神经网络的一种,已成为当前语音分析和图像识别领域的研究热点。它的权值共享网络结构使...
Deep Learning(深度学习)学习笔记整理系列
http://blog.csdn.net/zouxy09
作者:Zouxy
version 1.0 201...
Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现http://blog.csdn.net/zouxy09
自己平时看了一些论文,但老...
Deep Learning论文笔记之(三)单层非监督学习网络分析http://blog.csdn.net/zouxy09
自己平时看了一些论文,但老感觉看...
遇到的问题
我在实现过程中犯的第一个错误是没有循序渐进。仗着自己写过一些神经网络的代码以为手到擒来,直接按照LeNet-5的结构写,过于复杂的结构给测试和调试都带来了很大...
自今年七月份以来,一直在实验室负责卷积神经网络(Convolutional Neural Network,CNN),期间配置和使用过theano和cuda-convnet、cuda-convnet2。...
一、卷积神经网络的基本概念
受Hubel和Wiesel对猫视觉皮层电生理研究启发,有人提出卷积神经网络(CNN),Yann Lecun 最早将CNN用于手写数字识别并一直保持了其在...
Deep Learning论文笔记之(一)K-means特征学习http://blog.csdn.net/zouxy09
自己平时看了一些论文,但老感觉看...
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)当前位置: &
5,219 次阅读 -
最近研究了支持向量机(Support Vector Machine,SVM)和人工神经网络(Artifical Neural Network,ANN)等模式识别理论,结合OpenCV的书:《Mastering OpenCV with Practical Computer Vision Projects》,将两种思想运用到车辆的车牌识别算法中。车辆识别结合了多种图像处理技术,如视频监控、图像检测、图像分割和光学字符识别(OCR)等,在道路交通监控中有着重要的作用。以下内容主要包含几个方面:
? 图像预处理(图像分割)
? SVM分类器(对分割图像的分类)
? 图像预处理(图像分割)? SVM分类器(对分割图像的分类)&
? 特征提取
? OCR分类(使用多层感知器Multi-Layer Perceptron,MLP)
? OCR分割? 特征提取? OCR分类(使用多层感知器Multi-Layer Perceptron,MLP)&
一、实验准备
由于图像素材有限,且对于不同国家,车牌的规格与尺寸不尽相同,因此只能选择资料中已有的西班牙车牌进行研究。这里的素材来源于最常见的西班牙车牌(在西班牙,也有多种形状的车牌)。如下图所示,车牌的大小为520mm*110mm,其中左右两组字符由41mm的空间分离,左边包含四个数字,右边包含三个字母,每个字符之间的距离为14mm。所有字符的大小均为45mm*77mm。
参考书籍中给出了一个已经定义好的车牌类Plate,后续的图像处理需要用到,直接使用即可,毕竟研究的重点是后续的处理和模式分类算法:
&span class="hljs-preprocessor"&#ifndef Plate_h&/span&
&span class="hljs-preprocessor"&#define Plate_h&/span&
&span class="hljs-preprocessor"&#include &string.h&&/span&
&span class="hljs-preprocessor"&#include &vector&&/span&
&span class="hljs-preprocessor"&#include &opencv/cv.h&&/span&
&span class="hljs-preprocessor"&#include &opencv/highgui.h&&/span&
&span class="hljs-preprocessor"&#include &opencv/cvaux.h&&/span&
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span&
&span class="hljs-keyword"&class&/span& Plate{
&span class="hljs-keyword"&public&/span&:
Plate(Mat img, Rect pos);
&span class="hljs-built_in"&string&/span& str();
Mat plateI
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&&span class="hljs-keyword"&char&/span&&&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Rect&&/span& charsP
&span class="hljs-preprocessor"&#endif&/span&
12345678910111213141516171819202122232425
&span class="hljs-preprocessor"&#ifndef Plate_h&/span&&span class="hljs-preprocessor"&#define Plate_h&/span&&&span class="hljs-preprocessor"&#include &string.h&&/span&&span class="hljs-preprocessor"&#include &vector&&/span&&&span class="hljs-preprocessor"&#include &opencv/cv.h&&/span&&span class="hljs-preprocessor"&#include &opencv/highgui.h&&/span&&span class="hljs-preprocessor"&#include &opencv/cvaux.h&&/span&&&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& cv;&&span class="hljs-keyword"&class&/span& Plate{&span class="hljs-keyword"&public&/span&:&&&&Plate();&&&&Plate(Mat img, Rect pos);&&&&&span class="hljs-built_in"&string&/span& str();&&&&Rect position;&&&&Mat plateImg;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<&span class="hljs-keyword"&char&/span&>&/span& chars;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Rect>&/span& charsPos;};&&span class="hljs-preprocessor"&#endif&/span&
&span class="hljs-preprocessor"&#include "Plate.h"&/span&
Plate::Plate(){
Plate::Plate(Mat img, Rect pos){
plateImg =
position =
&span class="hljs-built_in"&string&/span& Plate::str(){
&span class="hljs-built_in"&string&/span& result = &span class="hljs-string"&""&/span&;
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&&span class="hljs-keyword"&int&/span&&&/span& orderI
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&&span class="hljs-keyword"&int&/span&&&/span&
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i& charsPos.size(); i++){
orderIndex.push_back(i);
xpositions.push_back(charsPos[i].x);
&span class="hljs-keyword"&float&/span& min = xpositions[&span class="hljs-number"&0&/span&];
&span class="hljs-keyword"&int&/span& minIdx = &span class="hljs-number"&0&/span&;
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i& xpositions.size(); i++){
min = xpositions[i];
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = j&xpositions.size(); j++){
&span class="hljs-keyword"&if&/span& (xpositions[j]&min){
min = xpositions[j];
&span class="hljs-keyword"&int&/span& aux_i = orderIndex[i];
&span class="hljs-keyword"&int&/span& aux_min = orderIndex[minIdx];
orderIndex[i] = aux_
orderIndex[minIdx] = aux_i;
&span class="hljs-keyword"&float&/span& aux_xi = xpositions[i];
&span class="hljs-keyword"&float&/span& aux_xmin = xpositions[minIdx];
xpositions[i] = aux_
xpositions[minIdx] = aux_
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i&orderIndex.size(); i++){
result = result + chars[orderIndex[i]];
&span class="hljs-keyword"&return&/span&
1234567891011121314151617181920212223242526272829303132333435363738394041424344
&span class="hljs-preprocessor"&#include "Plate.h"&/span&&Plate::Plate(){}&Plate::Plate(Mat img, Rect pos){&&&&plateImg = img;&&&&position = pos;}&&span class="hljs-built_in"&string&/span& Plate::str(){&&&&&span class="hljs-built_in"&string&/span& result = &span class="hljs-string"&""&/span&;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<&span class="hljs-keyword"&int&/span&>&/span& orderIndex;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<&span class="hljs-keyword"&int&/span&>&/span& xpositions;&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i< charsPos.size(); i++){&&&&&&&&orderIndex.push_back(i);&&&&&&&&xpositions.push_back(charsPos[i].x);&&&&}&&&&&span class="hljs-keyword"&float&/span& min = xpositions[&span class="hljs-number"&0&/span&];&&&&&span class="hljs-keyword"&int&/span& minIdx = &span class="hljs-number"&0&/span&;&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i< xpositions.size(); i++){&&&&&&&&min = xpositions[i];&&&&&&&&minIdx = i;&&&&&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = i; j<xpositions.size(); j++){&&&&&&&&&&&&&span class="hljs-keyword"&if&/span& (xpositions[j]<min){&&&&&&&&&&&&&&&&min = xpositions[j];&&&&&&&&&&&&&&&&minIdx = j;&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&&span class="hljs-keyword"&int&/span& aux_i = orderIndex[i];&&&&&&&&&span class="hljs-keyword"&int&/span& aux_min = orderIndex[minIdx];&&&&&&&&orderIndex[i] = aux_min;&&&&&&&&orderIndex[minIdx] = aux_i;&&&&&&&&&&span class="hljs-keyword"&float&/span& aux_xi = xpositions[i];&&&&&&&&&span class="hljs-keyword"&float&/span& aux_xmin = xpositions[minIdx];&&&&&&&&xpositions[i] = aux_xmin;&&&&&&&&xpositions[minIdx] = aux_xi;&&&&}&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i<orderIndex.size(); i++){&&&&&&&&result = result + chars[orderIndex[i]];&&&&}&&&&&span class="hljs-keyword"&return&/span& result;}
二、算法流程
正如上面叙述的,车牌识别有两个主要步骤,即检测与识别。其中车牌检测的目标是在图像或视频帧中检测到车牌的位置。在完成这一步后,进行识别部分,这里使用OCR算法来识别车牌上的字符,其中有数字,也包含字母。
三、车牌检测
车牌识别的第一步自然是检测图像或视频帧中的车牌,并去除其他多余的信息,这一部分主要依靠图像分割来完成。而对于图像分割工作主要包含以下步骤:
1.Sobel滤波器;
2.阈值算子;
3.闭形态学算子;
4.一个填充区域掩码;
5.用颜色标记图像中可能检测到的车辆;
6.执行SVM分类器后检测出车牌。
使用边缘检测的原因是一般情况下拍摄到的车牌有大量竖直的边缘,且车牌没有旋转和透视扭曲,通过检测竖直边可以删除图像中多余的区域。在使用Sobel滤波器之前,需要确保图像为灰度图像,否则需要转化;另一个预处理操作是进行适当的高斯滤波,从而消除可能由摄像机或其他环境产生的噪声,这里使用5*5的高斯滤波去噪。
以下是图像分割的源代码,ImageEecognition.h和ImageEecognition.cpp,其中一些主要的函数调用方法已给出,如Sobel函数:
&span class="hljs-preprocessor"&#ifndef ImageEecognition_h&/span&
&span class="hljs-preprocessor"&#define ImageEecognition_h&/span&
&span class="hljs-preprocessor"&#include &string.h&&/span&
&span class="hljs-preprocessor"&#include &vector&&/span&
&span class="hljs-preprocessor"&#include "Plate.h"&/span&
&span class="hljs-preprocessor"&#include &opencv/cv.h&&/span&
&span class="hljs-preprocessor"&#include &opencv/highgui.h&&/span&
&span class="hljs-preprocessor"&#include &opencv/cvaux.h&&/span&
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span&
&span class="hljs-keyword"&class&/span& ImageRecognition{
&span class="hljs-keyword"&public&/span&:
ImageRecognition();
&span class="hljs-built_in"&string&/span&
&span class="hljs-keyword"&void&/span& setFilename(&span class="hljs-built_in"&string&/span& f);
&span class="hljs-keyword"&bool&/span& saveR
&span class="hljs-keyword"&bool&/span& showS
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span& run(Mat input);
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span& segment(Mat input);
&span class="hljs-keyword"&bool&/span& verifySizes(RotatedRect mr);
Mat histeq(Mat in);
&span class="hljs-preprocessor"&#endif&/span&
123456789101112131415161718192021222324252627282930
&span class="hljs-preprocessor"&#ifndef ImageEecognition_h&/span&&span class="hljs-preprocessor"&#define ImageEecognition_h&/span&&&span class="hljs-preprocessor"&#include &string.h&&/span&&span class="hljs-preprocessor"&#include &vector&&/span&&&span class="hljs-preprocessor"&#include "Plate.h"&/span&&&span class="hljs-preprocessor"&#include &opencv/cv.h&&/span&&span class="hljs-preprocessor"&#include &opencv/highgui.h&&/span&&span class="hljs-preprocessor"&#include &opencv/cvaux.h&&/span&&&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& cv;&&span class="hljs-keyword"&class&/span& ImageRecognition{&span class="hljs-keyword"&public&/span&:&&&&ImageRecognition();&&&&&span class="hljs-built_in"&string&/span& filename;&&&&&span class="hljs-keyword"&void&/span& setFilename(&span class="hljs-built_in"&string&/span& f);&&&&&span class="hljs-keyword"&bool&/span& saveRecognition;&&&&&span class="hljs-keyword"&bool&/span& showSteps;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& run(Mat input);&&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& segment(Mat input);&&&&&span class="hljs-keyword"&bool&/span& verifySizes(RotatedRect mr);&&&&Mat histeq(Mat in);};&&span class="hljs-preprocessor"&#endif&/span&
&span class="hljs-preprocessor"&#include "ImageRecognition.h"&/span&
&span class="hljs-keyword"&void&/span& ImageRecognition::setFilename(&span class="hljs-built_in"&string&/span& name) {
filename =
ImageRecognition::ImageRecognition(){
showSteps = &span class="hljs-keyword"&false&/span&;
saveRecognition = &span class="hljs-keyword"&false&/span&;
&span class="hljs-keyword"&bool&/span& ImageRecognition::verifySizes(RotatedRect ROI){
&span class="hljs-comment"&// 以下设置车牌默认参数,用于识别矩形区域内是否为目标车牌&/span&
&span class="hljs-keyword"&float&/span& error = &span class="hljs-number"&0.4&/span&;
&span class="hljs-comment"&// 西班牙车牌宽高比: 520 / 110 = 4.7272&/span&
&span class="hljs-keyword"&float&/span& aspect = &span class="hljs-number"&4.7272&/span&;
&span class="hljs-comment"&// 设定区域面积的最小/最大尺寸,不在此范围内的不被视为车牌&/span&
&span class="hljs-keyword"&int&/span& min = &span class="hljs-number"&15&/span& * aspect * &span class="hljs-number"&15&/span&;
&span class="hljs-comment"&// 15个像素&/span&
&span class="hljs-keyword"&int&/span& max = &span class="hljs-number"&125&/span& * aspect * &span class="hljs-number"&125&/span&;
&span class="hljs-comment"&// 125个像素&/span&
&span class="hljs-keyword"&float&/span& rmin = aspect - aspect*
&span class="hljs-keyword"&float&/span& rmax = aspect + aspect*
&span class="hljs-keyword"&int&/span& area = ROI.size.height * ROI.size.
&span class="hljs-keyword"&float&/span& r = (&span class="hljs-keyword"&float&/span&)ROI.size.width / (&span class="hljs-keyword"&float&/span&)ROI.size.
&span class="hljs-keyword"&if&/span& (r&&span class="hljs-number"&1&/span&)
r = (&span class="hljs-keyword"&float&/span&)ROI.size.height / (&span class="hljs-keyword"&float&/span&)ROI.size.
&span class="hljs-comment"&// 判断是否符合以上参数&/span&
&span class="hljs-keyword"&if&/span& ((area & min || area & max) || (r & rmin || r & rmax))
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&false&/span&;
&span class="hljs-keyword"&else&/span&
&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&true&/span&;
&span class="hljs-comment"&// 对图像进行直方图均衡处理,调整亮度&/span&
Mat ImageRecognition::histeq(Mat ima)
Mat imt(ima.size(), ima.type());
&span class="hljs-comment"&// 若输入图像为彩色,需要在HSV空间中做直方图均衡处理&/span&
&span class="hljs-comment"&// 再转换回RGB格式&/span&
&span class="hljs-keyword"&if&/span& (ima.channels() == &span class="hljs-number"&3&/span&)
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Mat&&/span& hsvS
cvtColor(ima, hsv, CV_BGR2HSV);
split(hsv, hsvSplit);
equalizeHist(hsvSplit[&span class="hljs-number"&2&/span&], hsvSplit[&span class="hljs-number"&2&/span&]);
merge(hsvSplit, hsv);
cvtColor(hsv, imt, CV_HSV2BGR);
&span class="hljs-comment"&// 若输入图像为灰度图,直接做直方图均衡处理&/span&
&span class="hljs-keyword"&else&/span& &span class="hljs-keyword"&if&/span& (ima.channels() == &span class="hljs-number"&1&/span&){
equalizeHist(ima, imt);
&span class="hljs-keyword"&return&/span&
&span class="hljs-comment"&// 图像分割函数&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span& ImageRecognition::segment(Mat input)
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span&
&span class="hljs-comment"&//n图像转换为灰度图&/span&
cvtColor(input, grayImage, CV_BGR2GRAY);
blur(grayImage, grayImage, Size(&span class="hljs-number"&5&/span&, &span class="hljs-number"&5&/span&));
&span class="hljs-comment"&// 对图像进行滤波,去除噪声&/span&
&span class="hljs-comment"&// 通常车牌拥有显著的边缘特征,这里使用sobel算子检测边缘&/span&
Mat sobelI
Sobel(grayImage,
&span class="hljs-comment"&// 输入图像&/span&
sobelImage,
&span class="hljs-comment"&// 输出图像&/span&
&span class="hljs-comment"&//输出图像的深度&/span&
&span class="hljs-number"&1&/span&,
&span class="hljs-comment"&// x方向上的差分阶数&/span&
&span class="hljs-number"&0&/span&,
&span class="hljs-comment"&// y方向上的差分阶数&/span&
&span class="hljs-number"&3&/span&,
&span class="hljs-comment"&// 扩展Sobel核的大小,必须是1,3,5或7&/span&
&span class="hljs-number"&1&/span&,
&span class="hljs-comment"&// 计算导数值时可选的缩放因子,默认值是1&/span&
&span class="hljs-number"&0&/span&,
&span class="hljs-comment"&// 表示在结果存入目标图之前可选的delta值,默认值为0&/span&
BORDER_DEFAULT); &span class="hljs-comment"&// 边界模式,默认值为BORDER_DEFAULT&/span&
&span class="hljs-keyword"&if&/span& (showSteps)
imshow(&span class="hljs-string"&"Sobel"&/span&, sobelImage);
&span class="hljs-comment"&// 阈值分割得到二值图像,所采用的阈值由Otsu算法得到&/span&
Mat thresholdI
&span class="hljs-comment"&// 输入一幅8位图像,自动得到优化的阈值&/span&
threshold(sobelImage, thresholdImage, &span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, CV_THRESH_OTSU + CV_THRESH_BINARY);
&span class="hljs-keyword"&if&/span& (showSteps)
imshow(&span class="hljs-string"&"Threshold Image"&/span&, thresholdImage);
&span class="hljs-comment"&// 形态学之闭运算&/span&
&span class="hljs-comment"&// 定义一个结构元素structuringElement,维度为17*3&/span&
Mat structuringElement = getStructuringElement(MORPH_RECT, Size(&span class="hljs-number"&17&/span&, &span class="hljs-number"&3&/span&));
&span class="hljs-comment"&// 使用morphologyEx函数得到包含车牌的区域(但不包含车牌号)&/span&
morphologyEx(thresholdImage, thresholdImage, CV_MOP_CLOSE, structuringElement);
&span class="hljs-keyword"&if&/span& (showSteps)
imshow(&span class="hljs-string"&"Close"&/span&, thresholdImage);
&span class="hljs-comment"&// 找到可能的车牌的轮廓&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&& &span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&& Point&&/span& &&/span&
findContours(thresholdImage,
contours, &span class="hljs-comment"&// 检测的轮廓数组,每一个轮廓用一个point类型的vector表示&/span&
CV_RETR_EXTERNAL, &span class="hljs-comment"&// 表示只检测外轮廓&/span&
CV_CHAIN_APPROX_NONE); &span class="hljs-comment"&// 轮廓的近似办法,这里存储所有的轮廓点&/span&
&span class="hljs-comment"&// 对每个轮廓检测和提取最小区域的有界矩形区域&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Point&&/span& &&/span&::iterator itc = contours.begin();
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&RotatedRect&&/span&
&span class="hljs-comment"&// 若没有达到设定的宽高比要求,移去该区域&/span&
&span class="hljs-keyword"&while&/span& (itc != contours.end())
RotatedRect ROI = minAreaRect(Mat(*itc));
&span class="hljs-keyword"&if&/span& (!verifySizes(ROI)){
itc = contours.erase(itc);
&span class="hljs-keyword"&else&/span&{
rects.push_back(ROI);
&span class="hljs-comment"&// 在白色的图上画出蓝色的轮廓&/span&
input.copyTo(result);
cv::drawContours(result,
-&span class="hljs-number"&1&/span&,
&span class="hljs-comment"&// 所有的轮廓都画出&/span&
cv::Scalar(&span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&), &span class="hljs-comment"&// 颜色&/span&
&span class="hljs-number"&1&/span&);
&span class="hljs-comment"&// 线粗&/span&
&span class="hljs-comment"&// 使用漫水填充算法裁剪车牌获取更清晰的轮廓&/span&
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i& rects.size(); i++){
circle(result, rects[i].center, &span class="hljs-number"&3&/span&, Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&), -&span class="hljs-number"&1&/span&);
&span class="hljs-comment"&// 得到宽度和高度中较小的值,得到车牌的最小尺寸&/span&
&span class="hljs-keyword"&float&/span& minSize = (rects[i].size.width & rects[i].size.height) ? rects[i].size.width : rects[i].size.
minSize = minSize - minSize * &span class="hljs-number"&0.5&/span&;
&span class="hljs-comment"&// 在块中心附近产生若干个随机种子&/span&
srand(time(NULL));
&span class="hljs-comment"&// 初始化漫水填充算法的参数&/span&
mask.create(input.rows + &span class="hljs-number"&2&/span&, input.cols + &span class="hljs-number"&2&/span&, CV_8UC1);
mask = Scalar::all(&span class="hljs-number"&0&/span&);
&span class="hljs-comment"&// loDiff表示当前观察像素值与其部件邻域像素值或者待加入&/span&
&span class="hljs-comment"&// 该部件的种子像素之间的亮度或颜色之负差的最大值&/span&
&span class="hljs-keyword"&int&/span& loDiff = &span class="hljs-number"&30&/span&;
&span class="hljs-comment"&// upDiff表示当前观察像素值与其部件邻域像素值或者待加入&/span&
&span class="hljs-comment"&// 该部件的种子像素之间的亮度或颜色之正差的最大值&/span&
&span class="hljs-keyword"&int&/span& upDiff = &span class="hljs-number"&30&/span&;
&span class="hljs-keyword"&int&/span& connectivity = &span class="hljs-number"&4&/span&; &span class="hljs-comment"&// 用于控制算法的连通性,可取4或者8&/span&
&span class="hljs-keyword"&int&/span& newMaskVal = &span class="hljs-number"&255&/span&;
&span class="hljs-keyword"&int&/span& NumSeeds = &span class="hljs-number"&10&/span&;
&span class="hljs-comment"&// 操作标志符分为几个部分&/span&
&span class="hljs-keyword"&int&/span& flags = connectivity + &span class="hljs-comment"&// 用于控制算法的连通性,可取4或者8&/span&
(newMaskVal && &span class="hljs-number"&8&/span&) +
CV_FLOODFILL_FIXED_RANGE + &span class="hljs-comment"&// 设置该标识符,会考虑当前像素与种子像素之间的差&/span&
CV_FLOODFILL_MASK_ONLY; &span class="hljs-comment"&// 函数不会去填充改变原始图像, 而是去填充掩模图像&/span&
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = &span class="hljs-number"&0&/span&; j & NumS j++){
seed.x = rects[i].center.x + rand() % (&span class="hljs-keyword"&int&/span&)minSize - (minSize / &span class="hljs-number"&2&/span&);
seed.y = rects[i].center.y + rand() % (&span class="hljs-keyword"&int&/span&)minSize - (minSize / &span class="hljs-number"&2&/span&);
circle(result, seed, &span class="hljs-number"&1&/span&, Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, &span class="hljs-number"&255&/span&), -&span class="hljs-number"&1&/span&);
&span class="hljs-comment"&// 运用填充算法,参数已设置&/span&
&span class="hljs-keyword"&int&/span& area = floodFill(input,
Scalar(&span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&),
Scalar(loDiff, loDiff, loDiff),
Scalar(upDiff, upDiff, upDiff),
&span class="hljs-keyword"&if&/span& (showSteps)
imshow(&span class="hljs-string"&"MASK"&/span&, mask);
&span class="hljs-comment"&// 得到裁剪掩码后,检查其有效尺寸&/span&
&span class="hljs-comment"&// 对于每个掩码的白色像素,先得到其位置&/span&
&span class="hljs-comment"&// 再使用minAreaRect函数获取最接近的裁剪区域&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Point&&/span& pointsI
Mat_&uchar&::iterator itMask = mask.begin&uchar&();
Mat_&uchar&::iterator end = mask.end&uchar&();
&span class="hljs-keyword"&for&/span& (; itMask != ++itMask)
&span class="hljs-keyword"&if&/span& (*itMask == &span class="hljs-number"&255&/span&)
pointsInterest.push_back(itMask.pos());
RotatedRect minRect = minAreaRect(pointsInterest);
&span class="hljs-keyword"&if&/span& (verifySizes(minRect)){
&span class="hljs-comment"&// 旋转矩形图&/span&
Point2f rect_points[&span class="hljs-number"&4&/span&]; minRect.points(rect_points);
&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = &span class="hljs-number"&0&/span&; j & &span class="hljs-number"&4&/span&; j++)
line(result, rect_points[j], rect_points[(j + &span class="hljs-number"&1&/span&) % &span class="hljs-number"&4&/span&], Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&), &span class="hljs-number"&1&/span&, &span class="hljs-number"&8&/span&);
&span class="hljs-comment"&// 得到旋转图像区域的矩阵&/span&
&span class="hljs-keyword"&float&/span& r = (&span class="hljs-keyword"&float&/span&)minRect.size.width / (&span class="hljs-keyword"&float&/span&)minRect.size.
&span class="hljs-keyword"&float&/span& angle = minRect.
&span class="hljs-keyword"&if&/span& (r&&span class="hljs-number"&1&/span&)
angle = &span class="hljs-number"&90&/span& +
Mat rotmat = getRotationMatrix2D(minRect.center, angle, &span class="hljs-number"&1&/span&);
&span class="hljs-comment"&// 通过仿射变换旋转输入的图像&/span&
warpAffine(input, img_rotated, rotmat, input.size(), CV_INTER_CUBIC);
&span class="hljs-comment"&// 最后裁剪图像&/span&
Size rect_size = minRect.
&span class="hljs-keyword"&if&/span& (r & &span class="hljs-number"&1&/span&)
swap(rect_size.width, rect_size.height);
getRectSubPix(img_rotated, rect_size, minRect.center, img_crop);
Mat resultR
resultResized.create(&span class="hljs-number"&33&/span&, &span class="hljs-number"&144&/span&, CV_8UC3);
resize(img_crop, resultResized, resultResized.size(), &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&, INTER_CUBIC);
&span class="hljs-comment"&// 为了消除光照影响,对裁剪图像使用直方图均衡化处理&/span&
cvtColor(resultResized, grayResult, CV_BGR2GRAY);
blur(grayResult, grayResult, Size(&span class="hljs-number"&3&/span&, &span class="hljs-number"&3&/span&));
grayResult = histeq(grayResult);
&span class="hljs-keyword"&if&/span& (saveRecognition){
&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);
ss && &span class="hljs-string"&"tmp/"&/span& && filename && &span class="hljs-string"&"_"&/span& && i && &span class="hljs-string"&".jpg"&/span&;
imwrite(ss.str(), grayResult);
output.push_back(Plate(grayResult, minRect.boundingRect()));
&span class="hljs-keyword"&if&/span& (showSteps)
imshow(&span class="hljs-string"&"Contours"&/span&, result);
&span class="hljs-keyword"&return&/span&
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span& ImageRecognition::run(Mat input)
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&Plate&&/span& tmp = segment(input);
&span class="hljs-comment"&// 返回检测结果&/span&
&span class="hljs-keyword"&return&/span&
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
&span class="hljs-preprocessor"&#include "ImageRecognition.h"&/span&&&span class="hljs-keyword"&void&/span& ImageRecognition::setFilename(&span class="hljs-built_in"&string&/span& name) {&&&&filename = name;}&ImageRecognition::ImageRecognition(){&&&&showSteps = &span class="hljs-keyword"&false&/span&;&&&&saveRecognition = &span class="hljs-keyword"&false&/span&;}&&span class="hljs-keyword"&bool&/span& ImageRecognition::verifySizes(RotatedRect ROI){&&&&&span class="hljs-comment"&// 以下设置车牌默认参数,用于识别矩形区域内是否为目标车牌&/span&&&&&&span class="hljs-keyword"&float&/span& error = &span class="hljs-number"&0.4&/span&;&&&&&span class="hljs-comment"&// 西班牙车牌宽高比: 520 / 110 = 4.7272&/span&&&&&&span class="hljs-keyword"&float&/span& aspect = &span class="hljs-number"&4.7272&/span&;&&&&&span class="hljs-comment"&// 设定区域面积的最小/最大尺寸,不在此范围内的不被视为车牌&/span&&&&&&span class="hljs-keyword"&int&/span& min = &span class="hljs-number"&15&/span& * aspect * &span class="hljs-number"&15&/span&;&&&&&span class="hljs-comment"&// 15个像素&/span&&&&&&span class="hljs-keyword"&int&/span& max = &span class="hljs-number"&125&/span& * aspect * &span class="hljs-number"&125&/span&;&&&span class="hljs-comment"&// 125个像素&/span&&&&&&span class="hljs-keyword"&float&/span& rmin = aspect - aspect*error;&&&&&span class="hljs-keyword"&float&/span& rmax = aspect + aspect*error;&&&&&&span class="hljs-keyword"&int&/span& area = ROI.size.height * ROI.size.width;&&&&&span class="hljs-keyword"&float&/span& r = (&span class="hljs-keyword"&float&/span&)ROI.size.width / (&span class="hljs-keyword"&float&/span&)ROI.size.height;&&&&&span class="hljs-keyword"&if&/span& (r<&span class="hljs-number"&1&/span&)&&&&&&&&r = (&span class="hljs-keyword"&float&/span&)ROI.size.height / (&span class="hljs-keyword"&float&/span&)ROI.size.width;&&&&&&span class="hljs-comment"&// 判断是否符合以上参数&/span&&&&&&span class="hljs-keyword"&if&/span& ((area < min || area > max) || (r < rmin || r > rmax))&&&&&&&&&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&false&/span&;&&&&&span class="hljs-keyword"&else&/span&&&&&&&&&&span class="hljs-keyword"&return&/span& &span class="hljs-keyword"&true&/span&;}&&span class="hljs-comment"&// 对图像进行直方图均衡处理,调整亮度&/span&Mat ImageRecognition::histeq(Mat ima){&&&&Mat imt(ima.size(), ima.type());&&&&&span class="hljs-comment"&// 若输入图像为彩色,需要在HSV空间中做直方图均衡处理&/span&&&&&&span class="hljs-comment"&// 再转换回RGB格式&/span&&&&&&span class="hljs-keyword"&if&/span& (ima.channels() == &span class="hljs-number"&3&/span&)&&&&{&&&&&&&&Mat hsv;&&&&&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Mat>&/span& hsvSplit;&&&&&&&&cvtColor(ima, hsv, CV_BGR2HSV);&&&&&&&&split(hsv, hsvSplit);&&&&&&&&equalizeHist(hsvSplit[&span class="hljs-number"&2&/span&], hsvSplit[&span class="hljs-number"&2&/span&]);&&&&&&&&merge(hsvSplit, hsv);&&&&&&&&cvtColor(hsv, imt, CV_HSV2BGR);&&&&}&&&&&span class="hljs-comment"&// 若输入图像为灰度图,直接做直方图均衡处理&/span&&&&&&span class="hljs-keyword"&else&/span& &span class="hljs-keyword"&if&/span& (ima.channels() == &span class="hljs-number"&1&/span&){&&&&&&&&equalizeHist(ima, imt);&&&&}&&&&&span class="hljs-keyword"&return&/span& imt;}&&span class="hljs-comment"&// 图像分割函数&/span&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& ImageRecognition::segment(Mat input){&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& output;&&&&&&span class="hljs-comment"&//n图像转换为灰度图&/span&&&&&Mat grayImage;&&&&cvtColor(input, grayImage, CV_BGR2GRAY);&&&&blur(grayImage, grayImage, Size(&span class="hljs-number"&5&/span&, &span class="hljs-number"&5&/span&));&&&span class="hljs-comment"&// 对图像进行滤波,去除噪声&/span&&&&&&&span class="hljs-comment"&// 通常车牌拥有显著的边缘特征,这里使用sobel算子检测边缘&/span&&&&&Mat sobelImage;&&&&Sobel(grayImage,&&&&&& &span class="hljs-comment"&// 输入图像&/span&&&&&&&&&&&sobelImage,&&&&&&&span class="hljs-comment"&// 输出图像&/span&&&&&&&&&&&CV_8U,&&&&&&&&&& &span class="hljs-comment"&//输出图像的深度&/span&&&&&&&&&&&&span class="hljs-number"&1&/span&,&&&&&&&&&&&&&& &span class="hljs-comment"&// x方向上的差分阶数&/span&&&&&&&&&&&&span class="hljs-number"&0&/span&,&&&&&&&&&&&&&& &span class="hljs-comment"&// y方向上的差分阶数&/span&&&&&&&&&&&&span class="hljs-number"&3&/span&,&&&&&&&&&&&&&& &span class="hljs-comment"&// 扩展Sobel核的大小,必须是1,3,5或7&/span&&&&&&&&&&&&span class="hljs-number"&1&/span&,&&&&&&&&&&&&&& &span class="hljs-comment"&// 计算导数值时可选的缩放因子,默认值是1&/span&&&&&&&&&&&&span class="hljs-number"&0&/span&,&&&&&&&&&&&&&& &span class="hljs-comment"&// 表示在结果存入目标图之前可选的delta值,默认值为0&/span&&&&&&&&&&&BORDER_DEFAULT); &span class="hljs-comment"&// 边界模式,默认值为BORDER_DEFAULT&/span&&&&&&span class="hljs-keyword"&if&/span& (showSteps)&&&&&&&&imshow(&span class="hljs-string"&"Sobel"&/span&, sobelImage);&&&&&&span class="hljs-comment"&// 阈值分割得到二值图像,所采用的阈值由Otsu算法得到&/span&&&&&Mat thresholdImage;&&&&&span class="hljs-comment"&// 输入一幅8位图像,自动得到优化的阈值&/span&&&&&threshold(sobelImage, thresholdImage, &span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, CV_THRESH_OTSU + CV_THRESH_BINARY);&&&&&span class="hljs-keyword"&if&/span& (showSteps)&&&&&&&&imshow(&span class="hljs-string"&"Threshold Image"&/span&, thresholdImage);&&&&&&span class="hljs-comment"&// 形态学之闭运算&/span&&&&&&span class="hljs-comment"&// 定义一个结构元素structuringElement,维度为17*3&/span&&&&&Mat structuringElement = getStructuringElement(MORPH_RECT, Size(&span class="hljs-number"&17&/span&, &span class="hljs-number"&3&/span&));&&&&&span class="hljs-comment"&// 使用morphologyEx函数得到包含车牌的区域(但不包含车牌号)&/span&&&&&morphologyEx(thresholdImage, thresholdImage, CV_MOP_CLOSE, structuringElement);&&&&&span class="hljs-keyword"&if&/span& (showSteps)&&&&&&&&imshow(&span class="hljs-string"&"Close"&/span&, thresholdImage);&&&&&&span class="hljs-comment"&// 找到可能的车牌的轮廓&/span&&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&< &span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&< Point>&/span& >&/span& contours;&&&&findContours(thresholdImage,&&&&&&&&&&&&&&&& contours, &span class="hljs-comment"&// 检测的轮廓数组,每一个轮廓用一个point类型的vector表示&/span&&&&&&&&&&&&&&&&& CV_RETR_EXTERNAL, &span class="hljs-comment"&// 表示只检测外轮廓&/span&&&&&&&&&&&&&&&&& CV_CHAIN_APPROX_NONE); &span class="hljs-comment"&// 轮廓的近似办法,这里存储所有的轮廓点&/span&&&&&&&span class="hljs-comment"&// 对每个轮廓检测和提取最小区域的有界矩形区域&/span&&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Point>&/span& >&/span&::iterator itc = contours.begin();&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<RotatedRect>&/span& rects;&&&&&span class="hljs-comment"&// 若没有达到设定的宽高比要求,移去该区域&/span&&&&&&span class="hljs-keyword"&while&/span& (itc != contours.end()) &&&&{&&&&&&&&RotatedRect ROI = minAreaRect(Mat(*itc));&&&&&&&&&span class="hljs-keyword"&if&/span& (!verifySizes(ROI)){&&&&&&&&&&&&itc = contours.erase(itc);&&&&&&&&}&&&&&&&&&span class="hljs-keyword"&else&/span&{&&&&&&&&&&&&++itc;&&&&&&&&&&&&rects.push_back(ROI);&&&&&&&&}&&&&}&&&&&&span class="hljs-comment"&// 在白色的图上画出蓝色的轮廓&/span&&&&&cv::Mat result;&&&&input.copyTo(result);&&&&cv::drawContours(result,&&&&&&&&&&&&&&&&&&&& contours,&&&&&&&&&&&&&&&&&&&& -&span class="hljs-number"&1&/span&,&&&&&&&&&&&&&&&&&&&&&span class="hljs-comment"&// 所有的轮廓都画出&/span&&&&&&&&&&&&&&&&&&&&& cv::Scalar(&span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&), &span class="hljs-comment"&// 颜色&/span&&&&&&&&&&&&&&&&&&&&& &span class="hljs-number"&1&/span&);&&&&&&&&&&&&&&&&&&&&&span class="hljs-comment"&// 线粗&/span&&&&&&&span class="hljs-comment"&// 使用漫水填充算法裁剪车牌获取更清晰的轮廓&/span&&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& i = &span class="hljs-number"&0&/span&; i< rects.size(); i++){&&&&&&&&&circle(result, rects[i].center, &span class="hljs-number"&3&/span&, Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&), -&span class="hljs-number"&1&/span&);&&&&&&&&&span class="hljs-comment"&// 得到宽度和高度中较小的值,得到车牌的最小尺寸&/span&&&&&&&&&&span class="hljs-keyword"&float&/span& minSize = (rects[i].size.width < rects[i].size.height) ? rects[i].size.width : rects[i].size.height;&&&&&&&&minSize = minSize - minSize * &span class="hljs-number"&0.5&/span&;&&&&&&&&&span class="hljs-comment"&// 在块中心附近产生若干个随机种子&/span&&&&&&&&&srand(time(NULL));&&&&&&&&&span class="hljs-comment"&// 初始化漫水填充算法的参数&/span&&&&&&&&&Mat mask;&&&&&&&&mask.create(input.rows + &span class="hljs-number"&2&/span&, input.cols + &span class="hljs-number"&2&/span&, CV_8UC1);&&&&&&&&mask = Scalar::all(&span class="hljs-number"&0&/span&);&&&&&&&&&span class="hljs-comment"&// loDiff表示当前观察像素值与其部件邻域像素值或者待加入&/span&&&&&&&&&&span class="hljs-comment"&// 该部件的种子像素之间的亮度或颜色之负差的最大值&/span&&&&&&&&&&span class="hljs-keyword"&int&/span& loDiff = &span class="hljs-number"&30&/span&;&&&&&&&&&span class="hljs-comment"&// upDiff表示当前观察像素值与其部件邻域像素值或者待加入&/span&&&&&&&&&&span class="hljs-comment"&// 该部件的种子像素之间的亮度或颜色之正差的最大值&/span&&&&&&&&&&span class="hljs-keyword"&int&/span& upDiff = &span class="hljs-number"&30&/span&;&&&&&&&&&span class="hljs-keyword"&int&/span& connectivity = &span class="hljs-number"&4&/span&; &span class="hljs-comment"&// 用于控制算法的连通性,可取4或者8&/span&&&&&&&&&&span class="hljs-keyword"&int&/span& newMaskVal = &span class="hljs-number"&255&/span&;&&&&&&&&&span class="hljs-keyword"&int&/span& NumSeeds = &span class="hljs-number"&10&/span&;&&&&&&&&Rect ccomp;&&&&&&&&&span class="hljs-comment"&// 操作标志符分为几个部分&/span&&&&&&&&&&span class="hljs-keyword"&int&/span& flags = connectivity + &span class="hljs-comment"&// 用于控制算法的连通性,可取4或者8&/span&&&&&&&&&&&&&&&&&&&&&(newMaskVal << &span class="hljs-number"&8&/span&) +&&&&&&&&&&&&&&&&&&&&CV_FLOODFILL_FIXED_RANGE + &span class="hljs-comment"&// 设置该标识符,会考虑当前像素与种子像素之间的差&/span&&&&&&&&&&&&&&&&&&&&&CV_FLOODFILL_MASK_ONLY; &span class="hljs-comment"&// 函数不会去填充改变原始图像, 而是去填充掩模图像&/span&&&&&&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = &span class="hljs-number"&0&/span&; j < NumSeeds; j++){&&&&&&&&&&&&Point seed;&&&&&&&&&&&&seed.x = rects[i].center.x + rand() % (&span class="hljs-keyword"&int&/span&)minSize - (minSize / &span class="hljs-number"&2&/span&);&&&&&&&&&&&&seed.y = rects[i].center.y + rand() % (&span class="hljs-keyword"&int&/span&)minSize - (minSize / &span class="hljs-number"&2&/span&);&&&&&&&&&&&&circle(result, seed, &span class="hljs-number"&1&/span&, Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&, &span class="hljs-number"&255&/span&), -&span class="hljs-number"&1&/span&);&&&&&&&&&&&&&span class="hljs-comment"&// 运用填充算法,参数已设置&/span&&&&&&&&&&&&&&span class="hljs-keyword"&int&/span& area = floodFill(input,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mask,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& seed,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Scalar(&span class="hljs-number"&255&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &ccomp,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Scalar(loDiff, loDiff, loDiff),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Scalar(upDiff, upDiff, upDiff),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& flags);&&&&&&&&}&&&&&&&&&span class="hljs-keyword"&if&/span& (showSteps)&&&&&&&&&&&&imshow(&span class="hljs-string"&"MASK"&/span&, mask);&&&&&&&&&&span class="hljs-comment"&// 得到裁剪掩码后,检查其有效尺寸&/span&&&&&&&&&&span class="hljs-comment"&// 对于每个掩码的白色像素,先得到其位置&/span&&&&&&&&&&span class="hljs-comment"&// 再使用minAreaRect函数获取最接近的裁剪区域&/span&&&&&&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Point>&/span& pointsInterest;&&&&&&&&Mat_<uchar>::iterator itMask = mask.begin<uchar>();&&&&&&&&Mat_<uchar>::iterator end = mask.end<uchar>();&&&&&&&&&span class="hljs-keyword"&for&/span& (; itMask != end; ++itMask)&&&&&&&&&&&&&span class="hljs-keyword"&if&/span& (*itMask == &span class="hljs-number"&255&/span&)&&&&&&&&&&&&&&&&pointsInterest.push_back(itMask.pos());&&&&&&&&&RotatedRect minRect = minAreaRect(pointsInterest);&&&&&&&&&&span class="hljs-keyword"&if&/span& (verifySizes(minRect)){&&&&&&&&&&&&&span class="hljs-comment"&// 旋转矩形图&/span&&&&&&&&&&&&&Point2f rect_points[&span class="hljs-number"&4&/span&]; minRect.points(rect_points);&&&&&&&&&&&&&span class="hljs-keyword"&for&/span& (&span class="hljs-keyword"&int&/span& j = &span class="hljs-number"&0&/span&; j < &span class="hljs-number"&4&/span&; j++)&&&&&&&&&&&&&&&&line(result, rect_points[j], rect_points[(j + &span class="hljs-number"&1&/span&) % &span class="hljs-number"&4&/span&], Scalar(&span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&, &span class="hljs-number"&255&/span&), &span class="hljs-number"&1&/span&, &span class="hljs-number"&8&/span&);&&&&&&&&&&&&&&span class="hljs-comment"&// 得到旋转图像区域的矩阵&/span&&&&&&&&&&&&&&span class="hljs-keyword"&float&/span& r = (&span class="hljs-keyword"&float&/span&)minRect.size.width / (&span class="hljs-keyword"&float&/span&)minRect.size.height;&&&&&&&&&&&&&span class="hljs-keyword"&float&/span& angle = minRect.angle;&&&&&&&&&&&&&span class="hljs-keyword"&if&/span& (r<&span class="hljs-number"&1&/span&)&&&&&&&&&&&&&&&&angle = &span class="hljs-number"&90&/span& + angle;&&&&&&&&&&&&Mat rotmat = getRotationMatrix2D(minRect.center, angle, &span class="hljs-number"&1&/span&);&&&&&&&&&&&&&&span class="hljs-comment"&// 通过仿射变换旋转输入的图像&/span&&&&&&&&&&&&&Mat img_rotated;&&&&&&&&&&&&warpAffine(input, img_rotated, rotmat, input.size(), CV_INTER_CUBIC);&&&&&&&&&&&&&&span class="hljs-comment"&// 最后裁剪图像&/span&&&&&&&&&&&&&Size rect_size = minRect.size;&&&&&&&&&&&&&span class="hljs-keyword"&if&/span& (r < &span class="hljs-number"&1&/span&)&&&&&&&&&&&&&&&&swap(rect_size.width, rect_size.height);&&&&&&&&&&&&Mat img_crop;&&&&&&&&&&&&getRectSubPix(img_rotated, rect_size, minRect.center, img_crop);&&&&&&&&&&&&&Mat resultResized;&&&&&&&&&&&&resultResized.create(&span class="hljs-number"&33&/span&, &span class="hljs-number"&144&/span&, CV_8UC3);&&&&&&&&&&&&resize(img_crop, resultResized, resultResized.size(), &span class="hljs-number"&0&/span&, &span class="hljs-number"&0&/span&, INTER_CUBIC);&&&&&&&&&&&&&span class="hljs-comment"&// 为了消除光照影响,对裁剪图像使用直方图均衡化处理&/span&&&&&&&&&&&&&Mat grayResult;&&&&&&&&&&&&cvtColor(resultResized, grayResult, CV_BGR2GRAY);&&&&&&&&&&&&blur(grayResult, grayResult, Size(&span class="hljs-number"&3&/span&, &span class="hljs-number"&3&/span&));&&&&&&&&&&&&grayResult = histeq(grayResult);&&&&&&&&&&&&&span class="hljs-keyword"&if&/span& (saveRecognition){&&&&&&&&&&&&&&&&&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);&&&&&&&&&&&&&&&&ss << &span class="hljs-string"&"tmp/"&/span& << filename << &span class="hljs-string"&"_"&/span& << i << &span class="hljs-string"&".jpg"&/span&;&&&&&&&&&&&&&&&&imwrite(ss.str(), grayResult);&&&&&&&&&&&&}&&&&&&&&&&&&output.push_back(Plate(grayResult, minRect.boundingRect()));&&&&&&&&}&&&&}&&&&&span class="hljs-keyword"&if&/span& (showSteps)&&&&&&&&imshow(&span class="hljs-string"&"Contours"&/span&, result);&&&&&&span class="hljs-keyword"&return&/span& output;}&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& ImageRecognition::run(Mat input){&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<Plate>&/span& tmp = segment(input);&&&&&span class="hljs-comment"&// 返回检测结果&/span&&&&&&span class="hljs-keyword"&return&/span& tmp;}
对分割完的图像使用SVM分类,并由代码自动创建正负样本。这里需要了解一下SVM(Support Vector Machine),即支持向量机算法,这是一种有监督学习方法。OpenCV开发SVM算法是基于LibSVM软件包开发的,LibSVM软件包是台湾大学林智仁开发设计的一个简单、易于使用和快速有效的SVM模式识别与回归的软件包。用OpenCV使用SVM算法的大概流程如下:
1)设置训练样本集,一般需要两组数据,一组是数据的类别,一组是数据的向量信息。
2)设置SVM参数。利用CvSVMParams类实现类内的成员变量svm_type表示SVM类型:
CvSVM&span class="hljs-tag"&::C_SVC&/span&
&span class="hljs-comment"&// C-SVC&/span&
CvSVM&span class="hljs-tag"&::NU_SVC&/span&
&span class="hljs-comment"&// v-SVC&/span&
CvSVM&span class="hljs-tag"&::ONE_CLASS&/span& &span class="hljs-comment"&// 一类SVM&/span&
CvSVM&span class="hljs-tag"&::EPS_SVR&/span&
&span class="hljs-comment"&// e-SVR&/span&
CvSVM&span class="hljs-tag"&::NU_SVR&/span&
&span class="hljs-comment"&// v-SVR&/span&
CvSVM&span class="hljs-tag"&::C_SVC&/span&&&&& &span class="hljs-comment"&// C-SVC&/span&CvSVM&span class="hljs-tag"&::NU_SVC&/span&&&&&&span class="hljs-comment"&// v-SVC&/span&CvSVM&span class="hljs-tag"&::ONE_CLASS&/span& &span class="hljs-comment"&// 一类SVM&/span&CvSVM&span class="hljs-tag"&::EPS_SVR&/span&&& &span class="hljs-comment"&// e-SVR&/span&CvSVM&span class="hljs-tag"&::NU_SVR&/span&&&&&&span class="hljs-comment"&// v-SVR&/span&
成员变量kernel_type表示核函数的类型:
CvSVM::LINEAR 线性 &span class="hljs-string"&u'v
CvSVM::POLY 多项式:(r*u'&/span&v + coef0)^degree
CvSVM::RBF RBF函数:exp(-r|u-v|^&span class="hljs-number"&2&/span&)
CvSVM::SIGMOID sigmoid函数:tanh(r*&span class="hljs-string"&u'v + coef0)&/span&
CvSVM::LINEAR 线性 &span class="hljs-string"&u'vCvSVM::POLY 多项式:(r*u'&/span&v + coef0)^degreeCvSVM::RBF RBF函数:exp(-r|u-v|^&span class="hljs-number"&2&/span&)CvSVM::SIGMOID sigmoid函数:tanh(r*&span class="hljs-string"&u'v + coef0)&/span&
成员变量degree针对多项式核函数degree的设置,gamma针对多项式/rbf/sigmoid核函数的设置,coef0针对多项式/sigmoid核函数的设置,Cvalue为损失函数,在C-SVC、e-SVR、v-SVR中有效,nu设置v-SVC、一类SVM和v-SVR参数,p为设置e-SVR中损失函数的值,class_weightsC_SVC的权重,term_crit为SVM训练过程的终止条件。其中默认值degree = 0,gamma = 1,coef0 = 0,Cvalue = 1,nu = 0,p = 0,class_weights = 0
3)在分类之前,需要训练分类器。
在这里,使用75张包含车牌的图像(正样本)和35张不包含车牌的大小为144*33像素的图像(对应负样本)。(若要使车牌识别系统具有普适性,需要更多的训练数据,在本实验中这些数据已经够用)。
在得到分割后的车牌和非车牌图像后,我们把二者都执行reshaple(1,1),再存放到trainImage的矩阵中,并修改对应trainLables矩阵的0-1值,然后把trainData改为32为浮点数系,再把trainData和trainLabel直接写进xml文件。
训练SVM的代码如下:
&span class="hljs-comment"&// Main entry code OpenCV&/span&
&span class="hljs-preprocessor"&#include &cv.h&&/span&
&span class="hljs-preprocessor"&#include &highgui.h&&/span&
&span class="hljs-preprocessor"&#include &cvaux.h&&/span&
&span class="hljs-preprocessor"&#include &iostream&&/span&
&span class="hljs-preprocessor"&#include &vector&&/span&
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;
&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span&
&span class="hljs-keyword"&int&/span& main ( &span class="hljs-keyword"&int&/span& argc, &span class="hljs-keyword"&char&/span&** argv )
&span class="hljs-built_in"&cout&/span& && &span class="hljs-string"&"OpenCV Training SVM Automatic Number Plate Recognition\n"&/span&;
&span class="hljs-built_in"&cout&/span& && &span class="hljs-string"&"\n"&/span&;
&span class="hljs-keyword"&char&/span&* path_P
&span class="hljs-keyword"&char&/span&* path_NoP
&span class="hljs-keyword"&int&/span& numP
&span class="hljs-keyword"&int&/span& numNoP
&span class="hljs-keyword"&int&/span& imageWidth=&span class="hljs-number"&144&/span&;
&span class="hljs-keyword"&int&/span& imageHeight=&span class="hljs-number"&33&/span&;
&span class="hljs-comment"&//Check if user specify image to process&/span&
&span class="hljs-keyword"&if&/span&(argc &= &span class="hljs-number"&5&/span& )
numPlates= atoi(argv[&span class="hljs-number"&1&/span&]);
numNoPlates= atoi(argv[&span class="hljs-number"&2&/span&]);
path_Plates= argv[&span class="hljs-number"&3&/span&];
path_NoPlates= argv[&span class="hljs-number"&4&/span&];
}&span class="hljs-keyword"&else&/span&{
&span class="hljs-built_in"&cout&/span& && &span class="hljs-string"&"Usage:\n"&/span& && argv[&span class="hljs-number"&0&/span&] && &span class="hljs-string"&" &num Plate Files& &num Non Plate Files& &path to plate folder files& &path to non plate files& \n"&/span&;
&span class="hljs-keyword"&return&/span& &span class="hljs-number"&0&/span&;
M&span class="hljs-comment"&//(numPlates+numNoPlates, 1, CV_32FC1);&/span&
Mat trainingD&span class="hljs-comment"&//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );&/span&
Mat trainingI
&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&&&span class="hljs-keyword"&int&/span&&&/span& trainingL
&span class="hljs-keyword"&for&/span&(&span class="hljs-keyword"&int&/span& i=&span class="hljs-number"&0&/span&; i& numP i++)
&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);
ss && path_Plates && i && &span class="hljs-string"&".jpg"&/span&;
Mat img=imread(ss.str(), &span class="hljs-number"&0&/span&);
img= img.reshape(&span class="hljs-number"&1&/span&, &span class="hljs-number"&1&/span&);
trainingImages.push_back(img);
trainingLabels.push_back(&span class="hljs-number"&1&/span&);
&span class="hljs-keyword"&for&/span&(&span class="hljs-keyword"&int&/span& i=&span class="hljs-number"&0&/span&; i& numNoP i++)
&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);
ss && path_NoPlates && i && &span class="hljs-string"&".jpg"&/span&;
Mat img=imread(ss.str(), &span class="hljs-number"&0&/span&);
img= img.reshape(&span class="hljs-number"&1&/span&, &span class="hljs-number"&1&/span&);
trainingImages.push_back(img);
trainingLabels.push_back(&span class="hljs-number"&0&/span&);
Mat(trainingImages).copyTo(trainingData);
&span class="hljs-comment"&//trainingData = trainingData.reshape(1,trainingData.rows);&/span&
trainingData.convertTo(trainingData, CV_32FC1);
Mat(trainingLabels).copyTo(classes);
FileStorage fs(&span class="hljs-string"&"SVM.xml"&/span&, FileStorage::WRITE);
fs && &span class="hljs-string"&"TrainingData"&/span& && trainingD
fs && &span class="hljs-string"&"classes"&/span& &&
fs.release();
&span class="hljs-keyword"&return&/span& &span class="hljs-number"&0&/span&;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
&span class="hljs-comment"&// Main entry code OpenCV&/span&&&span class="hljs-preprocessor"&#include &cv.h&&/span&&span class="hljs-preprocessor"&#include &highgui.h&&/span&&span class="hljs-preprocessor"&#include &cvaux.h&&/span&&&span class="hljs-preprocessor"&#include &iostream&&/span&&span class="hljs-preprocessor"&#include &vector&&/span&&&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& &span class="hljs-built_in"&std&/span&;&span class="hljs-keyword"&using&/span& &span class="hljs-keyword"&namespace&/span& cv;&&span class="hljs-keyword"&int&/span& main ( &span class="hljs-keyword"&int&/span& argc, &span class="hljs-keyword"&char&/span&** argv ){&&&&&span class="hljs-built_in"&cout&/span& << &span class="hljs-string"&"OpenCV Training SVM Automatic Number Plate Recognition\n"&/span&;&&&&&span class="hljs-built_in"&cout&/span& << &span class="hljs-string"&"\n"&/span&;&&&&&&span class="hljs-keyword"&char&/span&* path_Plates;&&&&&span class="hljs-keyword"&char&/span&* path_NoPlates;&&&&&span class="hljs-keyword"&int&/span& numPlates;&&&&&span class="hljs-keyword"&int&/span& numNoPlates;&&&&&span class="hljs-keyword"&int&/span& imageWidth=&span class="hljs-number"&144&/span&;&&&&&span class="hljs-keyword"&int&/span& imageHeight=&span class="hljs-number"&33&/span&;&&&&&&span class="hljs-comment"&//Check if user specify image to process&/span&&&&&&span class="hljs-keyword"&if&/span&(argc >= &span class="hljs-number"&5&/span& )&&&&{&&&&&&&&numPlates= atoi(argv[&span class="hljs-number"&1&/span&]);&&&&&&&&numNoPlates= atoi(argv[&span class="hljs-number"&2&/span&]);&&&&&&&&path_Plates= argv[&span class="hljs-number"&3&/span&];&&&&&&&&path_NoPlates= argv[&span class="hljs-number"&4&/span&];&&&&&}&span class="hljs-keyword"&else&/span&{&&&&&&&&&span class="hljs-built_in"&cout&/span& << &span class="hljs-string"&"Usage:\n"&/span& << argv[&span class="hljs-number"&0&/span&] << &span class="hljs-string"&" &num Plate Files& &num Non Plate Files& &path to plate folder files& &path to non plate files& \n"&/span&;&&&&&&&&&span class="hljs-keyword"&return&/span& &span class="hljs-number"&0&/span&;&&&&}&&&&&&&&&&&&&Mat classes;&span class="hljs-comment"&//(numPlates+numNoPlates, 1, CV_32FC1);&/span&&&&&Mat trainingData;&span class="hljs-comment"&//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );&/span&&&&&&Mat trainingImages;&&&&&span class="hljs-stl_container"&&span class="hljs-built_in"&vector&/span&<&span class="hljs-keyword"&int&/span&>&/span& trainingLabels;&&&&&&span class="hljs-keyword"&for&/span&(&span class="hljs-keyword"&int&/span& i=&span class="hljs-number"&0&/span&; i< numPlates; i++)&&&&{&&&&&&&&&&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);&&&&&&&&ss << path_Plates << i << &span class="hljs-string"&".jpg"&/span&;&&&&&&&&Mat img=imread(ss.str(), &span class="hljs-number"&0&/span&);&&&&&&&&img= img.reshape(&span class="hljs-number"&1&/span&, &span class="hljs-number"&1&/span&);&&&&&&&&trainingImages.push_back(img);&&&&&&&&trainingLabels.push_back(&span class="hljs-number"&1&/span&);&&&&}&&&&&&span class="hljs-keyword"&for&/span&(&span class="hljs-keyword"&int&/span& i=&span class="hljs-number"&0&/span&; i< numNoPlates; i++)&&&&{&&&&&&&&&span class="hljs-built_in"&stringstream&/span& ss(&span class="hljs-built_in"&stringstream&/span&::in | &span class="hljs-built_in"&stringstream&/span&::out);&&&&&&&&ss << path_NoPlates << i << &span class="hljs-string"&".jpg"&/span&;&&&&&&&&Mat img=imread(ss.str(), &span class="hljs-number"&0&/span&);&&&&&&&&img= img.reshape(&span class="hljs-number"&1&/span&, &span class="hljs-number"&1&/span&);&&&&&&&&trainingImages.push_back(img);&&&&&&&&trainingLabels.push_back(&span class="hljs-number"&0&/span&);&&&&&}&&&&&Mat(trainingImages).copyTo(trainingData);&&&&&span class="hljs-comment"&//trainingData = trainingData.reshape(1,trainingData.rows);&/span&&&&&trainingData.convertTo(trainingData, CV_32FC1);&&&&Mat(trainingLabels).copyTo(classes);&&&&&FileStorage fs(&span class="hljs-string"&"SVM.xml"&/span&, FileStorage::WRITE);&&&&fs << &span class="hljs-string"&"TrainingData"&/span& << trainingData;&&&&fs << &span class="hljs-string"&"classes"&/span& << classes;&&&&fs.release();&&&&&&span class="hljs-keyword"&return&/span& &span class="hljs-number"&0&/span&;}
在代码中,调用CvSVM::train函数建立SVM模型,第一个参数为训练数据,第二个参数为分类结果,最后一个参数即CvSVMParams。
4)用这个SVM进行分类。调用函数CvSVM::predict实现分类。
5)获得支持向量
除了分类,也可以得到SVM的支持向量,调用函数CvSVM::get_support_vector_c}

我要回帖

更多关于 cnn深度神经网络 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信