#include "SelectBestContainerEngine.h" #include "myutils.h" #define CONTAINER_LEN 11 using namespace ai_matrix; SelectBestContainerEngine::SelectBestContainerEngine() {} SelectBestContainerEngine::~SelectBestContainerEngine() {} APP_ERROR SelectBestContainerEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; //获取几个摄像头识别集装箱 std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { if (iter->second.strTarget.find("CONTAINER") != std::string::npos) { LogDebug << "DataSource:" << iter->first << " deal CONTAINER"; mapDataSourceIsEnd_[iter->first] = false; if (iter->second.strTarget.find("CONTAINER_T") != std::string::npos) { setTopContainerSid_.insert(iter->first); } } } InitParam(); LogInfo << "SelectBestContainerEngine Init ok"; return APP_ERR_OK; } APP_ERROR SelectBestContainerEngine::DeInit() { LogInfo << "SelectBestContainerEngine DeInit ok"; return APP_ERR_OK; } /** * 初始化参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestContainerEngine::InitParam() { for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { iter->second = false; } mapTCFail0_.clear(); mapTCSucc0_.clear(); mapStep1Pre0_.clear(); mapSecondFlag0_.clear(); mapTCFail1_.clear(); mapTCSucc1_.clear(); mapStep1Pre1_.clear(); mapSecondFlag1_.clear(); } /** * 验证集装箱号是否满足规则(前10位依次与2^0 ~2^9相乘)/11 所得余数,即是校验位) * inParam : std::string &strContainerNo 集装箱号信息 * outParam: N/A * return : true(校验通过)/false(校验失败) */ bool SelectBestContainerEngine::VerifyContainerNo(std::string &strContainerNo) { bool bChkFlag = false; if(strContainerNo.length() != CONTAINER_LEN) { return bChkFlag; } int iSum = 0; for (int i = 0; i < strContainerNo.length()-1; ++i) { iSum += 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 : N/A * outParam: N/A * return : N/A */ void SelectBestContainerEngine::MakeBestContainer(Container &containerBest, TransSubData *pTransSubData, std::shared_ptr pProcessData) { // std::string strContainerInfo; // for (size_t i = 0; i < pTransSubData->vecTransInfo.size(); i++) // { // TransInfo transInfo = pTransSubData->vecTransInfo[i]; // for (size_t j = 0; j < transInfo.vecValue.size(); j++) // { // strContainerInfo += transInfo.vecValue[j]; // } // } containerBest.iDataSource = pProcessData->iDataSource; containerBest.i64TimeStamp = pProcessData->i64TimeStamp; containerBest.bIsEnd = pProcessData->bIsEnd; containerBest.strTrainDate = pProcessData->strTrainDate; containerBest.strTrainName = pProcessData->strTrainName; containerBest.step1Location = pTransSubData->step1Location; containerBest.strBestImg = std::to_string(pProcessData->iFrameId) + ".jpg"; containerBest.fScoreSum = pTransSubData->fScoreSum; containerBest.strContainerNo = pTransSubData->strAllValue; } /** * 处理失败的集装箱信息 * inParam : TransSubData &transSubData 单个转换结果 : std::shared_ptr pProcessData 帧处理信息 : int iIndex 第几个箱号 * outParam: N/A * return : N/A */ void SelectBestContainerEngine::DealFailContianer(TransSubData &transSubData, std::shared_ptr pProcessData, int iIndex, std::map &mapTCFail) { if (mapTCFail.find(pProcessData->iDataSource) == mapTCFail.end()) { mapTCFail[pProcessData->iDataSource] = TrainContainer(); } Container containerTemp; if (iIndex == 1) { containerTemp = mapTCFail[pProcessData->iDataSource].container1; } else if (iIndex == 2) { containerTemp = mapTCFail[pProcessData->iDataSource].container2; } if (transSubData.strAllValue.length() > containerTemp.strContainerNo.length()) { Container containerBest; MakeBestContainer(containerBest, &transSubData, pProcessData); if (iIndex == 1) { mapTCFail[pProcessData->iDataSource].container1 = containerBest; } else if (iIndex == 2) { mapTCFail[pProcessData->iDataSource].container2 = containerBest; } } } /** * 处理成功的集装箱信息 * inParam : TransSubData &transSubData 单个转换结果 : std::shared_ptr pProcessData 帧处理信息 * outParam: N/A * return : N/A */ void SelectBestContainerEngine::DealSuccContianer(TransSubData &transSubData, std::shared_ptr pProcessData, int iIndex, std::map &mapTCSucc) { if (mapTCSucc.find(pProcessData->iDataSource) == mapTCSucc.end()) { mapTCSucc[pProcessData->iDataSource] = TrainContainer(); } //iIndex == 1表示第一个集装箱,只有第一个时才设置到第一个集装箱中。防止第一个未校验通过,第二个校验通过的设置为1. if (iIndex == 1) { Container containerTemp1 = mapTCSucc[pProcessData->iDataSource].container1; if (containerTemp1.strContainerNo.empty() || transSubData.strAllValue == containerTemp1.strContainerNo) { if (transSubData.fScoreSum > containerTemp1.fScoreSum) { Container containerBest; MakeBestContainer(containerBest, &transSubData, pProcessData); mapTCSucc[pProcessData->iDataSource].container1 = containerBest; } return; } } Container containerTemp2 = mapTCSucc[pProcessData->iDataSource].container2; if (containerTemp2.strContainerNo.empty() || transSubData.strAllValue == containerTemp2.strContainerNo) { if (transSubData.fScoreSum > containerTemp2.fScoreSum) { Container containerBest; MakeBestContainer(containerBest, &transSubData, pProcessData); mapTCSucc[pProcessData->iDataSource].container2 = containerBest; } } } /** * 识别成功和失败中选取最优结果 * inParam : std::shared_ptr pTrainContainer 选优结果 * outParam: N/A * return : N/A */ void SelectBestContainerEngine::SelectBestTrainContainer(std::shared_ptr pTrainContainer) { Container container1; Container container2; /* 数据源之间选择时,正确的选得分高的,错误的选长度长的。 优先从正向数据中获取,正向未通过校验或正向无数据再取反向数据 */ //1.获取正向校验通过数据 for (auto iterSucee = mapTCSucc0_.begin(); iterSucee != mapTCSucc0_.end(); iterSucee++) { LogDebug << "sourceid:" << iterSucee->first << " frameid:" << iterSucee->second.container1.strBestImg << " containerNo1:" << iterSucee->second.container1.strContainerNo << " frameid:" << iterSucee->second.container2.strBestImg << " containerNo2:" << iterSucee->second.container2.strContainerNo; if (!iterSucee->second.container1.strContainerNo.empty() && iterSucee->second.container1.fScoreSum > container1.fScoreSum) { container1 = iterSucee->second.container1; } if (!iterSucee->second.container2.strContainerNo.empty() && iterSucee->second.container2.fScoreSum > container2.fScoreSum) { if (iterSucee->second.container2.strContainerNo == container1.strContainerNo) { LogError << "sourceid:" << iterSucee->first << " frameid:" << iterSucee->second.container2.strBestImg << " containerNo2:" << iterSucee->second.container2.strContainerNo << " equal containerNo1"; continue; } container2 = iterSucee->second.container2; } } pTrainContainer->container1 = container1; pTrainContainer->container2 = container2; if (!pTrainContainer->container1.strContainerNo.empty() && !pTrainContainer->container2.strContainerNo.empty()) { //正向全部识别成功直接返回。 return; } //2. 正向没全部识别成功,获取反向校验通过数据 Container containerRev1; Container containerRev2; for (auto iterSucee = mapTCSucc1_.begin(); iterSucee != mapTCSucc1_.end(); iterSucee++) { LogDebug << "reverse sourceid:" << iterSucee->first << " frameid:"<< iterSucee->second.container1.strBestImg << " containerNo1:" << iterSucee->second.container1.strContainerNo << " frameid:"<< iterSucee->second.container2.strBestImg << " containerNo2:" << iterSucee->second.container2.strContainerNo; if (!iterSucee->second.container1.strContainerNo.empty() && iterSucee->second.container1.fScoreSum > containerRev1.fScoreSum) { containerRev1 = iterSucee->second.container1; } if (!iterSucee->second.container2.strContainerNo.empty() && iterSucee->second.container2.fScoreSum > containerRev2.fScoreSum) { containerRev2 = iterSucee->second.container2; } } //反向识别且和正向不相等则,按时间顺序设置。 if (!containerRev1.strContainerNo.empty() && containerRev1.strContainerNo != pTrainContainer->container1.strContainerNo) { //正向没识别第一个时,反向识别,则反向作为第一个。 if (pTrainContainer->container1.strContainerNo.empty()) { pTrainContainer->container1 = containerRev1; } else { //正向识别第一个,则肯定没识别到第二个,因此按时间处理下。如果反向也只识别到第一个,则作为第二个集装箱号。 Container container1Temp = pTrainContainer->container1; if(container1Temp.i64TimeStamp >= containerRev1.i64TimeStamp) { pTrainContainer->container2 = container1Temp; pTrainContainer->container1 = containerRev1; } else if (containerRev2.strContainerNo.empty()) { pTrainContainer->container2 = containerRev1; } } } if (!containerRev2.strContainerNo.empty() && containerRev2.strContainerNo != pTrainContainer->container2.strContainerNo) { if (pTrainContainer->container2.strContainerNo.empty() ) { pTrainContainer->container2 = containerRev2; } } if (!pTrainContainer->container1.strContainerNo.empty() && !pTrainContainer->container2.strContainerNo.empty()) { return; } //3. 获取正向未校验通过数据 for (auto iterFail = mapTCFail0_.begin(); iterFail != mapTCFail0_.end(); iterFail++) { LogDebug << "sourceid:" << iterFail->first << " frameid:"<< iterFail->second.container1.strBestImg << " containerNo1:" << iterFail->second.container1.strContainerNo << " frameid:"<< iterFail->second.container2.strBestImg << " containerNo2:" << iterFail->second.container2.strContainerNo; if (pTrainContainer->container1.strContainerNo.empty()) { if (iterFail->second.container1.strContainerNo.length() > pTrainContainer->container1.strContainerNo.length()) { pTrainContainer->container1 = iterFail->second.container1; } } if (pTrainContainer->container2.strContainerNo.empty()) { if (iterFail->second.container2.strContainerNo.length() > pTrainContainer->container2.strContainerNo.length()) { pTrainContainer->container2 = iterFail->second.container2; } } } //4.获取反向未通过校验数据 (正向有内容不再取反向内容) if (pTrainContainer->container1.strContainerNo.empty() || pTrainContainer->container2.strContainerNo.empty()) { for (auto iterFail = mapTCFail1_.begin(); iterFail != mapTCFail1_.end(); iterFail++) { LogDebug << "reverse sourceid:" << iterFail->first << " frameid:" << iterFail->second.container1.strBestImg << " containerNo1:" << iterFail->second.container1.strContainerNo << " frameid:" << iterFail->second.container2.strBestImg << " containerNo2:" << iterFail->second.container2.strContainerNo; if (pTrainContainer->container1.strContainerNo.empty()) { if (iterFail->second.container1.strContainerNo.length() > pTrainContainer->container1.strContainerNo.length()) { pTrainContainer->container1 = iterFail->second.container1; } } if (pTrainContainer->container2.strContainerNo.empty()) { if (iterFail->second.container2.strContainerNo.length() > pTrainContainer->container2.strContainerNo.length()) { pTrainContainer->container2 = iterFail->second.container2; } } } } } /** * 识别成功和失败中选取最优结果 * inParam : std::shared_ptr pTrainContainer 选优结果 * outParam: N/A * return : N/A */ void SelectBestContainerEngine::DealContainer(std::shared_ptr pProcessData, TransSubData &transSubData, std::map &mapTCSucc, std::map &mapTCFail, std::map &mapStep1Pre, std::map &mapSecondFlag) { /* mapStep1Pre先保存第1个箱号上一帧识别结果的大框信息。当识别大框信息和保存上一个识别信息间隔大于画面一半时, 则说明识别到了第2个箱号,此时mapStep1Pre保存第2个箱号的上一帧的大框信息。 mapStep1Pre保存的第1个箱号时 和前帧识别大框间隔小于画面一半时,则属于第1个箱号,否则属于第2个箱号 mapStep1Pre保存的第2个箱号时 和前帧识别大框间隔小于画面一半时,则属于第2个箱号,否则属于第1个箱号 */ if (mapStep1Pre.find(pProcessData->iDataSource) == mapStep1Pre.end()) { mapStep1Pre[pProcessData->iDataSource] = transSubData.step1Location; } if (mapSecondFlag.find(pProcessData->iDataSource) == mapSecondFlag.end()) { mapSecondFlag[pProcessData->iDataSource] = false; } int iCompareValue = 0; int iPreCenter = 0; int iCurCenter = 0; if (setTopContainerSid_.count(pProcessData->iDataSource) != 0) { //顶部集装箱,使用Y坐标比较 iCompareValue = pProcessData->iHeight / 2; iPreCenter = mapStep1Pre[pProcessData->iDataSource].fLTY; iCurCenter = transSubData.step1Location.fLTY; } else { //侧部集装箱,使用X坐标比较 iCompareValue = pProcessData->iWidth / 2; iPreCenter = mapStep1Pre[pProcessData->iDataSource].fLTX; iCurCenter = transSubData.step1Location.fLTX; } int iIndex = 0; if (!mapSecondFlag[pProcessData->iDataSource]) { iIndex = 1; if (abs(iPreCenter - iCurCenter) > iCompareValue) { iIndex = 2; mapSecondFlag[pProcessData->iDataSource] = true; } mapStep1Pre[pProcessData->iDataSource] = transSubData.step1Location; } else { if (abs(iPreCenter - iCurCenter) > iCompareValue) { iIndex = 1; } else { iIndex = 2; mapStep1Pre[pProcessData->iDataSource] = transSubData.step1Location; } } //集装箱校验 bool bChkFlag = true; for (auto iter = transSubData.vecTransInfo.begin(); iter != transSubData.vecTransInfo.end(); ++iter) { bChkFlag &= iter->IsChkFlag; } if (bChkFlag) { bChkFlag = VerifyContainerNo(transSubData.strAllValue); } LogDebug << "datasource:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " iIndex:" << iIndex << " containerNo:" << transSubData.strAllValue << " chkflag:" << bChkFlag; if (!bChkFlag) { DealFailContianer(transSubData, pProcessData, iIndex, mapTCFail); } else { DealSuccContianer(transSubData, pProcessData, iIndex, mapTCSucc); } } APP_ERROR SelectBestContainerEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { //pop端口0 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); std::shared_ptr pTransData = std::static_pointer_cast(pProcessData->pVoidData); if (pProcessData->bIsEnd) { mapDataSourceIsEnd_[pProcessData->iDataSource] = pProcessData->bIsEnd; } for (size_t i = 0; i < pTransData->vecTransSubData.size(); i++) { TransSubData transSubData = pTransData->vecTransSubData[i]; //正方向信息 if (transSubData.iBigClassId == 0) { DealContainer(pProcessData, transSubData, mapTCSucc0_, mapTCFail0_, mapStep1Pre0_, mapSecondFlag0_); } //反方向信息 else if (transSubData.iBigClassId == 1) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " reverse info"; DealContainer(pProcessData, transSubData, mapTCSucc1_, mapTCFail1_, mapStep1Pre1_, mapSecondFlag1_); } } bool bAllEnd = true; for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { bAllEnd = bAllEnd && iter->second; } //4. 结束帧时,全部处理掉 if (bAllEnd) { std::shared_ptr pTrainContainer = std::make_shared(); SelectBestTrainContainer(pTrainContainer); outputQueMap_[strPort0_]->push(std::static_pointer_cast(pTrainContainer)); //push端口1,记录csv outputQueMap_[strPort1_]->push(std::static_pointer_cast(pTrainContainer)); //初始化参数变量 InitParam(); } } return APP_ERR_OK; }