|
|
@ -6,29 +6,43 @@
|
|
|
|
namespace easypr {
|
|
|
|
namespace easypr {
|
|
|
|
|
|
|
|
|
|
|
|
CCharsRecognise::CCharsRecognise() { m_charsSegment = new CCharsSegment(); }
|
|
|
|
CCharsRecognise::CCharsRecognise() { m_charsSegment = new CCharsSegment(); }
|
|
|
|
|
|
|
|
//定义了CCharsRecognise类的构造函数,创建一个新的CCharsSegment类的实例,并将其地址赋值给成员变量m_charsSegment
|
|
|
|
|
|
|
|
|
|
|
|
CCharsRecognise::~CCharsRecognise() { SAFE_RELEASE(m_charsSegment); }
|
|
|
|
CCharsRecognise::~CCharsRecognise() { SAFE_RELEASE(m_charsSegment); }
|
|
|
|
|
|
|
|
//定义了CCharsRecognise类的析构函数,
|
|
|
|
|
|
|
|
//调用了SAFE_RELEASE宏来释放(即删除并置空)m_charsSegment指针指向的CCharsSegment对象
|
|
|
|
|
|
|
|
|
|
|
|
int CCharsRecognise::charsRecognise(Mat plate, std::string& plateLicense) {
|
|
|
|
int CCharsRecognise::charsRecognise(Mat plate, std::string& plateLicense) {
|
|
|
|
|
|
|
|
//车牌字符识别函数,接收两个参数,一个是Mat类型的plate,它是需要进行识别的车牌图像;
|
|
|
|
|
|
|
|
//另一个是std::string&类型的plateLicense,它是一个引用,用于存储识别出来的车牌号码。
|
|
|
|
std::vector<Mat> matChars;
|
|
|
|
std::vector<Mat> matChars;
|
|
|
|
|
|
|
|
//matChars,用于存储经过字符分割后的单个字符图像。
|
|
|
|
int result = m_charsSegment->charsSegment(plate, matChars);
|
|
|
|
int result = m_charsSegment->charsSegment(plate, matChars);
|
|
|
|
|
|
|
|
//调用m_charsSegment对象的charsSegment函数进行字符分割,
|
|
|
|
|
|
|
|
//将分割后的字符存储在matChars中。charsSegment函数的返回值存储在result变量中。
|
|
|
|
if (result == 0) {
|
|
|
|
if (result == 0) {
|
|
|
|
|
|
|
|
//result = 0则表示字符分割成功,接着进行车牌号码的识别
|
|
|
|
int num = matChars.size();
|
|
|
|
int num = matChars.size();
|
|
|
|
for (int j = 0; j < num; j++)
|
|
|
|
for (int j = 0; j < num; j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Mat charMat = matChars.at(j);
|
|
|
|
Mat charMat = matChars.at(j);
|
|
|
|
|
|
|
|
//循环遍历matChars中的每个字符图像
|
|
|
|
bool isChinses = false;
|
|
|
|
bool isChinses = false;
|
|
|
|
float maxVal = 0;
|
|
|
|
float maxVal = 0;
|
|
|
|
if (j == 0) {
|
|
|
|
if (j == 0) {
|
|
|
|
bool judge = true;
|
|
|
|
bool judge = true;
|
|
|
|
isChinses = true;
|
|
|
|
isChinses = true;
|
|
|
|
|
|
|
|
//第一个字符,则认为是中文汉字
|
|
|
|
auto character = CharsIdentify::instance()->identifyChinese(charMat, maxVal, judge);
|
|
|
|
auto character = CharsIdentify::instance()->identifyChinese(charMat, maxVal, judge);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
|
|
|
|
//调用CharsIdentify::instance()->identifyChinese函数进行识别,并将识别结果追加到plateLicense中
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
isChinses = false;
|
|
|
|
isChinses = false;
|
|
|
|
|
|
|
|
//如果不是第一个字符,则认为不是中文汉字,
|
|
|
|
auto character = CharsIdentify::instance()->identify(charMat, isChinses);
|
|
|
|
auto character = CharsIdentify::instance()->identify(charMat, isChinses);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
|
|
|
|
//调用CharsIdentify::instance()->identify函数进行识别,并将识别结果追加到plateLicense中。
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -36,20 +50,27 @@ int CCharsRecognise::charsRecognise(Mat plate, std::string& plateLicense) {
|
|
|
|
if (plateLicense.size() < 7) {
|
|
|
|
if (plateLicense.size() < 7) {
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查plateLicense的长度是否小于7,如果小于7,则返回 - 1,表示车牌号码识别失败。否则,返回result,表示车牌号码识别成功。
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
|
|
|
|
int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
|
|
|
|
|
|
|
|
//同样是用来识别车牌的函数,数接收两个参数,一个是CPlate&类型的plate,它是需要进行识别的车牌对象;
|
|
|
|
|
|
|
|
// 另一个是std::string&类型的plateLicense,它是一个引用,用于存储识别出来的车牌号码
|
|
|
|
std::vector<Mat> matChars;
|
|
|
|
std::vector<Mat> matChars;
|
|
|
|
std::vector<Mat> grayChars;
|
|
|
|
std::vector<Mat> grayChars;
|
|
|
|
|
|
|
|
//matChars用于存储经过字符分割后的单个字符图像,grayChars用于存储灰度图像。
|
|
|
|
Mat plateMat = plate.getPlateMat();
|
|
|
|
Mat plateMat = plate.getPlateMat();
|
|
|
|
|
|
|
|
//调用plate.getPlateMat()获取车牌图像,并将其存储在plateMat中。
|
|
|
|
if (0) writeTempImage(plateMat, "plateMat/plate");
|
|
|
|
if (0) writeTempImage(plateMat, "plateMat/plate");
|
|
|
|
Color color;
|
|
|
|
Color color;
|
|
|
|
if (plate.getPlateLocateType() == CMSER) {
|
|
|
|
if (plate.getPlateLocateType() == CMSER) {
|
|
|
|
color = plate.getPlateColor();
|
|
|
|
color = plate.getPlateColor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//选择不同的方式来获取车牌颜色。如果车牌定位类型为CMSER,则直接使用plate.getPlateColor()获取车牌颜色;
|
|
|
|
|
|
|
|
//否则,从车牌图像中截取一部分区域,并调用getPlateType()函数获取车牌类型。
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
int w = plateMat.cols;
|
|
|
|
int w = plateMat.cols;
|
|
|
|
int h = plateMat.rows;
|
|
|
|
int h = plateMat.rows;
|
|
|
@ -58,35 +79,42 @@ int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int result = m_charsSegment->charsSegmentUsingOSTU(plateMat, matChars, grayChars, color);
|
|
|
|
int result = m_charsSegment->charsSegmentUsingOSTU(plateMat, matChars, grayChars, color);
|
|
|
|
|
|
|
|
//调用charsSegmentUsingOSTU方法对输入的车牌图像进行字符分割
|
|
|
|
if (result == 0) {
|
|
|
|
if (result == 0) {
|
|
|
|
int num = matChars.size();
|
|
|
|
int num = matChars.size();
|
|
|
|
for (int j = 0; j < num; j++)
|
|
|
|
for (int j = 0; j < num; j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
//for循环遍历每一个字符图像
|
|
|
|
Mat charMat = matChars.at(j);
|
|
|
|
Mat charMat = matChars.at(j);
|
|
|
|
Mat grayChar = grayChars.at(j);
|
|
|
|
Mat grayChar = grayChars.at(j);
|
|
|
|
|
|
|
|
//通过matChars.at(j)和grayChars.at(j)获取第j个字符图像和其灰度图像
|
|
|
|
if (color != Color::BLUE)
|
|
|
|
if (color != Color::BLUE)
|
|
|
|
grayChar = 255 - grayChar;
|
|
|
|
grayChar = 255 - grayChar;
|
|
|
|
|
|
|
|
//如果车牌颜色不是蓝色,则对灰度图像进行操作
|
|
|
|
bool isChinses = false;
|
|
|
|
bool isChinses = false;
|
|
|
|
std::pair<std::string, std::string> character;
|
|
|
|
std::pair<std::string, std::string> character;
|
|
|
|
float maxVal;
|
|
|
|
float maxVal;
|
|
|
|
if (0 == j) {
|
|
|
|
if (0 == j) {
|
|
|
|
isChinses = true;
|
|
|
|
isChinses = true;
|
|
|
|
bool judge = true;
|
|
|
|
bool judge = true;
|
|
|
|
|
|
|
|
//设定第一个字符为中文字符
|
|
|
|
character = CharsIdentify::instance()->identifyChineseGray(grayChar, maxVal, judge);
|
|
|
|
character = CharsIdentify::instance()->identifyChineseGray(grayChar, maxVal, judge);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
|
|
|
|
//使用CharsIdentify::instance()->identifyChineseGray方法识别灰度图像grayChar,
|
|
|
|
|
|
|
|
// 并将结果存储在character对中。
|
|
|
|
// set plate chinese mat and str
|
|
|
|
// set plate chinese mat and str
|
|
|
|
plate.setChineseMat(grayChar);
|
|
|
|
plate.setChineseMat(grayChar);
|
|
|
|
plate.setChineseKey(character.first);
|
|
|
|
plate.setChineseKey(character.first);
|
|
|
|
|
|
|
|
//设置车牌的中文图像和字符串。
|
|
|
|
if (0) writeTempImage(grayChar, "char_data/" + character.first + "/chars_");
|
|
|
|
if (0) writeTempImage(grayChar, "char_data/" + character.first + "/chars_");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (1 == j) {
|
|
|
|
else if (1 == j) {
|
|
|
|
isChinses = false;
|
|
|
|
isChinses = false;
|
|
|
|
bool isAbc = true;
|
|
|
|
bool isAbc = true;
|
|
|
|
character = CharsIdentify::instance()->identify(charMat, isChinses, isAbc);
|
|
|
|
character = CharsIdentify::instance()->identify(charMat, isChinses, isAbc);
|
|
|
|
|
|
|
|
//使用CharsIdentify::instance()->identify方法识别字符图像charMat
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
plateLicense.append(character.second);
|
|
|
|
|
|
|
|
//将识别的第二个字符串添加到plateLicense
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
isChinses = false;
|
|
|
|
isChinses = false;
|
|
|
@ -96,17 +124,21 @@ int CCharsRecognise::charsRecognise(CPlate& plate, std::string& plateLicense) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CCharacter charResult;
|
|
|
|
CCharacter charResult;
|
|
|
|
|
|
|
|
//创建CCharacter对象并设置其图像和字符串。
|
|
|
|
charResult.setCharacterMat(charMat);
|
|
|
|
charResult.setCharacterMat(charMat);
|
|
|
|
charResult.setCharacterGrayMat(grayChar);
|
|
|
|
charResult.setCharacterGrayMat(grayChar);
|
|
|
|
if (isChinses)
|
|
|
|
if (isChinses)
|
|
|
|
charResult.setCharacterStr(character.first);
|
|
|
|
charResult.setCharacterStr(character.first);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
charResult.setCharacterStr(character.second);
|
|
|
|
charResult.setCharacterStr(character.second);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//如果isChinses为true,则使用识别的第一个字符串作为字符的字符串;否则,使用识别的第二个字符串。
|
|
|
|
plate.addReutCharacter(charResult);
|
|
|
|
plate.addReutCharacter(charResult);
|
|
|
|
|
|
|
|
//字符结果添加到车牌对象中。
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (plateLicense.size() < 7) {
|
|
|
|
if (plateLicense.size() < 7) {
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
//最后,如果识别的字符数量少于7个,函数返回 - 1;否则返回result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|