Train_Identify/nvidia_ascend_engine/common_engine/SelectBestEngine/SelectBestContainerEngine.cpp

513 lines
19 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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<int, ai_matrix::DataSourceConfig> 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<ProcessData> 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<ProcessData> pProcessData 帧处理信息
: int iIndex 第几个箱号
* outParam: N/A
* return : N/A
*/
void SelectBestContainerEngine::DealFailContianer(TransSubData &transSubData, std::shared_ptr<ProcessData> pProcessData,
int iIndex, std::map<int, TrainContainer> &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<ProcessData> pProcessData 帧处理信息
* outParam: N/A
* return : N/A
*/
void SelectBestContainerEngine::DealSuccContianer(TransSubData &transSubData, std::shared_ptr<ProcessData> pProcessData,
int iIndex, std::map<int, TrainContainer> &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<TrainContainer> pTrainContainer 选优结果
* outParam: N/A
* return : N/A
*/
void SelectBestContainerEngine::SelectBestTrainContainer(std::shared_ptr<TrainContainer> 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<TrainContainer> pTrainContainer 选优结果
* outParam: N/A
* return : N/A
*/
void SelectBestContainerEngine::DealContainer(std::shared_ptr<ProcessData> pProcessData, TransSubData &transSubData,
std::map<int, TrainContainer> &mapTCSucc, std::map<int, TrainContainer> &mapTCFail,
std::map<int, Step1Location> &mapStep1Pre, std::map<int, bool> &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<void> pVoidData0 = nullptr;
iRet = inputQueMap_[strPort0_]->pop(pVoidData0);
if (nullptr == pVoidData0)
{
usleep(1000);
continue;
}
std::shared_ptr<ProcessData> pProcessData = std::static_pointer_cast<ProcessData>(pVoidData0);
std::shared_ptr<TransData> pTransData = std::static_pointer_cast<TransData>(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<TrainContainer> pTrainContainer = std::make_shared<TrainContainer>();
SelectBestTrainContainer(pTrainContainer);
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pTrainContainer));
//push端口1记录csv
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainContainer));
//初始化参数变量
InitParam();
}
}
return APP_ERR_OK;
}