generated from zhangwei/Matrixai
823 lines
27 KiB
C++
823 lines
27 KiB
C++
#include "TrainCharacterConversionEngine.h"
|
||
|
||
|
||
using namespace ai_matrix;
|
||
|
||
namespace
|
||
{
|
||
//按照x坐标排列
|
||
bool CompareX(const SingleData &v1, const SingleData &v2)
|
||
{
|
||
return (v1.fLTX < v2.fLTX);
|
||
}
|
||
|
||
//按照y坐标排列
|
||
bool CompareY(const SingleData &v1, const SingleData &v2)
|
||
{
|
||
return (v1.fLTY < v2.fLTY);
|
||
}
|
||
|
||
//自定义比较规则
|
||
bool CmpVec(const pair<string, uint32_t> &P1, const pair<string, uint32_t> &P2)
|
||
{
|
||
return P1.second < P2.second;
|
||
}
|
||
}
|
||
|
||
TrainCharacterConversionEngine::TrainCharacterConversionEngine() {}
|
||
|
||
TrainCharacterConversionEngine::~TrainCharacterConversionEngine() {}
|
||
|
||
APP_ERROR TrainCharacterConversionEngine::Init()
|
||
{
|
||
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
|
||
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
|
||
this->modelConfig_ = Config::getins()->getModelByTrainStep2Config();
|
||
this->baseConfig_ = Config::getins()->getBaseConfig();
|
||
|
||
InitParam();
|
||
LogInfo << "TrainCharacterConversionEngine Init ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
APP_ERROR TrainCharacterConversionEngine::DeInit()
|
||
{
|
||
LogInfo << "TrainCharacterConversionEngine DeInit ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
/**
|
||
* 初始化参数信息
|
||
*/
|
||
void TrainCharacterConversionEngine::InitParam()
|
||
{
|
||
mapNumInfo_.clear();
|
||
iPreFrameId_ = 0;
|
||
}
|
||
|
||
/**
|
||
* 校验车型是否符合验证
|
||
* inParam : int classId 大框类别id
|
||
* : const std::string &trainNum 车型字符信息
|
||
* outParam: N/A
|
||
* return : true:符合; false:不符合
|
||
*/
|
||
bool TrainCharacterConversionEngine::authTransNum(int classId, const std::string &trainNum)
|
||
{
|
||
switch (classId)
|
||
{
|
||
case TRAIN_HEAD: // 车头上的编号
|
||
break;
|
||
case K_TRAIN_NUM: // 编号 矿车、煤炭漏斗车(兖矿自备、枣矿自备)
|
||
{
|
||
if (trainNum == "K13" || trainNum == "KM100AH")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 4:
|
||
reg = "^K[1FMZ]{1}[36789]{1}[018ABKNT]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^K[1M]{1}[368]{1}[1ABDN]{1}[AGKNT]{1}";
|
||
break;
|
||
case 6:
|
||
reg = "^K[MF]{1}[69]{1}[80]{1}A[KH]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
case C_TRAIN_NUM: // 敞车 特殊车型 C5D CF CFK
|
||
{
|
||
if (trainNum == "CF" || trainNum == "C62A(N)")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 3:
|
||
reg = "^C[15678F]{1}[0123456DK]{1}";
|
||
break;
|
||
case 4:
|
||
reg = "^C[1678]{1}[012346]{1}[0ABCEFHKMTY]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^C[1678]{1}[01246]{1}[0ABCEY]{1}[KAFHNT]{1}";
|
||
break;
|
||
case 6:
|
||
reg = "^C[17]{1}0[0E]{1}[A-]{1}[AH]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
case P_TRAIN_NUM: // 编号 棚车
|
||
{
|
||
if (trainNum == "P70(H)" || trainNum == "P62(N)")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 3:
|
||
reg = "^P[1678]{1}[012345]{1}";
|
||
break;
|
||
case 4:
|
||
reg = "^P[678]{1}[023456]{1}[ABHKNST]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^P6[24]{1}[ANG]{1}[KT]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
case G_TRAIN_NUM: // 编号 罐车
|
||
{
|
||
if (trainNum == "GY100SK")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 2:
|
||
reg = "^G[HLS]{1}";
|
||
break;
|
||
case 3:
|
||
reg = "^[GL]{1}[1567HL]{1}[01246789K]{1}";
|
||
break;
|
||
case 4:
|
||
reg = "^[GU]{1}[167FJLNQSWY]{1}[170689]{1}[KSABDGTM075W]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^[GU]{1}[17FHNQY6]{1}[1706A89]{1}[SBDAM057W]{1}[KEHTB0ZAS]{1}";
|
||
break;
|
||
case 6:
|
||
reg = "^[UG]{1}[6YH]{1}[1489A]{1}[057W]{1}[Z0LSA]{1}[KSAT]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
case NX_TRAIN_NUM: // 编号 平车
|
||
{
|
||
if (trainNum == "N6")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 3:
|
||
reg = "^[NQX]{1}[1234678T]{1}[0124567HK]{1}";
|
||
break;
|
||
case 4:
|
||
reg = "^[BNX]{1}[16X]{1}[17BC]{1}[07AGKT]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^[NX]{1}[16NX]{1}[17C]{1}[07AGT]{1}[KTABH]{1}";
|
||
break;
|
||
case 6:
|
||
reg = "^NX[170]{2}[AB]{1}[KTHF]{1}";
|
||
break;
|
||
case 7:
|
||
reg = "^NX70[AB]{1}[-]{1}[KTHF]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
case J_TRAIN_NUM: // 编号 牲畜车 特种车
|
||
{
|
||
if (trainNum == "TP64GK")
|
||
{
|
||
return true;
|
||
}
|
||
std::regex reg;
|
||
switch (trainNum.size())
|
||
{
|
||
case 2:
|
||
reg = "^[DT]{1}[2678]{1}";
|
||
break;
|
||
case 3:
|
||
reg = "^[DST]{1}[12346789LQ]{1}[012578ADFGP]{1}";
|
||
break;
|
||
case 4:
|
||
reg = "^[DJNT]{1}[12356AFKQS]{1}[012345678DFQS]{1}[A12345679GHKQ]{1}";
|
||
break;
|
||
case 5:
|
||
reg = "^[DJQT]{1}[2KNSH1P]{1}[613XQ2]{1}[A761234B]{1}[KA70G]{1}";
|
||
break;
|
||
default:
|
||
// LogWarn << "Unknow train, classId: " << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return std::regex_match(trainNum, reg);
|
||
}
|
||
default:
|
||
LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 过滤第二步字段代号的误识别
|
||
* inParam : std::vector<SingleData> &vecObjs
|
||
* : TargetMaxLen iMaxLen
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::filterSingleData(std::vector<SingleData> &vecObjs, TargetMaxLen iMaxLen)
|
||
{
|
||
/*误识别场景
|
||
例: 车厢容积属性只有2位时,但因误识别导致自重的某个字符字段代号错误,划归到容积中,这样实际只有2位的容积变为3位。导致选优时错误。
|
||
只处理1个字段代号的误识别,若有多个字段代号同时错误,无法区分哪些字符字段代号是正确的。(字段代号误识别较多时,则增强模型训练)
|
||
|
||
排除一个最大和最小值后计算平局坐标值,每个框左上角和平局值左上角高度差大于平局值的高度则剔除.
|
||
*/
|
||
if (vecObjs.size() != iMaxLen || vecObjs.size() <= 2)
|
||
{
|
||
return;
|
||
}
|
||
|
||
std::deque<SingleData> dqObjs(vecObjs.begin(), vecObjs.end());
|
||
std::sort(dqObjs.begin(), dqObjs.end(), [](SingleData &a, SingleData &b)
|
||
{
|
||
return a.fLTY < b.fLTY;
|
||
});
|
||
dqObjs.pop_front();
|
||
dqObjs.pop_back();
|
||
|
||
SingleData singleDataAvg;
|
||
for (auto & dqObj : dqObjs)
|
||
{
|
||
singleDataAvg.fLTX += dqObj.fLTX;
|
||
singleDataAvg.fLTY += dqObj.fLTY;
|
||
singleDataAvg.fRBX += dqObj.fRBX;
|
||
singleDataAvg.fRBY += dqObj.fRBY;
|
||
}
|
||
singleDataAvg.fLTX = singleDataAvg.fLTX / dqObjs.size();
|
||
singleDataAvg.fLTY = singleDataAvg.fLTY / dqObjs.size();
|
||
singleDataAvg.fRBX = singleDataAvg.fRBX / dqObjs.size();
|
||
singleDataAvg.fRBY = singleDataAvg.fRBY / dqObjs.size();
|
||
float fAvgHeight = singleDataAvg.fRBY - singleDataAvg.fLTY;
|
||
|
||
//剔除位置错误的字符信息
|
||
for (auto iter = vecObjs.begin(); iter != vecObjs.end(); iter++)
|
||
{
|
||
float fTemp = fabs(iter->fLTY - singleDataAvg.fLTY);
|
||
if (fTemp > (fAvgHeight - 5))
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(iter->iClassId);
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " Line wrong ";
|
||
vecObjs.erase(iter);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 属性框内容转换
|
||
* inParam : std::map<int, std::vector<SingleData>> &mapLine
|
||
* outParam: TransSubData &transSubData
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::transPro(Step2ResultData &step2ResultData, std::map<int, std::vector<SingleData>> &mapLine)
|
||
{
|
||
//载重
|
||
if (mapLine.find(0) != mapLine.end())
|
||
{
|
||
TransInfo loadInfo;
|
||
loadInfo.iLine = 0;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(0).size(); j++)
|
||
{
|
||
//过滤非数字
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(0).at(j).iClassId);
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in load";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
loadInfo.vecValue.emplace_back(strOne);
|
||
loadInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(0).at(j).fScore;
|
||
}
|
||
|
||
//匹配正则表达式
|
||
//std::regex reg("^[0-9]{2}");
|
||
std::regex reg("^([4,5,6,7,8,9]{1}[0-9]{1}|[1]{1}[0-3]{1}[0-9]{1})$"); //(第1位:棚车:4 5; K自备车:1 5 7 8 9; 平车:7; 罐车:6 7; 敞车:6 7 8)
|
||
if (std::regex_match(strTemp, reg))
|
||
{
|
||
loadInfo.IsChkFlag = true;
|
||
}
|
||
loadInfo.strTmpResult = strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(loadInfo);
|
||
}
|
||
|
||
//自重
|
||
if (mapLine.find(1) != mapLine.end())
|
||
{
|
||
this->filterSingleData(mapLine.at(1), SELF_MAXLEN);
|
||
TransInfo selfInfo;
|
||
selfInfo.iLine = 1;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(1).size(); j++)
|
||
{
|
||
//过滤非数字
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(1).at(j).iClassId);
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in self";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
selfInfo.vecValue.emplace_back(strOne);
|
||
selfInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(1).at(j).fScore;
|
||
}
|
||
|
||
//匹配正则表达式
|
||
std::regex reg("^[1,2,3]{1}[0-9]{1,2}$");
|
||
if (std::regex_match(strTemp, reg))
|
||
{
|
||
selfInfo.IsChkFlag = true;
|
||
}
|
||
selfInfo.strTmpResult = strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(selfInfo);
|
||
}
|
||
|
||
//容积
|
||
if (mapLine.find(2) != mapLine.end())
|
||
{
|
||
this->filterSingleData(mapLine.at(2), VOLUME_MAXLEN);
|
||
TransInfo volumeInfo;
|
||
volumeInfo.iLine = 2;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(2).size(); j++)
|
||
{
|
||
//过滤非数字
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(2).at(j).iClassId);
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in volume";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
volumeInfo.vecValue.emplace_back(strOne);
|
||
volumeInfo.vecScore.emplace_back(mapLine.at(2).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(2).at(j).fScore;
|
||
}
|
||
|
||
//匹配正则表达式
|
||
//std::regex reg("^[0-9]{2,3}$");
|
||
std::regex reg("^[1,6,7,8,9]{1}[0-9]{1,2}$"); //(第1位:棚车:1; K自备车:1或9; 罐车:6或7; 敞车:7或8)
|
||
if (std::regex_match(strTemp, reg))
|
||
{
|
||
volumeInfo.IsChkFlag = true;
|
||
}
|
||
|
||
volumeInfo.strTmpResult = strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(volumeInfo);
|
||
}
|
||
|
||
//换长
|
||
if (mapLine.find(3) != mapLine.end())
|
||
{
|
||
TransInfo changeInfo;
|
||
changeInfo.iLine = 3;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(3).size(); j++)
|
||
{
|
||
//过滤非数字
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(3).at(j).iClassId);
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in change";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
changeInfo.vecValue.emplace_back(strOne);
|
||
changeInfo.vecScore.emplace_back(mapLine.at(3).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(3).at(j).fScore;
|
||
}
|
||
|
||
//匹配正则表达式
|
||
//std::regex reg("^[0-9]{2}$");
|
||
std::regex reg("^[1]{1}[0-9]{1}$");
|
||
if (std::regex_match(strTemp, reg))
|
||
{
|
||
changeInfo.IsChkFlag = true;
|
||
}
|
||
|
||
changeInfo.strTmpResult = strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(changeInfo);
|
||
}
|
||
|
||
//罐车容量计表
|
||
if (mapLine.find(4) != mapLine.end())
|
||
{
|
||
TransInfo volumeSurfaceInfo;
|
||
volumeSurfaceInfo.iLine = 4;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(4).size(); j++)
|
||
{
|
||
strTemp += this->modelConfig_.vecClass.at(mapLine.at(4).at(j).iClassId);
|
||
volumeSurfaceInfo.vecValue.emplace_back(this->modelConfig_.vecClass.at(mapLine.at(4).at(j).iClassId));
|
||
volumeSurfaceInfo.vecScore.emplace_back(mapLine.at(4).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(4).at(j).fScore;
|
||
}
|
||
|
||
volumeSurfaceInfo.IsChkFlag = true; //暂不校验
|
||
step2ResultData.vecTransInfo.emplace_back(volumeSurfaceInfo);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 车号框内容转换
|
||
* inParam : std::map<int, std::vector<SingleData>> &mapLine
|
||
* outParam: TransSubData &transSubData
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::transNum(Step2ResultData &step2ResultData, std::map<int, std::vector<SingleData>> &mapLine)
|
||
{
|
||
//车型
|
||
if (mapLine.find(0) != mapLine.end())
|
||
{
|
||
TransInfo typeInfo;
|
||
typeInfo.iLine = 0;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(0).size(); j++)
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(0).at(j).iClassId);
|
||
|
||
strTemp += strOne;
|
||
typeInfo.vecValue.emplace_back(strOne);
|
||
typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(0).at(j).fScore;
|
||
}
|
||
|
||
//校验车型是否符合验证
|
||
typeInfo.IsChkFlag = this->authTransNum(step2ResultData.iClassId, strTemp);
|
||
LogDebug << "--->>> 符合正则吗?" << typeInfo.IsChkFlag << " --- " << strTemp;
|
||
|
||
typeInfo.strTmpResult = strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(typeInfo);
|
||
}
|
||
|
||
// 编号
|
||
if (mapLine.find(1) != mapLine.end())
|
||
{
|
||
TransInfo numInfo;
|
||
numInfo.iLine = 1;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(1).size(); j++)
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(1).at(j).iClassId);
|
||
// 过滤非数字
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in num";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
numInfo.vecValue.emplace_back(strOne);
|
||
numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(1).at(j).fScore;
|
||
}
|
||
|
||
//匹配正则表达式
|
||
std::regex reg("^[0-9]{5,7}$"); //车厢编号,固定7位
|
||
if (std::regex_match(strTemp, reg))
|
||
{
|
||
numInfo.IsChkFlag = true;
|
||
}
|
||
numInfo.strTmpResult = strTemp;
|
||
|
||
// LogDebug << "--->>> 符合正则吗?" << numInfo.IsChkFlag << " --- " << strTemp;
|
||
step2ResultData.vecTransInfo.emplace_back(numInfo);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 车头框内容转换
|
||
* inParam : std::map<int, std::vector<SingleData>> &mapLine
|
||
* outParam: TransSubData &transSubData
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::transHead(Step2ResultData &step2ResultData, std::map<int, std::vector<SingleData>> &mapLine)
|
||
{
|
||
//车头型号
|
||
if (mapLine.find(0) != mapLine.end())
|
||
{
|
||
TransInfo typeInfo;
|
||
typeInfo.iLine = 0;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(0).size(); j++)
|
||
{
|
||
strTemp += this->modelConfig_.vecClass.at(mapLine.at(0).at(j).iClassId);
|
||
typeInfo.vecValue.emplace_back(this->modelConfig_.vecClass.at(mapLine.at(0).at(j).iClassId));
|
||
typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(0).at(j).fScore;
|
||
}
|
||
|
||
//不做结果校验,IsChkFlag默认为true
|
||
typeInfo.IsChkFlag = true;
|
||
step2ResultData.vecTransInfo.emplace_back(typeInfo);
|
||
}
|
||
|
||
//车头编号
|
||
if (mapLine.find(1) != mapLine.end())
|
||
{
|
||
TransInfo numInfo;
|
||
numInfo.iLine = 1;
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(1).size(); j++)
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(1).at(j).iClassId);
|
||
//过滤非数字
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in headnum";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
numInfo.vecValue.emplace_back(strOne);
|
||
numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(1).at(j).fScore;
|
||
}
|
||
|
||
//不做结果校验,IsChkFlag默认为true
|
||
numInfo.IsChkFlag = true;
|
||
step2ResultData.vecTransInfo.emplace_back(numInfo);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证集装箱号是否满足规则(前10位依次与2^0 ~2^9相乘)/11 所得余数,即是校验位)
|
||
* inParam : std::string &strContainerNo 集装箱号信息
|
||
* outParam: N/A
|
||
* return : true(校验通过)/false(校验失败)
|
||
*/
|
||
bool TrainCharacterConversionEngine::verifyContainerNo(std::string &strContainerNo)
|
||
{
|
||
bool bChkFlag = false;
|
||
|
||
if(strContainerNo.length() != 11)
|
||
{
|
||
return bChkFlag;
|
||
}
|
||
|
||
int iSum = 0;
|
||
for (int i = 0; i < strContainerNo.length()-1; ++i)
|
||
{
|
||
iSum += this->mapExchange_[strContainerNo.substr(i, 1)] * int(pow(2.0, i));
|
||
}
|
||
|
||
//当校验位等于10时要继续模运算,iSum % 11 % 10,保证最终结果为0~9之间的数
|
||
int iChkValue = iSum % 11 % 10;
|
||
if (iChkValue == atoi(strContainerNo.substr(strContainerNo.length()-1, 1).c_str()))
|
||
{
|
||
bChkFlag = true;
|
||
}
|
||
return bChkFlag;
|
||
}
|
||
|
||
/**
|
||
* 集装箱框内容转换
|
||
* inParam : std::map<int, std::vector<SingleData>> &mapLine
|
||
* outParam: TransSubData &transSubData
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::transContainerNum(Step2ResultData &step2ResultData, std::map<int, std::vector<SingleData>> &mapLine)
|
||
{
|
||
TransInfo info;
|
||
info.iLine = 0;
|
||
// 箱主代码+设备识别码(4位英文字母)
|
||
if (mapLine.find(0) != mapLine.end())
|
||
{
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(0).size(); j++)
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(0).at(j).iClassId);
|
||
// 过滤非字母
|
||
if (strOne[0] < 'A' || strOne[0] > 'Z')
|
||
{
|
||
// LogDebug << strOne << " not A-Z in container";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
info.vecValue.emplace_back(strOne);
|
||
info.vecScore.emplace_back(mapLine.at(0).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(0).at(j).fScore;
|
||
}
|
||
info.strTmpResult += strTemp;
|
||
}
|
||
|
||
// 箱号(6位数字)
|
||
if (mapLine.find(1) != mapLine.end())
|
||
{
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(1).size(); j++)
|
||
{
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(1).at(j).iClassId);
|
||
// 过滤非数字
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
// LogDebug << "engineId:" << engineId_ << " " << strOne << " not digit in num";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
info.vecValue.emplace_back(strOne);
|
||
info.vecScore.emplace_back(mapLine.at(1).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(1).at(j).fScore;
|
||
}
|
||
info.strTmpResult += strTemp;
|
||
}
|
||
|
||
//校验码(1位数字)
|
||
if (mapLine.find(2) != mapLine.end())
|
||
{
|
||
std::string strTemp;
|
||
for (auto j = 0; j < mapLine.at(2).size(); j++)
|
||
{
|
||
//过滤非数字
|
||
std::string strOne = this->modelConfig_.vecClass.at(mapLine.at(2).at(j).iClassId);
|
||
if (strOne[0] < '0' || strOne[0] > '9')
|
||
{
|
||
// LogDebug << "engineId:" << engineId_ << " " << strOne << " not digit in container_2";
|
||
continue;
|
||
}
|
||
strTemp += strOne;
|
||
info.vecValue.emplace_back(strOne);
|
||
info.vecScore.emplace_back(mapLine.at(2).at(j).fScore);
|
||
step2ResultData.fSubScoreSum += mapLine.at(2).at(j).fScore;
|
||
}
|
||
info.strTmpResult += strTemp;
|
||
}
|
||
|
||
// LogDebug << " -- " << info.strTmpResult;
|
||
|
||
if (this->verifyContainerNo(info.strTmpResult))
|
||
{
|
||
info.IsChkFlag = true;
|
||
}
|
||
step2ResultData.vecTransInfo.emplace_back(info);
|
||
}
|
||
|
||
|
||
/**
|
||
* 记录在画面中间位置识别的车号
|
||
* inParam : const TransSubData &transSubData 车号信息
|
||
: const std::shared_ptr<ProcessData> &pProcessData 帧数据
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainCharacterConversionEngine::recordNum(const Step2ResultData &step2ResultData, const int iFrameId)
|
||
{
|
||
float iCenterX = step2ResultData.fLTX + (step2ResultData.fRBX - step2ResultData.fLTX) / 2;
|
||
float iImgL = IMAGE_WIDTH / 3;
|
||
float iImgR = IMAGE_WIDTH / 3 * 2;
|
||
if (iCenterX <= iImgL || iCenterX >= iImgR)
|
||
{
|
||
return;
|
||
}
|
||
|
||
std::string strValue;
|
||
for (const auto& transInfo : step2ResultData.vecTransInfo)
|
||
{
|
||
if (transInfo.iLine != 1)
|
||
{
|
||
continue;
|
||
}
|
||
for (const auto & j : transInfo.vecValue)
|
||
{
|
||
strValue += j;
|
||
}
|
||
}
|
||
|
||
bool bIntervalFlag = ((int)(iFrameId - iPreFrameId_) > iSkipInterval_ * 2);
|
||
if (mapNumInfo_.find(strValue) == mapNumInfo_.end())
|
||
{
|
||
// LogDebug << " frameid:" << iFrameId << " NUM:" << strValue
|
||
// << " bIntervalFlag:" << bIntervalFlag;
|
||
if (bIntervalFlag)
|
||
{
|
||
mapNumInfo_[strValue] = iFrameId;
|
||
}
|
||
}
|
||
iPreFrameId_ = iFrameId;
|
||
}
|
||
|
||
APP_ERROR TrainCharacterConversionEngine::Process()
|
||
{
|
||
int iRet = APP_ERR_OK;
|
||
while (!isStop_)
|
||
{
|
||
std::shared_ptr<void> pVoidData0 = nullptr;
|
||
inputQueMap_[strPort0_]->pop(pVoidData0);
|
||
if (nullptr == pVoidData0)
|
||
{
|
||
usleep(1000); //1ms
|
||
continue;
|
||
}
|
||
|
||
std::shared_ptr<VStep2OutputData> pVStep2OutputData = std::static_pointer_cast<VStep2OutputData>(pVoidData0);
|
||
|
||
for (auto & i : pVStep2OutputData->vecStep2ResultData)
|
||
{
|
||
std::vector<SingleData> vecSingleData = i.vecSingleData;
|
||
|
||
std::map<int, std::vector<SingleData>> mapLine;
|
||
for (auto & j : vecSingleData)
|
||
{
|
||
mapLine[j.iLine].push_back(j);
|
||
}
|
||
float iWidth = i.fRBX - i.fLTX;
|
||
float iHeight = i.fRBY - i.fLTY;
|
||
bool bSortByX = iHeight < (iWidth * 1.5); // 竖排集装箱按y坐标排序
|
||
//每一行按x坐标排序
|
||
for (auto & it : mapLine)
|
||
{
|
||
if (it.second.size() > 2)
|
||
{
|
||
std::set<float> setX;
|
||
std::set<float> setY;
|
||
for (auto & j : it.second)
|
||
{
|
||
setX.insert(j.fLTX);
|
||
setY.insert(j.fLTY);
|
||
}
|
||
float X = *setX.rbegin() - *setX.begin();
|
||
float Y = *setY.rbegin() - *setY.begin();
|
||
bSortByX = (X > Y);
|
||
}
|
||
|
||
if (bSortByX)
|
||
{
|
||
std::sort(it.second.begin(), it.second.end(), CompareX);
|
||
}
|
||
else
|
||
{
|
||
std::sort(it.second.begin(), it.second.end(), CompareY);
|
||
}
|
||
|
||
std::string strTemp;
|
||
for (auto & j : it.second)
|
||
{
|
||
strTemp += this->modelConfig_.vecClass.at(j.iClassId);
|
||
}
|
||
}
|
||
|
||
switch (i.iClassId)
|
||
{
|
||
case TRAIN_HEAD:
|
||
this->transHead(i, mapLine);
|
||
// this->recordNum(pVStep2OutputData->vecStep2ResultData[i], pVStep2OutputData->iFrameId);
|
||
break;
|
||
case TRAIN_PRO:
|
||
this->transPro(i, mapLine);
|
||
break;
|
||
case K_TRAIN_NUM ... NX_TRAIN_NUM:
|
||
this->transNum(i, mapLine);
|
||
// this->recordNum(pVStep2OutputData->vecStep2ResultData[i], pVStep2OutputData->iFrameId);
|
||
break;
|
||
case CONTAINERNUM:
|
||
this->transContainerNum(i, mapLine);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pVStep2OutputData), true);
|
||
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pVStep2OutputData), true);
|
||
|
||
if (pVStep2OutputData->bIsEnd)
|
||
{
|
||
//初始化参数变量
|
||
InitParam();
|
||
}
|
||
}
|
||
|
||
return APP_ERR_OK;
|
||
}
|