You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

455 lines
12 KiB

5 years ago
#include "easypr/core/chars_identify.h"
#include "easypr/core/character.hpp"
#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 {
CharsIdentify* CharsIdentify::instance_ = nullptr;
CharsIdentify* CharsIdentify::instance() {
if (!instance_) {
instance_ = new CharsIdentify;
}
return instance_;
}
CharsIdentify::CharsIdentify() {
LOAD_ANN_MODEL(ann_, kDefaultAnnPath);
LOAD_ANN_MODEL(annChinese_, kChineseAnnPath);
LOAD_ANN_MODEL(annGray_, kGrayAnnPath);
kv_ = std::shared_ptr<Kv>(new Kv);
kv_->load(kChineseMappingPath);
extractFeature = getGrayPlusProject;
}
void CharsIdentify::LoadModel(std::string path) {
if (path != std::string(kDefaultAnnPath)) {
if (!ann_->empty())
ann_->clear();
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);
}
}
void CharsIdentify::LoadGrayChANN(std::string path) {
if (path != std::string(kGrayAnnPath)) {
if (!annGray_->empty())
annGray_->clear();
LOAD_ANN_MODEL(annGray_, path);
}
}
void CharsIdentify::LoadChineseMapping(std::string path) {
kv_->clear();
kv_->load(path);
}
void CharsIdentify::classify(cv::Mat featureRows, std::vector<int>& out_maxIndexs,
std::vector<float>& out_maxVals, std::vector<bool> isChineseVec){
int rowNum = featureRows.rows;
cv::Mat output(rowNum, kCharsTotalNumber, CV_32FC1);
ann_->predict(featureRows, output);
for (int output_index = 0; output_index < rowNum; output_index++) {
Mat output_row = output.row(output_index);
int result = 0;
float maxVal = -2.f;
bool isChinses = isChineseVec[output_index];
if (!isChinses) {
result = 0;
for (int j = 0; j < kCharactersNumber; j++) {
float val = output_row.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_row.at<float>(j);
//std::cout << "j:" << j << "val:" << val << std::endl;
if (val > maxVal) {
maxVal = val;
result = j;
}
}
}
out_maxIndexs[output_index] = result;
out_maxVals[output_index] = maxVal;
}
}
void CharsIdentify::classify(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();
Mat feature = charFeatures(charInput, kPredictSize);
featureRows.push_back(feature);
}
cv::Mat output(charVecSize, kCharsTotalNumber, CV_32FC1);
ann_->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);
int result = 0;
float maxVal = -2.f;
std::string label = "";
bool isChinses = character.getIsChinese();
if (!isChinses) {
result = 0;
for (int j = 0; j < kCharactersNumber; j++) {
float val = output_row.at<float>(j);
//std::cout << "j:" << j << "val:" << val << std::endl;
if (val > maxVal) {
maxVal = val;
result = j;
}
}
label = std::make_pair(kChars[result], kChars[result]).second;
}
else {
result = kCharactersNumber;
for (int j = kCharactersNumber; j < kCharsTotalNumber; j++) {
float val = output_row.at<float>(j);
//std::cout << "j:" << j << "val:" << val << std::endl;
if (val > maxVal) {
maxVal = val;
result = j;
}
}
const char* key = kChars[result];
std::string s = key;
std::string province = kv_->get(s);
label = std::make_pair(s, province).second;
}
/*std::cout << "result:" << result << std::endl;
std::cout << "maxVal:" << maxVal << std::endl;*/
character.setCharacterScore(maxVal);
character.setCharacterStr(label);
}
}
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 = 0;
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();
if (charVecSize == 0)
return;
Mat featureRows;
for (size_t index = 0; index < charVecSize; index++) {
Mat charInput = charVec[index].getCharacterMat();
Mat feature = charFeatures(charInput, kChineseSize);
featureRows.push_back(feature);
}
cv::Mat output(charVecSize, kChineseNumber, CV_32FC1);
annChinese_->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 = 0;
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);
}
}
int CharsIdentify::classify(cv::Mat f, float& maxVal, bool isChinses, bool isAlphabet){
int result = 0;
cv::Mat output(1, kCharsTotalNumber, CV_32FC1);
ann_->predict(f, output);
maxVal = -2.f;
if (!isChinses) {
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;
}
}
}
}
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;
}
bool CharsIdentify::isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese) {
cv::Mat feature = charFeatures(input, kPredictSize);
auto index = static_cast<int>(classify(feature, maxVal, isChinese));
if (isChinese) {
//std::cout << "maxVal:" << maxVal << std::endl;
}
float chineseMaxThresh = 0.2f;
if (maxVal >= 0.9 || (isChinese && maxVal >= chineseMaxThresh)) {
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 = 0;
cv::Mat output(1, kChineseNumber, CV_32FC1);
annChinese_->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::identifyChineseGray(cv::Mat input, float& out, bool& isChinese) {
cv::Mat feature;
extractFeature(input, feature);
float maxVal = -2;
int result = 0;
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, bool isAlphabet) {
cv::Mat feature = charFeatures(input, kPredictSize);
float maxVal = -2;
auto index = static_cast<int>(classify(feature, maxVal, isChinese, isAlphabet));
if (index < kCharactersNumber) {
return std::make_pair(kChars[index], kChars[index]);
}
else {
const char* key = kChars[index];
std::string s = key;
std::string province = kv_->get(s);
return std::make_pair(s, province);
}
}
int CharsIdentify::identify(std::vector<cv::Mat> inputs, std::vector<std::pair<std::string, std::string>>& outputs,
std::vector<bool> isChineseVec) {
Mat featureRows;
size_t input_size = inputs.size();
for (size_t i = 0; i < input_size; i++) {
Mat input = inputs[i];
cv::Mat feature = charFeatures(input, kPredictSize);
featureRows.push_back(feature);
}
std::vector<int> maxIndexs;
std::vector<float> maxVals;
classify(featureRows, maxIndexs, maxVals, isChineseVec);
for (size_t row_index = 0; row_index < input_size; row_index++) {
int index = maxIndexs[row_index];
if (index < kCharactersNumber) {
outputs[row_index] = std::make_pair(kChars[index], kChars[index]);
}
else {
const char* key = kChars[index];
std::string s = key;
std::string province = kv_->get(s);
outputs[row_index] = std::make_pair(s, province);
}
}
return 0;
}
}