前面的文章中我们主要介绍了车牌定位的相关技术,但是定位出来的相关区域可能并非是真实的车牌区域,EasyPR通过SVM支持向量机,一种机器学习算法来判定截取的图块是否是真的“车牌”,本节主要对相关的技术做详细的介绍。

注:SVM相关内容可以详细参考周志华老师的《机器学习》和一篇名为《支持向量机通俗导论(理解SVM的三层境界)》的文章。

一、SVM简介

支持向量机,其英文名为 support vector machine,故一般简称SVM,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。

如上图所示: 距离超平面最近的几个训练样本点被称之为支持向量(support vector),两个异类支持向量到超平面的距离之和被称之为间隔。对应的SVM的基本型如下:

上述问题本身是一个凸二次规划问题,通过拉格朗日乘子法可得到其对偶问题。

上述两个公式非常重要,简直是核心公式。

得到上面的两个公式,再带回L中把去w和b消掉,得到如下公式:

从对偶问题解出的拉格朗日乘子对应着训练样本(xi,yi)。注意到上式中有不等式约束,因此上述过程需满足KKT条件,即要求

支持向量机有一个重要的性质,训练完成后,大部分的训练样本都不需要保留,最终模型仅与支持向量有关。

接下来就是如何求解这个二次规划问题,可使用通用的二次规划算法来求解,也可以利用问题本身的特性,采用SMO算法来求解。

上面是对SVM的理论做了极其简单的介绍,对支持向量机理论感兴趣的童鞋可以做进一步的研究。

二、车牌判别

opencv中对SVM进行了集成,调用opencv的SVM接口是十分方便的,对于定位的车牌区域,首先获取其车牌特征,这边采用的是LBP算子,具体内容上一节做了详细的介绍。SVM调用的类是opencv 机器学习模块中的SVM类,具体的代码如下所示:

  typedef void (*svmCallback)(const cv::Mat& image, cv::Mat& features);
cv::Ptr<ml::SVM> svm_;
svmCallback extractFeature; PlateJudge::PlateJudge() {
svm_ = ml::SVM::load<ml::SVM>(kDefaultSvmPath);
extractFeature = getLBPFeatures;
} void PlateJudge::LoadModel(std::string path) {
if (path != std::string(kDefaultSvmPath)) {
if (!svm_->empty())
svm_->clear(); svm_ = ml::SVM::load<ml::SVM>(path);
}
} int PlateJudge::plateJudge(const Mat &inMat, int &result) {
Mat features;
extractFeature(inMat, features);
float response = svm_->predict(features);
result = (int)response; return ;
}

通过 SVM::load() 函数加载训练好的SVM参数文件,然后调用 predict()函数对当前区域进行判定,是否为车牌。

三、SVM训练

svm训练通过类SvmTrain 来进行,具体的训练函数如下所示:

 void SvmTrain::train() {
svm_ = cv::ml::SVM::create();
svm_->setType(cv::ml::SVM::C_SVC);
svm_->setKernel(cv::ml::SVM::RBF);
svm_->setDegree(0.1);
svm_->setGamma(0.1);
svm_->setCoef0(0.1);
svm_->setC();
svm_->setNu(0.1);
svm_->setP(0.1);
svm_->setTermCriteria(cvTermCriteria(CV_TERMCRIT_ITER, , 0.0001)); auto train_data = tdata(); fprintf(stdout, ">> Training SVM model, please wait...\n");
long start = utils::getTimestamp();
svm_->train(train_data); long end = utils::getTimestamp();
fprintf(stdout, ">> Training done. Time elapse: %ldms\n", end - start);
fprintf(stdout, ">> Saving model file...\n");
svm_->save(svm_xml_); fprintf(stdout, ">> Your SVM Model was saved to %s\n", svm_xml_);
fprintf(stdout, ">> Testing...\n"); this->test(); }

kernel_type:SVM的内核类型(4种):

