Simplified chars_identify and chars_recognise.

v1.6alpha
Micooz 10 years ago
parent 66adeedf5d
commit 9e4b6eb71b

@ -2,30 +2,22 @@
#define __CHARS_IDENTIFY_H__
#include <opencv2/opencv.hpp>
#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<std::string, std::string> identify(cv::Mat input);
private:
private:
CharsIdentify();
static CharsIdentify* instance_;
//! 字符分类
int classify(Mat f, bool isChinses, bool isSpeci);
//使用的ANN模型
cv::Ptr<cv::ml::ANN_MLP> ann_;
};
};
}

@ -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 = "»ÆÅÆ";

@ -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<string, string> 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<ml::ANN_MLP>(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<float>(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<float>(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<float>(j);
// cout << "j:" << j << "val:"<< val << endl;
if (val > maxVal) {
maxVal = val;
result = j;
}
}
std::pair<std::string, std::string> CharsIdentify::identify(cv::Mat input){
cv::Mat feature = features(input, kPredictSize);
auto index = static_cast<int>(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<float>(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<float>(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;
// }
//}
}

@ -11,37 +11,19 @@ namespace easypr {
SAFE_RELEASE(m_charsSegment);
}
int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense) {
std::string CCharsRecognise::charsRecognise(Mat plate) {
//车牌字符方块集合
vector<Mat> matVec;
std::vector<Mat> 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;
}
}

@ -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<cv::Mat> resultVec;
CCharsSegment cs;
std::vector<Mat> 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;
}
}

Loading…
Cancel
Save