diff --git a/include/easypr/core/chars_identify.h b/include/easypr/core/chars_identify.h index b9dd3a4..b16ddde 100644 --- a/include/easypr/core/chars_identify.h +++ b/include/easypr/core/chars_identify.h @@ -2,30 +2,22 @@ #define __CHARS_IDENTIFY_H__ #include -#include "easypr/util/util.h" - -using namespace cv; -using namespace std; namespace easypr { - class CharsIdentify { - public: +class CharsIdentify { + public: static CharsIdentify* instance(); - string identify(Mat input, bool isChinese, bool isSpeci); + std::pair identify(cv::Mat input); - private: + private: CharsIdentify(); static CharsIdentify* instance_; - - //! 字符分类 - int classify(Mat f, bool isChinses, bool isSpeci); - //!使用的ANN模型 cv::Ptr ann_; - }; +}; } diff --git a/include/easypr/core/chars_recognise.h b/include/easypr/core/chars_recognise.h index 867bd92..8d65208 100644 --- a/include/easypr/core/chars_recognise.h +++ b/include/easypr/core/chars_recognise.h @@ -15,9 +15,6 @@ #include "easypr/core/chars_segment.h" #include "easypr/core/chars_identify.h" -/*! \namespace easypr -Namespace where all the C++ EasyPR functionality resides -*/ namespace easypr { class CCharsRecognise { @@ -26,20 +23,11 @@ class CCharsRecognise { ~CCharsRecognise(); - //! 字符分割与识别 - int charsRecognise(Mat, string&); - - string charsRecognise(Mat plate); - - //! 是否开启调试模式 - inline void setCRDebug(int param) { m_charsSegment->setDebug(param); } - - //! 获取调试模式状态 - inline int getCRDebug() { return m_charsSegment->getDebug(); } + std::string charsRecognise(cv::Mat plate); //! 获得车牌颜色 - inline string getPlateColor(Mat input) const { - string color = "未知"; + inline std::string getPlateColor(cv::Mat input) const { + std::string color = "未知"; Color result = getPlateType(input, true); if (BLUE == result) color = "蓝牌"; if (YELLOW == result) color = "黄牌"; diff --git a/src/core/chars_identify.cpp b/src/core/chars_identify.cpp index 20445a4..2bcd1c1 100644 --- a/src/core/chars_identify.cpp +++ b/src/core/chars_identify.cpp @@ -1,44 +1,10 @@ #include "easypr/core/chars_identify.h" #include "easypr/core/core_func.h" #include "easypr/train/ann_train.h" -#include "easypr/config.h" +#include "easypr/config.h" namespace easypr { - std::map zh_map = { - { "zh_cuan", "川" }, - { "zh_e", "鄂" }, - { "zh_gan", "赣" }, - { "zh_gan1", "甘" }, - { "zh_gui", "贵" }, - { "zh_gui1", "桂" }, - { "zh_hei", "黑" }, - { "zh_hu", "沪" }, - { "zh_ji", "冀" }, - { "zh_jin", "津" }, - { "zh_jing", "京" }, - { "zh_jl", "吉" }, - { "zh_liao", "辽" }, - { "zh_lu", "鲁" }, - { "zh_meng", "蒙" }, - { "zh_min", "闽" }, - { "zh_ning", "宁" }, - { "zh_qing", "青" }, - { "zh_qiong", "琼" }, - { "zh_shan", "陕" }, - { "zh_su", "苏" }, - { "zh_sx", "晋" }, - { "zh_wan", "皖" }, - { "zh_xiang", "湘" }, - { "zh_xin", "新" }, - { "zh_yu", "豫" }, - { "zh_yu1", "渝" }, - { "zh_yue", "粤" }, - { "zh_yun", "云" }, - { "zh_zang", "藏" }, - { "zh_zhe", "浙" } - }; - CharsIdentify* CharsIdentify::instance_ = nullptr; CharsIdentify* CharsIdentify::instance(){ @@ -52,123 +18,15 @@ namespace easypr { ann_ = ml::ANN_MLP::load(kDefaultAnnPath); } - string CharsIdentify::identify(Mat input, bool isChinese, bool isSpeci) { - Mat f = features(input, kPredictSize); - - string result; - int index = classify(f, isChinese, isSpeci); - - if (!isChinese) { - result = result + kCharacters[index]; - } - else { - string s = kChinese[index - sizeof(kCharacters)]; - string province = zh_map[s]; - result = province + result; - } - - return result; - } - - int CharsIdentify::classify(Mat f, bool isChinses, bool isSpeci) { - int result = -1; - const int chars_number = sizeof(kCharacters); - const int zhchars_number = sizeof(kChinese) / sizeof(kChinese[0]); - Mat output(1, chars_number + zhchars_number, CV_32FC1); - ann_->predict(f, output); //使用ann对字符做判断 - - if (!isChinses) // 对数字和英文字母的判断 - { - if (isSpeci) { - // A-Z - result = 0; - float maxVal = -2; - for (int j = 10; j < chars_number; j++) { - float val = output.at(j); - // cout << "j:" << j << "val:"<< val << endl; - if (val > maxVal) { - maxVal = val; - result = j; - } - } - } - else { - // 0-9 - result = 0; - float maxVal = -2; - for (int j = 0; j < chars_number; j++) { - float val = output.at(j); - // cout << "j:" << j << "val:"<< val << endl; - if (val > - maxVal) //求得中文字符权重最大的那个,也就是通过ann认为最可能的字符 - { - maxVal = val; - result = j; - } - } - } - } - else // 对中文字符的判断 - { - result = chars_number; - float maxVal = -2; - for (int j = chars_number; j < chars_number + zhchars_number; j++) { - float val = output.at(j); - // cout << "j:" << j << "val:"<< val << endl; - if (val > maxVal) { - maxVal = val; - result = j; - } - } + std::pair CharsIdentify::identify(cv::Mat input){ + cv::Mat feature = features(input, kPredictSize); + auto index = static_cast(ann_->predict(feature)); + if (index < 34){ + return std::make_pair(kChars[index], kChars[index]); + } else { + const char* key = kChars[index]; + return std::make_pair(key, kCharsMap.at(key)); } - return result; } - //int CCharsIdentify::classify(Mat f) { - // int result = -1; - // Mat output(1, numAll, CV_32FC1); - // ann.predict(f, output); //使用ann对字符做判断 - - // float maxVal = -2; - // for (int j = 0; j < numCharacter; j++) { - // float val = output.at(j); - // // cout << "j:" << j << "val:"<< val << endl; - // if (val > maxVal) - // //求得中文字符权重最大的那个,也就是通过ann认为最可能的字符 - // { - // maxVal = val; - // result = j; - // } - // } - - // for (int j = numCharacter; j < numAll; j++) { - // float val = output.at(j); - // // cout << "j:" << j << "val:"<< val << endl; - // if (val > maxVal) { - // maxVal = val; - // result = j; - // } - // } - - // return result; - //} - - //string CCharsIdentify::charsIdentify(Mat input) { - // Mat f = features(input, m_predictSize); - // string result = ""; - // int index = classify(f); //使用ann来判别那个字符 - - // if (index >= numCharacter) { - // string s = strChinese[index - numCharacter]; - // string province = m_map[s]; - // return s; - // } - // else { - // char s = strCharacters[index]; - // char szBuf[216]; - // sprintf(szBuf, "%c", s); - // return szBuf; - // } - //} - } diff --git a/src/core/chars_recognise.cpp b/src/core/chars_recognise.cpp index 04121e1..bb2a527 100644 --- a/src/core/chars_recognise.cpp +++ b/src/core/chars_recognise.cpp @@ -11,37 +11,19 @@ namespace easypr { SAFE_RELEASE(m_charsSegment); } - int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense) { + std::string CCharsRecognise::charsRecognise(Mat plate) { //车牌字符方块集合 - vector matVec; + std::vector matChars; + std::string license; - string plateIdentify; - - int result = m_charsSegment->charsSegment(plate, matVec); + int result = m_charsSegment->charsSegment(plate, matChars); if (result == 0) { - int num = matVec.size(); - for (int j = 0; j < num; j++) { - Mat charMat = matVec[j]; - bool isChinses = false; - bool isSpeci = false; - - //默认首个字符块是中文字符 - if (j == 0) isChinses = true; - if (j == 1) isSpeci = true; - - string charcater = CharsIdentify::instance()->identify(charMat, isChinses, isSpeci); - - plateIdentify = plateIdentify + charcater; + for(auto block : matChars){ + auto character = CharsIdentify::instance()->identify(block); + license.append(character.second); } } - - plateLicense = plateIdentify; - - if (plateLicense.size() < 7) { - return -1; - } - - return result; + return license; } } \ No newline at end of file diff --git a/test/chars.hpp b/test/chars.hpp index 21c431d..9ac5c54 100644 --- a/test/chars.hpp +++ b/test/chars.hpp @@ -30,39 +30,27 @@ int test_chars_segment() { int test_chars_identify() { std::cout << "test_chars_identify" << std::endl; - cv::Mat src = cv::imread("resources/image/chars_identify.jpg"); + cv::Mat plate = cv::imread("resources/image/chars_identify.jpg"); - std::vector resultVec; - CCharsSegment cs; + std::vector matChars; + std::string license; - std::string plateIdentify = ""; + CCharsSegment cs; - int result = cs.charsSegment(src, resultVec); + int result = cs.charsSegment(plate, matChars); if (result == 0) { - size_t num = resultVec.size(); - for (size_t j = 0; j < num; j++) { - cv::Mat resultMat = resultVec[j]; - bool isChinses = false; - bool isSpec = false; - - //默认首个字符块是中文字符 - if (j == 0) - isChinses = true; - - if (j == 1) - isSpec = true; - - std::string charcater = CharsIdentify::instance()->identify(resultMat, isChinses, isSpec); - plateIdentify = plateIdentify + charcater; + for(auto block : matChars){ + auto character = CharsIdentify::instance()->identify(block); + license.append(character.second); } } const std::string plateLicense = "苏E771H6"; std::cout << "plateLicense: " << plateLicense << std::endl; - std::cout << "plateIdentify: " << plateIdentify << std::endl; + std::cout << "plateIdentify: " << license << std::endl; - if (plateLicense != plateIdentify) { + if (plateLicense != license) { std::cout << "Identify Not Correct!" << std::endl; return -1; } @@ -75,16 +63,10 @@ int test_chars_recognise() { std::cout << "test_chars_recognise" << std::endl; cv::Mat src = cv::imread("resources/image/chars_recognise.jpg"); - CCharsRecognise cr; - std::string charsRecognise = ""; - int result = cr.charsRecognise(src, charsRecognise); - if (result == 0) { - std::cout << "charsRecognise: " << charsRecognise << std::endl; - } - - return result; + std::cout << "charsRecognise: " << cr.charsRecognise(src) << std::endl; + return 0; } }