|
|
|
@ -1,9 +1,11 @@
|
|
|
|
|
#include "easypr/core/chars_identify.h"
|
|
|
|
|
#include "easypr/core/character.hpp"
|
|
|
|
|
#include "easypr/config.h"
|
|
|
|
|
#include "easypr/core/core_func.h"
|
|
|
|
|
#include "easypr/core/feature.h"
|
|
|
|
|
#include "easypr/core/params.h"
|
|
|
|
|
#include "easypr/config.h"
|
|
|
|
|
|
|
|
|
|
using namespace cv;
|
|
|
|
|
|
|
|
|
|
namespace easypr {
|
|
|
|
|
|
|
|
|
@ -17,29 +19,35 @@ namespace easypr {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CharsIdentify::CharsIdentify() {
|
|
|
|
|
ann_ = ml::ANN_MLP::load<ml::ANN_MLP>(kDefaultAnnPath);
|
|
|
|
|
annChinese_ = ml::ANN_MLP::load<ml::ANN_MLP>(kChineseAnnPath);
|
|
|
|
|
LOAD_ANN_MODEL(ann_, kDefaultAnnPath);
|
|
|
|
|
LOAD_ANN_MODEL(annChinese_, kChineseAnnPath);
|
|
|
|
|
LOAD_ANN_MODEL(annGray_, kGrayAnnPath);
|
|
|
|
|
kv_ = std::shared_ptr<Kv>(new Kv);
|
|
|
|
|
kv_->load("etc/province_mapping");
|
|
|
|
|
extractFeature = getGrayCharFeatures;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
LOAD_ANN_MODEL(ann_, path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CharsIdentify::LoadChineseModel(std::string path) {
|
|
|
|
|
if (path != std::string(kChineseAnnPath)) {
|
|
|
|
|
|
|
|
|
|
if (!annChinese_->empty())
|
|
|
|
|
annChinese_->clear();
|
|
|
|
|
LOAD_ANN_MODEL(annChinese_, path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
annChinese_ = ml::ANN_MLP::load<ml::ANN_MLP>(path);
|
|
|
|
|
void CharsIdentify::LoadGrayModel(std::string path) {
|
|
|
|
|
if (path != std::string(kGrayAnnPath)) {
|
|
|
|
|
if (!annGray_->empty())
|
|
|
|
|
annGray_->clear();
|
|
|
|
|
LOAD_ANN_MODEL(annGray_, path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -143,6 +151,60 @@ namespace easypr {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CharsIdentify::classifyChineseGray(std::vector<CCharacter>& charVec){
|
|
|
|
|
size_t charVecSize = charVec.size();
|
|
|
|
|
if (charVecSize == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Mat featureRows;
|
|
|
|
|
for (size_t index = 0; index < charVecSize; index++) {
|
|
|
|
|
Mat charInput = charVec[index].getCharacterMat();
|
|
|
|
|
cv::Mat feature;
|
|
|
|
|
extractFeature(charInput, feature);
|
|
|
|
|
featureRows.push_back(feature);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cv::Mat output(charVecSize, kChineseNumber, CV_32FC1);
|
|
|
|
|
annGray_->predict(featureRows, output);
|
|
|
|
|
|
|
|
|
|
for (size_t output_index = 0; output_index < charVecSize; output_index++) {
|
|
|
|
|
CCharacter& character = charVec[output_index];
|
|
|
|
|
Mat output_row = output.row(output_index);
|
|
|
|
|
bool isChinese = true;
|
|
|
|
|
|
|
|
|
|
float maxVal = -2;
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < kChineseNumber; j++) {
|
|
|
|
|
float val = output_row.at<float>(j);
|
|
|
|
|
//std::cout << "j:" << j << "val:" << val << std::endl;
|
|
|
|
|
if (val > maxVal) {
|
|
|
|
|
maxVal = val;
|
|
|
|
|
result = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no match
|
|
|
|
|
if (-1 == result) {
|
|
|
|
|
result = 0;
|
|
|
|
|
maxVal = 0;
|
|
|
|
|
isChinese = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto index = result + kCharsTotalNumber - kChineseNumber;
|
|
|
|
|
const char* key = kChars[index];
|
|
|
|
|
std::string s = key;
|
|
|
|
|
std::string province = kv_->get(s);
|
|
|
|
|
|
|
|
|
|
/*std::cout << "result:" << result << std::endl;
|
|
|
|
|
std::cout << "maxVal:" << maxVal << std::endl;*/
|
|
|
|
|
|
|
|
|
|
character.setCharacterScore(maxVal);
|
|
|
|
|
character.setCharacterStr(province);
|
|
|
|
|
character.setIsChinese(isChinese);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CharsIdentify::classifyChinese(std::vector<CCharacter>& charVec){
|
|
|
|
|
size_t charVecSize = charVec.size();
|
|
|
|
|
|
|
|
|
@ -197,7 +259,7 @@ namespace easypr {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses){
|
|
|
|
|
int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses, bool isAlphabet){
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
|
|
cv::Mat output(1, kCharsTotalNumber, CV_32FC1);
|
|
|
|
@ -205,13 +267,27 @@ namespace easypr {
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
if (!isAlphabet) {
|
|
|
|
|
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 = 0;
|
|
|
|
|
// begin with 11th char, which is 'A'
|
|
|
|
|
for (int j = 10; j < kCharactersNumber; j++) {
|
|
|
|
|
float val = output.at<float>(j);
|
|
|
|
|
// std::cout << "j:" << j << "val:" << val << std::endl;
|
|
|
|
|
if (val > maxVal) {
|
|
|
|
|
maxVal = val;
|
|
|
|
|
result = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -238,9 +314,7 @@ namespace easypr {
|
|
|
|
|
//std::cout << "maxVal:" << maxVal << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float chineseMaxThresh = 0.2f;
|
|
|
|
|
//float chineseMaxThresh = CParams::instance()->getParam2f();
|
|
|
|
|
|
|
|
|
|
if (maxVal >= 0.9 || (isChinese && maxVal >= chineseMaxThresh)) {
|
|
|
|
|
if (index < kCharactersNumber) {
|
|
|
|
@ -258,33 +332,9 @@ namespace easypr {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*bool CharsIdentify::charsJudge(std::vector<CCharacter>& charVec) {
|
|
|
|
|
cv::Mat feature = charFeatures(input, kPredictSize);
|
|
|
|
|
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
|
|
|
|
|
|
|
|
|
|
if (isChinese)
|
|
|
|
|
std::cout << "maxVal:" << maxVal << std::endl;
|
|
|
|
|
|
|
|
|
|
if (maxVal >= 0.9) {
|
|
|
|
|
if (index < kCharactersNumber) {
|
|
|
|
|
label = std::make_pair(kChars[index], kChars[index]).second;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
const char* key = kChars[index];
|
|
|
|
|
std::string s = key;
|
|
|
|
|
std::string province = kv_->get(s);
|
|
|
|
|
label = std::make_pair(s, province).second;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
std::pair<std::string, std::string> CharsIdentify::identifyChinese(cv::Mat input, float& out, bool& isChinese) {
|
|
|
|
|
cv::Mat feature = charFeatures(input, kChineseSize);
|
|
|
|
|
float maxVal = -2;
|
|
|
|
|
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
|
|
cv::Mat output(1, kChineseNumber, CV_32FC1);
|
|
|
|
@ -313,17 +363,48 @@ namespace easypr {
|
|
|
|
|
const char* key = kChars[index];
|
|
|
|
|
std::string s = key;
|
|
|
|
|
std::string province = kv_->get(s);
|
|
|
|
|
|
|
|
|
|
out = maxVal;
|
|
|
|
|
|
|
|
|
|
return std::make_pair(s, province);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::pair<std::string, std::string> CharsIdentify::identifyChineseGray(cv::Mat input, float& out, bool& isChinese) {
|
|
|
|
|
cv::Mat feature;
|
|
|
|
|
extractFeature(input, feature);
|
|
|
|
|
float maxVal = -2;
|
|
|
|
|
int result = -1;
|
|
|
|
|
cv::Mat output(1, kChineseNumber, CV_32FC1);
|
|
|
|
|
annGray_->predict(feature, output);
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < kChineseNumber; j++) {
|
|
|
|
|
float val = output.at<float>(j);
|
|
|
|
|
//std::cout << "j:" << j << "val:" << val << std::endl;
|
|
|
|
|
if (val > maxVal) {
|
|
|
|
|
maxVal = val;
|
|
|
|
|
result = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// no match
|
|
|
|
|
if (-1 == result) {
|
|
|
|
|
result = 0;
|
|
|
|
|
maxVal = 0;
|
|
|
|
|
isChinese = false;
|
|
|
|
|
} else if (maxVal > 0.9){
|
|
|
|
|
isChinese = true;
|
|
|
|
|
}
|
|
|
|
|
auto index = result + kCharsTotalNumber - kChineseNumber;
|
|
|
|
|
const char* key = kChars[index];
|
|
|
|
|
std::string s = key;
|
|
|
|
|
std::string province = kv_->get(s);
|
|
|
|
|
out = maxVal;
|
|
|
|
|
return std::make_pair(s, province);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<std::string, std::string> CharsIdentify::identify(cv::Mat input, bool isChinese) {
|
|
|
|
|
std::pair<std::string, std::string> CharsIdentify::identify(cv::Mat input, bool isChinese, bool isAlphabet) {
|
|
|
|
|
cv::Mat feature = charFeatures(input, kPredictSize);
|
|
|
|
|
float maxVal = -2;
|
|
|
|
|
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
|
|
|
|
|
auto index = static_cast<int>(classify(feature, maxVal, isChinese, isAlphabet));
|
|
|
|
|
if (index < kCharactersNumber) {
|
|
|
|
|
return std::make_pair(kChars[index], kChars[index]);
|
|
|
|
|
}
|
|
|
|
|