VCarContainer/engine/DetectDivideEngine/ContainerDivideEngine.cpp

1 line
18 KiB
C++
Raw 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 "ContainerDivideEngine.h"
#include <utility>
using namespace ai_matrix;
ContainerDivideEngine::ContainerDivideEngine() {}
ContainerDivideEngine::~ContainerDivideEngine() {}
APP_ERROR ContainerDivideEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
this->vecDataSourceConfig_ = Config::getins()->getAllDataSourceConfig();
if (this->vecDataSourceConfig_.size() <= this->engineId_)
{
LogWarn << " -- " << engineName_ << "_" << engineId_ << " dataSource no set, Engine DeInit";
return APP_ERR_OK;
}
this->dataSourceConfig_ = this->vecDataSourceConfig_.at(engineId_);
this->baseConfig_ = Config::getins()->getBaseConfig();
this->identifyConfig_ = Config::getins()->getIdentifyConfig();
this->initParam();
LogInfo << "DetectDivideEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR ContainerDivideEngine::DeInit()
{
LogInfo << "DetectDivideEngine DeInit ok";
return APP_ERR_OK;
}
/**
* 初始化参数信息
* inParam : N/A
* outParam: N/A
* return : N/A
*/
void ContainerDivideEngine::initParam()
{
this->iContainerIndex = 0;
this->vecContainerFail_.clear();
}
void ContainerDivideEngine::sendBestData(const VSelectBestData& selectBestData)
{
// 直接发送第一个箱子的箱号
std::shared_ptr<VSelectBestData> pVSelectBestData = std::make_shared<VSelectBestData>();
*pVSelectBestData = selectBestData;
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pVSelectBestData), true);
LogInfo << " 帧:" << selectBestData.iFrameId
<< " 数据源:" << selectBestData.iDataSource
<< " 节:" << selectBestData.iContainerIndex
<< " 发送识别结果 " << selectBestData.strNumResult;
this->stdContainerResult_ = selectBestData.strNumResult;
this->iContainerIndex++;
}
void ContainerDivideEngine::makeResult(const std::shared_ptr<VStep2OutputData>& pVStep2OutputData,
VSelectBestData & selectBestData) const
{
selectBestData.strDetectDate = pVStep2OutputData->strDetectDate;
selectBestData.strDetectTime = pVStep2OutputData->strDetectTime;
selectBestData.iDataSource = pVStep2OutputData->iDataSource;
selectBestData.iFrameId = pVStep2OutputData->iFrameId;
selectBestData.strNumResult = pVStep2OutputData->step2ResultData.transInfo.strTmpResult;
selectBestData.bIsChkFlag = pVStep2OutputData->step2ResultData.transInfo.bIsChkFlag;
selectBestData.fSumScore = pVStep2OutputData->step2ResultData.fSubScoreSum;
selectBestData.iContainerIndex = this->iContainerIndex;
selectBestData.bHaveTwoContainer = pVStep2OutputData->vecCornerResultData.size() > 2;
}
/**
* 依据像素进行集装箱切分
* @param pVStep2OutputData
*/
void ContainerDivideEngine::divideByPixelInfo(std::shared_ptr<VStep2OutputData> pVStep2OutputData)
{
auto vCompare = [](std::string a, std::string b) {
if (a.size() != b.size()) return 999;
int count = 0;
for (int i = 0; i < a.size(); ++i)
{
if (a[i] != b[i])
{
++count;
}
}
return count;
};
Step2ResultData step2ResultData_pre = this->pVStep2OutputDataPre_->step2ResultData;
Step2ResultData step2ResultData = pVStep2OutputData->step2ResultData;
float fCenterX = (step2ResultData.fRBX + step2ResultData.fLTX)/2;
float fCenterY = (step2ResultData.fRBY + step2ResultData.fLTY)/2;
float fCenterX_Pre = (step2ResultData_pre.fRBX + step2ResultData_pre.fLTX)/2;
float fCenterY_Pre = (step2ResultData_pre.fRBY + step2ResultData_pre.fLTY)/2;
LogDebug << " 帧:" << pVStep2OutputData->iFrameId
<< " 数据源:" << pVStep2OutputData->iDataSource
<< " Y差值:" << std::abs(fCenterY - fCenterY_Pre) << " X差值:" << std::abs(fCenterX - fCenterX_Pre);
if ((pVStep2OutputData->iDataSource == 0
&& std::abs(fCenterY - fCenterY_Pre) > this->identifyConfig_.iTop_Y_SplitSpanPx)
||
(pVStep2OutputData->iDataSource != 0
&& std::abs(fCenterX - fCenterX_Pre) > this->identifyConfig_.iSide_X_SplitSpanPx))
{
if (step2ResultData.transInfo.bIsChkFlag)
{
if (stdContainerResult_ != step2ResultData.transInfo.strTmpResult)
{
if (stdContainerResult_.empty())
{
// 筛选不满足校验的部分 取最长的发送
int iSize = 0, iIndex = 0;
std::string strContainer_tmp;
for (int i = 0; i < this->vecContainerFail_.size(); i++)
{
this->vecContainerFail_[i];
if (iSize < this->vecContainerFail_[i].strNumResult.size())
{
iSize = this->vecContainerFail_[i].strNumResult.size();
iIndex = i;
strContainer_tmp = this->vecContainerFail_[i].strNumResult;
}
}
sendBestData(this->vecContainerFail_[iIndex]);
}
// 记录第二箱子
this->vecContainerFail_.clear();
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
this->sendBestData(selectBestData);
}
}
else
{
// 筛选不满足校验的部分 取最长的发送
int iSize = 0, iIndex = 0;
std::string strContainer_tmp;
for (int i = 0; i < this->vecContainerFail_.size(); i++)
{
this->vecContainerFail_[i];
if (iSize < this->vecContainerFail_[i].strNumResult.size())
{
iSize = this->vecContainerFail_[i].strNumResult.size();
iIndex = i;
strContainer_tmp = this->vecContainerFail_[i].strNumResult;
}
}
if (this->vecContainerFail_.size() > 0 && this->iContainerIndex < 1)
{
sendBestData(this->vecContainerFail_[iIndex]);
}
// 把之前的清理掉再存新箱子的 (有风险,有可能切分错)
this->vecContainerFail_.clear();
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
this->vecContainerFail_.emplace_back(selectBestData);
}
}
else
{// 不满足像素差
if (!this->stdContainerResult_.empty())
{
if (step2ResultData.transInfo.bIsChkFlag)
{
if (this->stdContainerResult_ != step2ResultData.transInfo.strTmpResult)
{
// if (vCompare(this->stdContainerResult_, step2ResultData.transInfo.strTmpResult) > 2)
// {
this->vecContainerFail_.clear();
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
this->sendBestData(selectBestData);
// }
}
}
}
else
{
if (step2ResultData.transInfo.bIsChkFlag)
{
this->stdContainerResult_ = step2ResultData.transInfo.strTmpResult;
this->vecContainerFail_.clear();
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
this->sendBestData(selectBestData);
}
else
{
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
this->vecContainerFail_.emplace_back(selectBestData);
}
}
}
}
bool ContainerDivideEngine::setectBestByCorner()
{
if (!this->vecContainer_.empty())
{
// 汇总下vecContainer中有几种正确的识别结果选出识别次数最多的
std::map<std::string, int> mapContainer_count;
std::map<std::string, int> mapContainer_index;
int i = 0;
for (auto &container: this->vecContainer_)
{
mapContainer_count[container.strNumResult]++;
mapContainer_index[container.strNumResult] = i;
++i;
}
std::string strBestContainer;
int count = 0;
// 取出现次数最高的 且与第一个箱子不一样的
for (auto &it_max: mapContainer_count) {
if (it_max.first.empty()) continue;
if (it_max.second >= count) {
count = it_max.second;
strBestContainer = it_max.first;
}
}
this->sendBestData(this->vecContainer_[mapContainer_index[strBestContainer]]);
this->vecContainer_.clear();
this->vecContainerFail_.clear();
}
else
{
if (this->vecContainerFail_.empty()) return false;
// 汇总下vecContainer中有几种正确的识别结果选出识别次数最多的
int iMaxSize = 0, iIndex = 0;
std::map<std::string, int> mapContainer_index;
int i = 0;
for (auto &container: this->vecContainerFail_)
{
if (container.strNumResult.size() > iMaxSize) {
iMaxSize = container.strNumResult.size();
iIndex = i;
}
++i;
}
this->sendBestData(this->vecContainerFail_[iIndex]);
this->vecContainer_.clear();
this->vecContainerFail_.clear();
}
return true;
}
/**
* 依据箱角切分
* @param pVStep2OutputData
*/
void ContainerDivideEngine::divideByCornerInfo(std::shared_ptr<VStep2OutputData> pVStep2OutputData)
{
Step2ResultData step2ResultData = pVStep2OutputData->step2ResultData;
if (pVStep2OutputData->vecCornerResultData.size() > 1 && this->iContainerIndex < 1)
{
if (pVStep2OutputData->vecCornerResultData.size() > 2)
{
LogWarn << "帧:" << pVStep2OutputData->iFrameId
<< " 数据源:" << pVStep2OutputData->iDataSource
<< " ---- >>> 检测到超过2个箱角疑似画面过滤倾斜或模型训练不足";
return;
}
LogInfo << "帧:" << pVStep2OutputData->iFrameId
<< " 数据源:" << pVStep2OutputData->iDataSource
<< " ---- >>> 检测到多个箱角,准备切分";
if (pVStep2OutputData->iDataSource == 0 || this->dataSourceConfig_.strRunDirection == "right")
{
if (this->vecContainerFail_.empty())
{
VSelectBestData selectBestData;
selectBestData.strDetectDate = pVStep2OutputData->strDetectDate;
selectBestData.strDetectTime = pVStep2OutputData->strDetectTime;
selectBestData.iDataSource = pVStep2OutputData->iDataSource;
selectBestData.iFrameId = 1;
selectBestData.strNumResult = "invalid-?";
selectBestData.iContainerIndex = this->iContainerIndex;
selectBestData.bHaveTwoContainer = true;
this->vecContainerFail_.emplace_back(selectBestData);
}
this->setectBestByCorner();
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
if (step2ResultData.transInfo.bIsChkFlag)
{
this->vecContainer_.emplace_back(selectBestData);
}
else
{
this->vecContainerFail_.emplace_back(selectBestData);
}
return;
}
if (this->dataSourceConfig_.strRunDirection == "left")
{
LogWarn << "向左行驶的一侧暂不支持箱角识别,请及时修改参数 divide_mode: \"pixel\"";
return;
}
}
else
{
VSelectBestData selectBestData;
this->makeResult(pVStep2OutputData, selectBestData);
if (step2ResultData.transInfo.bIsChkFlag)
{
this->vecContainer_.emplace_back(selectBestData);
}
else
{
this->vecContainerFail_.emplace_back(selectBestData);
}
}
}
/**
* 切分车厢
* @param pVStep2OutputData
*/
void ContainerDivideEngine::divideInfo(std::shared_ptr<VStep2OutputData> pVStep2OutputData)
{
if (!this->pVStep2OutputDataPre_) return;
if (this->iContainerIndex > 1) return;
if (this->vecDataSourceConfig_[pVStep2OutputData->iDataSource].strDivideModel == "corner")
{
this->divideByCornerInfo(pVStep2OutputData);
}
else
{
this->divideByPixelInfo(pVStep2OutputData);
}
}
APP_ERROR ContainerDivideEngine::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<VStep2OutputData> pVStep2OutputData = std::static_pointer_cast<VStep2OutputData>(pVoidData0);
if (pVStep2OutputData->bIsEnd)
{
std::shared_ptr<VSelectBestData> pVSelectBestData = std::make_shared<VSelectBestData>();
pVSelectBestData->bIsEnd = true;
pVSelectBestData->iDataSource = pVStep2OutputData->iDataSource;
pVSelectBestData->strDetectDate = pVStep2OutputData->strDetectDate;
pVSelectBestData->strDetectTime = pVStep2OutputData->strDetectTime;
if (this->iContainerIndex > 1)
{
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pVSelectBestData), true);
this->initParam();
continue;
}
if (this->vecDataSourceConfig_[pVStep2OutputData->iDataSource].strDivideModel == "corner")
{
if (!this->vecContainerFail_.empty() || !this->vecContainer_.empty())
{
this->setectBestByCorner();
}
}
else
{
if (!this->vecContainerFail_.empty())
{
// 筛选不满足校验的部分 取最长的发送
int iSize = 0, iIndex = 0;
std::string strContainer_tmp;
for (int i = 0; i < this->vecContainerFail_.size(); i++)
{
this->vecContainerFail_[i];
if (iSize < this->vecContainerFail_[i].strNumResult.size())
{
iSize = this->vecContainerFail_[i].strNumResult.size();
iIndex = i;
strContainer_tmp = this->vecContainerFail_[i].strNumResult;
}
}
this->vecContainerFail_[iIndex].bIsEnd = true;
sendBestData(this->vecContainerFail_[iIndex]);
this->initParam();
continue;
}
}
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pVSelectBestData), true);
this->initParam();
continue;
}
std::string strFilePath ;
strFilePath = this->baseConfig_.strDebugResultPath + "/"
+ pVStep2OutputData->strDetectDate + "/"
+ StringUtil::getins()->replace_all_distinct(pVStep2OutputData->strDetectTime, ":", "-") + "/"
+ std::to_string(pVStep2OutputData->iFrameId) + "_" + std::to_string(pVStep2OutputData->iDataSource) + ".json";
// 先读取文本内容,追加新的信息后再写入
Json::Value jvFrameInfo;
if (!FileUtil::getins()->readJsonInfo(jvFrameInfo, strFilePath))
{
LogError << "read fail:" << strFilePath;
}
// jvFrameInfo["isEnd"] = (pVStep2OutputData->bIsEnd || jvFrameInfo["isEnd"].asBool());
// 识别结果存储
float fCenter = pVStep2OutputData->step2ResultData.fLTX + (pVStep2OutputData->step2ResultData.fRBX - pVStep2OutputData->step2ResultData.fLTX) / 2;
// this->mapContainerCenterInfo_.insert(std::make_pair(pVStep2OutputData->iFrameId, fCenter));
Json::Value jvInfo;
jvInfo["classid"] = pVStep2OutputData->step2ResultData.iClassId;
jvInfo["score"] = pVStep2OutputData->step2ResultData.fScore;
jvInfo["ltx"] = pVStep2OutputData->step2ResultData.fLTX;
jvInfo["lty"] = pVStep2OutputData->step2ResultData.fLTY;
jvInfo["rbx"] = pVStep2OutputData->step2ResultData.fRBX;
jvInfo["rby"] = pVStep2OutputData->step2ResultData.fRBY;
jvFrameInfo["step1"].append(jvInfo);
for (auto &step2ResultData : pVStep2OutputData->vecCornerResultData)
{
float fCenter = step2ResultData.fLTX + (step2ResultData.fRBX - step2ResultData.fLTX) / 2;
// this->mapContainerCenterInfo_.insert(std::make_pair(pVStep2OutputData->iFrameId, fCenter));
Json::Value jvInfo;
jvInfo["classid"] = step2ResultData.iClassId;
jvInfo["score"] = step2ResultData.fScore;
jvInfo["ltx"] = step2ResultData.fLTX;
jvInfo["lty"] = step2ResultData.fLTY;
jvInfo["rbx"] = step2ResultData.fRBX;
jvInfo["rby"] = step2ResultData.fRBY;
jvFrameInfo["step1"].append(jvInfo);
}
FileUtil::getins()->writeJsonInfo(jvFrameInfo, strFilePath);
if (pVStep2OutputData->step2ResultData.fScore != 0.0f)
{
LogDebug << " 帧:" << pVStep2OutputData->iFrameId
<< " 数据源:" << pVStep2OutputData->iDataSource
<< " - "<< pVStep2OutputData->step2ResultData.transInfo.strTmpResult;
}
this->divideInfo(pVStep2OutputData);
this->pVStep2OutputDataPre_ = pVStep2OutputData;
}
return APP_ERR_OK;
}