CvSVM::LINEAR : 线性内核-- linear: u'*v
CvSVM::POLY : 多项式内核:-- polynomial: (gamma*u'*v + coef0)^degree
CvSVM::RBF : 高斯核-- radial basis function: exp(-gamma*|u-v|^2)
CvSVM::SIGMOID:Sigmoid函数内核-- sigmoid: tanh(gamma*u'*v + coef0)

svm_type:指定SVM的类型(5种):

1、CvSVM::C_SVC : C类支撑向量分类机。 n类分组 (n≥2),容许用异常值处罚因子C进行不完全分类。

2、CvSVM::NU_SVC : 类支撑向量分类机。n类似然不完全分类的分类器。参数为庖代C(其值在区间【0,1】中,nu越大,决定计划鸿沟越腻滑)。

3、CvSVM::ONE_CLASS : 单分类器,所有的练习数据提取自同一个类里,然后SVM建树了一个分界线以分别该类在特点空间中所占区域和其它类在特点空间中所占区域。

4、CvSVM::EPS_SVR : 类支撑向量回归机。练习集中的特点向量和拟合出来的超平面的间隔须要小于p。异常值处罚因子C被采取。

5、CvSVM::NU_SVR : 类支撑向量回归机。 庖代了 p。

degree:内核函数(POLY)的参数degree。

gamma:内核函数(POLY/ RBF/ SIGMOID)的参数

coef0:内核函数(POLY/ SIGMOID)的参数coef0。

Cvalue:SVM类型(C_SVC/ EPS_SVR/ NU_SVR)的参数C。

nu:SVM类型(NU_SVC/ ONE_CLASS/ NU_SVR)的参数

p:SVM类型(EPS_SVR)的参数

class_weights:C_SVC中的可选权重,赋给指定的类,乘以C今后变成 class_weights*C 。所以这些权重影响不合类此外错误分类处罚项。权重越大,某一类此外误分类数据的处罚项就越大。

term_crit:SVM的迭代练习过程的中断前提,解决项目组受束缚二次最优题目。您可以指定的公差和或最大迭代次数。

对于训练数据 tdata()的获取,如下所示:

 cv::Ptr<cv::ml::TrainData> SvmTrain::tdata() {
this->prepare(); cv::Mat samples;
std::vector<int> responses; for (auto f : train_file_list_) {
auto image = cv::imread(f.file);
if (!image.data) {
fprintf(stdout, ">> Invalid image: %s ignore.\n", f.file.c_str());
continue;
}
cv::Mat feature;
getLBPFeatures(image, feature);
feature = feature.reshape(, ); samples.push_back(feature);
responses.push_back(int(f.label));
} cv::Mat samples_, responses_;
samples.convertTo(samples_, CV_32FC1);
cv::Mat(responses).copyTo(responses_); return cv::ml::TrainData::create(samples_, cv::ml::SampleTypes::ROW_SAMPLE,
responses_);
}

对于训练得到的结果,将保存在 svm_xml_文件中。

EasyPR源码剖析(7):车牌判断之SVM的更多相关文章

  1. EasyPR源码剖析(1):概述

    EasyPR(Easy to do Plate Recognition)是本人在opencv学习过程中接触的一个开源的中文车牌识别系统,项目Git地址为https://github.com/liuru ...

  2. EasyPR源码剖析(6):车牌判断之LBP特征

    一.LBP特征 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点. 原始的LBP算子定义在像素 ...

  3. EasyPR源码剖析(5):车牌定位之偏斜扭转

    一.简介 通过颜色定位和Sobel算子定位可以计算出一个个的矩形区域,这些区域都是潜在车牌区域,但是在进行SVM判别是否是车牌之前,还需要进行一定的处理.主要是考虑到以下几个问题: 1.定位区域存在一 ...

  4. EasyPR源码剖析(3):车牌定位之颜色定位

    一.简介 对车牌颜色进行识别,可能大部分人首先想到的是RGB模型, 但是此处RGB模型有一定的局限性,譬如蓝色,其值是255,还需要另外两个分量都为0,不然很有可能你得到的值是白色.黄色更麻烦,它是由 ...

  5. EasyPR源码剖析(4):车牌定位之Sobel算子定位

    一.简介 sobel算子主要是用于获得数字图像的一阶梯度,常见的应用是边缘检测. Ⅰ.水平变化: 将 I 与一个奇数大小的内核进行卷积.比如,当内核大小为3时, 的计算结果为: Ⅱ.垂直变化: 将: ...

  6. EasyPR源码剖析(2):车牌定位

    上一篇主要介绍了车牌识别的整体框架和流程,车牌识别主要划分为了两个过程:即车牌检测和字符识别,而车牌识别的核心环节就是这一节主要介绍的车牌定位,即 Plate Locate.车牌定位主要是将图片中有可 ...

  7. EasyPR源码剖析(8):字符分割

    通过前面的学习,我们已经可以从图像中定位出车牌区域,并且通过SVM模型删除“虚假”车牌,下面我们需要对车牌检测步骤中获取到的车牌图像,进行光学字符识别(OCR),在进行光学字符识别之前,需要对车牌图块 ...

  8. EasyPR源码剖析(9):字符识别

    在上一篇文章的介绍中,我们已经通过相应的字符分割方法,将车牌区域进行分割,得到7个分割字符图块,接下来要做的就是将字符图块放入训练好的神经网络模型,通过模型来预测每个图块所表示的具体字符.神经网络的介 ...

  9. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

随机推荐

  1. C 语言 符合运算符

    复合赋值 5个算术运算符 + - * / % 可以和赋值运算符 = 结合起来形成符合运算符 += -= *= /= %= total += 5 total = total + 5 note:两个运算符 ...

  2. Anatomy of a Database System学习笔记 - 查询

    查询解析 解析会生成一个查询的内部展示.格式检查包含在解析过程中. 每次解析一个SELECT,步骤如下:1. 从FROM里找到表名,转换成schema.tablename.这一步需要调用目录管理器ca ...

  3. web 安全:

    XSSXSS 全称“跨站脚本”,是注入攻击的一种. 其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本. 这时服务器端如果没有过 ...

  4. VS编写一个项目的路径规划

    原文路径:http://blog.csdn.net/puttytree/article/details/7838419 https://www.cnblogs.com/zhehan54/p/45678 ...

  5. [SQL]批量修改存储过程视图

    存储过程与视图适用 ); )='w_sp_Sms_ExpeOrKeepEmpl'; DECLARE C_TABLES CURSOR FAST_FORWARD FOR SELECT NAME FROM ...

  6. SVN命令行操作

    参考 https://wenku.baidu.com/view/511a7d29ed630b1c59eeb5f3.html 1, 将文件checkout到本地目录 svn check out http ...

  7. python 使用多进程打开多个cmd窗口,并在子进程结束之后关闭cmd窗口

    额,我想表达的是使用os.system()打开另一个可执行文件,然后等待其结束,关闭cmd窗口 主要是我突发奇想想装逼; 如果只是用multiprocessing库的多进程,然后输出信息的话,根本没法 ...

  8. CSS 文字太多用省略号表示

    width:150px;/*要显示文字的宽度*/ overflow:hidden; /*超出的部分隐藏起来.*/ white-space:nowrap;/*不显示的地方用省略号...代替*/ text ...

  9. Java中获取系统时间的四种方式

    第一种: Date day=new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" ...

  10. Android studio下载慢解决,使用阿里云解决(转)

    转自:https://blog.csdn.net/kangweijian/article/details/79120849?%3E 使用开源中国的maven库 阿里云的(速度飞快):http://ma ...