|
|
|
@ -0,0 +1,72 @@
|
|
|
|
|
字符识别(Chars Recognition):该步骤的主要目的就是从上一个车牌检测步骤中获取到的车牌图像,进行光学字符识别(OCR)这个过程。其中用到的机器学习算法是人工神经网络(ANN)中的多层感知机(MLP)模型。
|
|
|
|
|
在CharsRecognize过程中,一副车牌图块首先会进行灰度化,二值化,然后使用一系列算法获取到车牌的每个字符的分割图块。获得海量的这些字符图块后,进行手工分类(这个步骤非常耗时间,后面会介绍如何加速这个处理的方法),然后放入神经网络(ANN)的MLP模型中,进行训练。在实际的车牌识别过程中,将得到7个字符图块放入训练好的神经网络模型,通过模型来预测每个图块所表示的具体字符,例如图片中就输出了“苏EUK722”。
|
|
|
|
|
字符识别主要是通过 类CharsIdentify?来进行,对于中文字符和非中文字符,分别采取了不同的策略,训练得到的ANN模型也不一样,中文字符的识别主要使用?identifyChinese?来处理,非中文字符的识别主要采用?identify?来处理。另外,类CharsIdentify采用了单例模式,具体的初始化代码和构造函数如下:
|
|
|
|
|
CharsIdentify* CharsIdentify::instance_ = nullptr;
|
|
|
|
|
|
|
|
|
|
CharsIdentify* CharsIdentify::instance() {
|
|
|
|
|
if (!instance_) {
|
|
|
|
|
instance_ = new CharsIdentify;
|
|
|
|
|
}
|
|
|
|
|
return instance_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CharsIdentify::CharsIdentify() {
|
|
|
|
|
ann_ = ml::ANN_MLP::load<ml::ANN_MLP>(kDefaultAnnPath);
|
|
|
|
|
annChinese_ = ml::ANN_MLP::load<ml::ANN_MLP>(kChineseAnnPath);
|
|
|
|
|
kv_ = std::shared_ptr<Kv>(new Kv);
|
|
|
|
|
kv_->load("etc/province_mapping");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CharsIdentify::LoadModel(std::string path) {
|
|
|
|
|
if (path != std::string(kDefaultAnnPath)) {
|
|
|
|
|
|
|
|
|
|
if (!ann_->empty())
|
|
|
|
|
ann_->clear();
|
|
|
|
|
|
|
|
|
|
ann_ = ml::ANN_MLP::load<ml::ANN_MLP>(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CharsIdentify::LoadChineseModel(std::string path) {
|
|
|
|
|
if (path != std::string(kChineseAnnPath)) {
|
|
|
|
|
|
|
|
|
|
if (!annChinese_->empty())
|
|
|
|
|
annChinese_->clear();
|
|
|
|
|
|
|
|
|
|
annChinese_ = ml::ANN_MLP::load<ml::ANN_MLP>(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
可以通过神经网络模型对车牌字符进行识别,具体的识别函数如下所示:
|
|
|
|
|
int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses){
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
|
|
cv::Mat output(1, kCharsTotalNumber, CV_32FC1);
|
|
|
|
|
ann_->predict(f, output);
|
|
|
|
|
|
|
|
|
|
maxVal = -2.f;
|
|
|
|
|
if (!isChinses) {
|
|
|
|
|
result = 0;
|
|
|
|
|
for (int j = 0; j < kCharactersNumber; j++) {
|
|
|
|
|
float val = output.at<float>(j);
|
|
|
|
|
// std::cout << "j:" << j << "val:" << val << std::endl;
|
|
|
|
|
if (val > maxVal) {
|
|
|
|
|
maxVal = val;
|
|
|
|
|
result = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
result = kCharactersNumber;
|
|
|
|
|
for (int j = kCharactersNumber; j < kCharsTotalNumber; j++) {
|
|
|
|
|
float val = output.at<float>(j);
|
|
|
|
|
//std::cout << "j:" << j << "val:" << val << std::endl;
|
|
|
|
|
if (val > maxVal) {
|
|
|
|
|
maxVal = val;
|
|
|
|
|
result = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//std::cout << "maxVal:" << maxVal << std::endl;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
ann_为之前加载得到的神经网路模型,直接调用其?predict()?函数,即可得到输出矩阵 output,输出矩阵中最大的值即为识别的车牌字符,其中,数值分别为0-64的65个数字。
|