在前面的几篇文章中,我们介绍了EasyPR中车牌定位模块的相关内容。本文开始分析车牌定位模块后续步骤的车牌判断模块。车牌判断模块是EasyPR中的基于机器学习模型的一个模块,这个模型就是作者前文中从机器学习谈起中提到的SVM(支持向量机)。
我们已经知道,车牌定位模块的输出是一些候选车牌的图片。但如何从这些候选车牌图片中甄选出真正的车牌,就是通过SVM模型判断/预测得到的。






简单来说,EasyPR的车牌判断模块就是将候选车牌的图片一张张地输入到SVM模型中,然后问它,这是车牌么?如果SVM模型回答不是,那么就继续下一张,如果是,则把图片放到一个输出列表里。最后把列表输入到下一步处理。由于EasyPR使用的是列表作为输出,因此它可以输出一副图片中所有的车牌,不像一些车牌识别程序,只能输出一个车牌结果。


一.SVM应用
我们可以看一下SVM进行判断的代码:
int CPlateJudge::plateJudge(const vector<Mat>& inVec,
vector<Mat>& resultVec)
{
int num = inVec.size();
for (int j = 0; j < num; j++)
{
Mat inMat = inVec[j];
Mat p = histeq(inMat).reshape(1, 1);
p.convertTo(p, CV_32FC1);
int response = (int)svm.predict(p);
if (response == 1)
{
resultVec.push_back(inMat);
}
}
return 0;
}
首先我们读取这幅图片,然后把这幅图片转为OPENCV需要的格式;
Mat p = histeq(inMat).reshape(1, 1);
p.convertTo(p, CV_32FC1);
接着调用svm的方法predict;
int response = (int)svm.predict(p);
perdict方法返回的值是1的话,就代表是车牌,否则就不是;
if (response == 1){ resultVec.push_back(inMat);
}
训练和预测两个过程是分开的。也就是说你们在使用EasyPR时用到的CvSVM类是我在先前就训练好的。我是如何把我训练好的模型交给各位使用的呢?CvSVM类有个方法,把训练好的结果以xml文件的形式存储,我就是把这个xml文件随EasyPR发布,并让程序在执行前先加载好这个xml。这个xml的位置就是在文件夹Model下面--svm.xml文件。
如果看CPlateJudge的代码,在构造函数中调用了LoadModel()这个方法。
CPlateJudge::CPlateJudge()
{
//cout << "CPlateJudge" << endl;
m_path = "model/svm.xml";
LoadModel();
}
LoadModel()方法的主要任务就是装载model文件夹下svm.xml这个模型。
void CPlateJudge::LoadModel()
{
svm.clear();
svm.load(m_path.c_str(), "svm");
}
如果你把这个xml文件换成其他的,那么你就可以改变EasyPR车牌判断的内核,从而实现你自己的车牌判断模块。
后面的部分全部是告诉你如何有效地实现一个自己的模型(也就是svm.xml文件)。如果你对EasyPR的需求仅仅在应用层面,那么到目前的了解就足够了。如果你希望能够改善EasyPR的效果,定制一个自己的车牌判断模块,那么请继续往下看。