generated from zhangwei/Matrixai
1 line
32 KiB
C++
1 line
32 KiB
C++
#include "TrainStep1FilterEngine.h"
|
||
|
||
using namespace ai_matrix;
|
||
|
||
//namespace
|
||
//{
|
||
// //按照x坐标排列
|
||
// bool CompareX(const SingleData &a, const SingleData &b)
|
||
// {
|
||
// return a.fLTX < b.fLTX;
|
||
// }
|
||
//}
|
||
|
||
TrainStep1FilterEngine::TrainStep1FilterEngine() {}
|
||
|
||
TrainStep1FilterEngine::~TrainStep1FilterEngine() {}
|
||
|
||
APP_ERROR TrainStep1FilterEngine::Init()
|
||
{
|
||
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
|
||
|
||
this->baseConfig_ = Config::getins()->getBaseConfig();
|
||
this->dataSourceConfig_ = Config::getins()->getDataSourceConfig();
|
||
this->identifyConfig_ = Config::getins()->getIdentifyConfig();
|
||
|
||
this->mapTargetStr_.insert(std::make_pair(NUM, "NUM"));
|
||
this->mapTargetStr_.insert(std::make_pair(PRO, "PRO"));
|
||
this->mapTargetStr_.insert(std::make_pair(HEAD, "HEAD"));
|
||
this->mapTargetStr_.insert(std::make_pair(SPACE, "SPACE"));//SPACE
|
||
this->mapTargetStr_.insert(std::make_pair(TRAINSPACE, "SPACE"));//SPACE
|
||
this->mapTargetStr_.insert(std::make_pair(CONTAINER, "CONTAINER"));//CONTAINER
|
||
|
||
this->initParam();
|
||
LogInfo << "TrainStep1FilterEngine Init ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
APP_ERROR TrainStep1FilterEngine::DeInit()
|
||
{
|
||
LogInfo << "TrainStep1FilterEngine DeInit ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
/**
|
||
* 参数初始化(列车结束时需调用)
|
||
*/
|
||
void TrainStep1FilterEngine::initParam()
|
||
{
|
||
this->pInferenceResultDataPre_ = nullptr;
|
||
|
||
this->iNotChgCount_ = 0;
|
||
|
||
while (!this->stackBackInfo_.empty())
|
||
{
|
||
this->stackBackInfo_.pop();
|
||
}
|
||
while (!this->queInferenceResultData_.empty())
|
||
{
|
||
this->queInferenceResultData_.pop();
|
||
}
|
||
iTrainStatus_ = TRAINSTATUS_RUN;
|
||
g_come_direction = DIRECTION_UNKNOWN;
|
||
mapCalDirection_.clear();
|
||
}
|
||
|
||
void TrainStep1FilterEngine::addBackInfo()
|
||
{
|
||
std::string strAllClassType;
|
||
for (size_t i = 0; i < this->pInferenceResultDataPre_->vecSingleData.size(); i++)
|
||
{
|
||
if (strAllClassType.find(this->mapTargetStr_[this->pInferenceResultDataPre_->vecSingleData[i].iTargetType]) != std::string::npos)
|
||
{
|
||
continue;
|
||
}
|
||
strAllClassType += this->mapTargetStr_[this->pInferenceResultDataPre_->vecSingleData[i].iTargetType];
|
||
}
|
||
|
||
if (strAllClassType.empty())
|
||
{
|
||
return;
|
||
}
|
||
|
||
TrainBackInfo trainBackInfo;
|
||
trainBackInfo.pInferenceResultData = this->pInferenceResultDataPre_;
|
||
trainBackInfo.strAllClassType = strAllClassType;
|
||
if (this->stackBackInfo_.empty())
|
||
{
|
||
this->stackBackInfo_.push(trainBackInfo);
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 新增倒车信息:" << strAllClassType
|
||
<< " 当前数量:" << this->stackBackInfo_.size();
|
||
}
|
||
else
|
||
{
|
||
TrainBackInfo trainBackInfoTop = stackBackInfo_.top();
|
||
|
||
if (trainBackInfoTop.strAllClassType != trainBackInfo.strAllClassType)
|
||
{
|
||
if (((g_come_direction == DIRECTION_RIGHT &&
|
||
this->dataSourceConfig_.iRightFirst == RIGHT_RUN_AND_PRO_FIRST) ||
|
||
(g_come_direction == DIRECTION_LEFT &&
|
||
this->dataSourceConfig_.iLeftFirst == LEFT_RUN_AND_PRO_FIRST)) &&
|
||
((trainBackInfo.strAllClassType == "SPACE" &&
|
||
(trainBackInfoTop.strAllClassType == "PROSPACE" ||
|
||
trainBackInfoTop.strAllClassType == "SPACEPRO")) ||
|
||
(trainBackInfo.strAllClassType == "NUM" &&
|
||
(trainBackInfoTop.strAllClassType == "NUMSPACE" ||
|
||
trainBackInfoTop.strAllClassType == "SPACENUM")) ||
|
||
((trainBackInfo.strAllClassType == "PROSPACE" ||
|
||
trainBackInfo.strAllClassType == "SPACEPRO")
|
||
&& trainBackInfoTop.strAllClassType == "PRO")))
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (((g_come_direction == DIRECTION_RIGHT &&
|
||
this->dataSourceConfig_.iRightFirst == RIGHT_RUN_AND_NUM_FIRST) ||
|
||
(g_come_direction == DIRECTION_LEFT &&
|
||
this->dataSourceConfig_.iRightFirst == LEFT_RUN_AND_NUM_FIRST)) &&
|
||
((trainBackInfo.strAllClassType == "SPACE" &&
|
||
(trainBackInfoTop.strAllClassType == "NUMSPACE" ||
|
||
trainBackInfoTop.strAllClassType == "SPACENUM")) ||
|
||
(trainBackInfo.strAllClassType == "PRO" &&
|
||
(trainBackInfoTop.strAllClassType == "PROSPACE" ||
|
||
trainBackInfoTop.strAllClassType == "SPACEPRO")) ||
|
||
((trainBackInfo.strAllClassType == "NUMSPACE" ||
|
||
trainBackInfo.strAllClassType == "SPACENUM") &&
|
||
trainBackInfoTop.strAllClassType == "NUM")))
|
||
{
|
||
return;
|
||
}
|
||
this->stackBackInfo_.push(trainBackInfo);
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 新增倒车信息:" << strAllClassType
|
||
<< " 当前数量:" << this->stackBackInfo_.size();
|
||
}
|
||
}
|
||
}
|
||
|
||
bool TrainStep1FilterEngine::isEndDealBackInfo()
|
||
{
|
||
if (this->stackBackInfo_.empty())
|
||
{
|
||
return true;
|
||
}
|
||
|
||
bool bPopFlag = false;
|
||
|
||
if (this->pInferenceResultDataPre_->vecSingleData.size() == 0) return false;
|
||
|
||
/*
|
||
处理倒车数据时,数据需设置为倒车,主要是保证这样的数据后面Engine不处理,防止切分车厢出错。
|
||
|
||
类型不相等时,就pop,当pop后,还剩一个数据时,则表示已经回到了刚开始倒车的地方。(只剩一个数据的逻辑在上方)
|
||
|
||
处理最后一个时,不能只判断下类型相同就弹出。需要控制下位置。(要么类型相同位置合适,要么类型不相同)
|
||
正向为向左行驶,则当前数据的位置尽量小于等于栈中最后一个元素的位置。
|
||
正向为向右行驶,则当前数据的位置尽量大于等于栈中最后一个元素的位置。
|
||
*/
|
||
// std::sort(this->pInferenceResultDataPre_->vecSingleData.begin(), this->pInferenceResultDataPre_->vecSingleData.end(), CompareX);
|
||
|
||
std::string strAllClassType;
|
||
for (size_t i = 0; i < this->pInferenceResultDataPre_->vecSingleData.size(); i++)
|
||
{
|
||
if (strAllClassType.find(mapTargetStr_[this->pInferenceResultDataPre_->vecSingleData[i].iTargetType]) != std::string::npos)
|
||
{
|
||
continue;
|
||
}
|
||
strAllClassType += mapTargetStr_[this->pInferenceResultDataPre_->vecSingleData[i].iTargetType];
|
||
}
|
||
if (strAllClassType.empty())
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (stackBackInfo_.size() == 1)
|
||
{
|
||
TrainBackInfo trainBackInfoLast = stackBackInfo_.top();
|
||
std::shared_ptr<InferenceResultData> pInferenceResultDataBack = std::static_pointer_cast<InferenceResultData>(trainBackInfoLast.pInferenceResultData);
|
||
// std::sort(pInferenceResultDataBack->vecSingleData.begin(), pInferenceResultDataBack->vecSingleData.end(), CompareX);
|
||
|
||
for (size_t i = 0; i < pInferenceResultDataBack->vecSingleData.size(); i++)
|
||
{
|
||
int bFlag = -1;
|
||
for (size_t j = 0; j < pInferenceResultDataPre_->vecSingleData.size(); j++)
|
||
{
|
||
if (pInferenceResultDataBack->vecSingleData[i].iClassId == pInferenceResultDataPre_->vecSingleData[j].iClassId)
|
||
{
|
||
if (pInferenceResultDataPre_->vecSingleData[j].fLTX < 1 || pInferenceResultDataBack->vecSingleData[i].fLTX < 1)
|
||
{
|
||
LogDebug << "大框X坐标小于1,判定为异常大框。过滤!!";
|
||
break;
|
||
}
|
||
bFlag = (pInferenceResultDataBack->vecSingleData[i].fLTX <= pInferenceResultDataPre_->vecSingleData[j].fLTX) ? 1 : 0;
|
||
LogDebug << "帧:" << pInferenceResultDataPre_->iFrameId
|
||
<< " 倒车前帧:" << pInferenceResultDataBack->iFrameId
|
||
<< " 恢复到原位:" << bFlag
|
||
<< " 当前框位置:" << pInferenceResultDataPre_->vecSingleData[i].fLTX
|
||
<< " 倒车前位置:" << pInferenceResultDataBack->vecSingleData[i].fLTX
|
||
<< "方向:" << g_come_direction;
|
||
}
|
||
}
|
||
|
||
if ((g_come_direction == DIRECTION_LEFT && bFlag == 0) ||
|
||
(g_come_direction == DIRECTION_RIGHT && bFlag == 1))
|
||
{
|
||
bPopFlag = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (bPopFlag)
|
||
{
|
||
LogDebug << "frameId:" << pInferenceResultDataPre_->iFrameId << " 恢复倒车前的位置:" << bPopFlag;
|
||
stackBackInfo_.pop();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TrainBackInfo trainBackInfoTop_bak = stackBackInfo_.top();
|
||
stackBackInfo_.pop();
|
||
TrainBackInfo trainBackInfoTop = stackBackInfo_.top();
|
||
|
||
if (trainBackInfoTop.strAllClassType != strAllClassType)
|
||
{
|
||
stackBackInfo_.push(trainBackInfoTop_bak);
|
||
LogDebug << "帧:" << pInferenceResultDataPre_->iFrameId << " 倒车信息:" << stackBackInfo_.size()
|
||
<< " 顶部倒车信息:" << trainBackInfoTop.strAllClassType << " 本次识别信息:" << strAllClassType;
|
||
}
|
||
else
|
||
{
|
||
LogDebug << "帧:" << pInferenceResultDataPre_->iFrameId
|
||
<< " 倒车信息:" << stackBackInfo_.size()
|
||
<< " 顶部倒车信息:" << trainBackInfoTop.strAllClassType
|
||
<< " 本次识别信息:" << strAllClassType
|
||
<< " 删除倒车信息:" << trainBackInfoTop_bak.strAllClassType;
|
||
}
|
||
}
|
||
|
||
return stackBackInfo_.empty() ? true : false;
|
||
}
|
||
|
||
/**
|
||
* 校验火车是否停止
|
||
* return : true:停止; false:非停止 1(正常行驶) 2(停车) 3(倒车)
|
||
*/
|
||
int TrainStep1FilterEngine::getTrainStatus()
|
||
{
|
||
if (g_come_direction == DIRECTION_UNKNOWN)
|
||
{
|
||
LogDebug << " frameId:" << this->pInferenceResultDataPre_->iFrameId << " 未判断出行车方向,暂定认为火车正常行驶中";
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
|
||
// 无框时,返回之前的列车状态
|
||
if (this->pInferenceResultDataPre_->vecSingleData.size() == 0)
|
||
{
|
||
return iTrainStatus_;
|
||
}
|
||
|
||
queInferenceResultData_.push(this->pInferenceResultDataPre_);
|
||
|
||
if (queInferenceResultData_.size() < 3)
|
||
{
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
|
||
std::shared_ptr<InferenceResultData> pInferenceResultDataFront = queInferenceResultData_.front();
|
||
// iNotChgCount_大于0表示有可能停车,此时pop队列数据要多留存几个。用最开始的数据来判断是否真正停车,如果每次只用上上帧判断当列车超级慢时可能判断为停车。
|
||
int iSizeTemp = iNotChgCount_ > 0 ? 10 : 2;
|
||
while (queInferenceResultData_.size() > iSizeTemp)
|
||
{
|
||
queInferenceResultData_.pop();
|
||
}
|
||
// LogDebug << "frameId:" << pProcessData->iFrameId << " 判断运动状态队列 第一帧:" << postDataFront.iFrameId << " 队列size:" << quePostData_.size() << " iSizeTemp:" << iSizeTemp;
|
||
|
||
bool bSameFlag = false;
|
||
for (size_t i = 0; i < this->pInferenceResultDataPre_->vecSingleData.size(); i++)
|
||
{
|
||
SingleData singleDataBack = this->pInferenceResultDataPre_->vecSingleData[i];
|
||
for (size_t j = 0; j < pInferenceResultDataFront->vecSingleData.size(); j++)
|
||
{
|
||
SingleData singleDataFront = pInferenceResultDataFront->vecSingleData[j];
|
||
|
||
/*
|
||
使用iBigClassId,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致类别不一样
|
||
使用iTargetType,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致像素差判断不准。
|
||
*/
|
||
if (singleDataFront.iTargetType != singleDataBack.iTargetType)
|
||
{
|
||
LogDebug << "判断前后帧识别的是否一致 上一个:" << singleDataFront.iTargetType << " 当前:" << singleDataBack.iTargetType;
|
||
continue;
|
||
}
|
||
|
||
if (singleDataFront.iTargetType == CONTAINER) continue;
|
||
|
||
bSameFlag = true;
|
||
int iCenterBack = singleDataBack.fLTX + (singleDataBack.fRBX - singleDataBack.fLTX) / 2;
|
||
int iCenterFront = singleDataFront.fLTX + (singleDataFront.fRBX - singleDataFront.fLTX) / 2;
|
||
|
||
if (abs(iCenterBack - iCenterFront) > this->identifyConfig_.iChkstopPx)
|
||
{
|
||
iNotChgCount_ = 0;
|
||
/*
|
||
iCenterBack > iCenterFront 表示向右行驶,且原方向为向左行驶
|
||
iCenterBack < iCenterFront 表示向左行驶,且原方向为向右行驶
|
||
以上2种表示倒车。
|
||
*/
|
||
if ((iCenterBack > iCenterFront && g_come_direction == DIRECTION_LEFT) ||
|
||
(iCenterBack < iCenterFront && g_come_direction == DIRECTION_RIGHT))
|
||
{
|
||
if (this->identifyConfig_.iPartitionFrameSpan < (this->pInferenceResultDataPre_->iFrameId - pInferenceResultDataFront->iFrameId)
|
||
&& this->identifyConfig_.iSplitFrameSpanPx < abs(iCenterBack - iCenterFront))
|
||
{
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
// LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 检测到火车倒车";
|
||
return TRAINSTATUS_BACK;
|
||
}
|
||
else
|
||
{
|
||
// LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 正常行驶";
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
}
|
||
/*
|
||
小于10个像素表示可能停车,累计未变化次数。
|
||
累计变化次数超过10次,返回停车
|
||
累计变化次数未超过10次,返回之前行驶状态
|
||
*/
|
||
else
|
||
{
|
||
iNotChgCount_++;
|
||
LogDebug << " frameId:" << this->pInferenceResultDataPre_->iFrameId
|
||
<< " 大框移动范围小("
|
||
<< abs(iCenterBack - iCenterFront)
|
||
<< ") 判断停车计数:" << iNotChgCount_ << "/" << this->identifyConfig_.iChkstopCount;
|
||
if (iNotChgCount_ > this->identifyConfig_.iChkstopCount)
|
||
{
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 检测到火车停车";
|
||
return TRAINSTATUS_STOP;
|
||
}
|
||
else
|
||
{
|
||
// LogDebug << "frameId:" << pProcessData->iFrameId << " iTrainStatus_:" << iTrainStatus_;
|
||
return iTrainStatus_;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
未找到相同的框,说明是老框消失掉了,新框出现了。
|
||
按新框出现的位置判断是向左行驶,还是向右行驶。
|
||
*/
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " bSameFlag:" << bSameFlag;
|
||
if (!bSameFlag)
|
||
{
|
||
// std::sort(this->pInferenceResultDataPre_->vecSingleData.begin(), this->pInferenceResultDataPre_->vecSingleData.end(), CompareX);
|
||
SingleData singleData = this->pInferenceResultDataPre_->vecSingleData.front();
|
||
if (g_come_direction == DIRECTION_LEFT)
|
||
{
|
||
singleData = this->pInferenceResultDataPre_->vecSingleData.back();
|
||
}
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " fLTX:" << singleData.fLTX << " fRBX:" << singleData.fRBX;
|
||
|
||
iNotChgCount_ = 0;
|
||
int iCenter = singleData.fLTX + (singleData.fRBX - singleData.fLTX) / 2;
|
||
int iValue = IMAGE_WIDTH / 2;
|
||
if ((iCenter > iValue && g_come_direction == DIRECTION_RIGHT) ||
|
||
(iCenter < iValue && g_come_direction == DIRECTION_LEFT))
|
||
{
|
||
/*
|
||
针对有效帧较少时,和上上帧比较没有同类型大框,且当前帧已行驶到画面中心导致误判的情况,
|
||
增加和上帧同类型大框的比较处理。
|
||
*/
|
||
std::shared_ptr<InferenceResultData> pInferenceResultDataMiddle = queInferenceResultData_.front();
|
||
for (size_t i = 0; i < pInferenceResultDataPre_->vecSingleData.size(); i++)
|
||
{
|
||
SingleData singleDataBack = pInferenceResultDataPre_->vecSingleData[i];
|
||
for (size_t j = 0; j < pInferenceResultDataMiddle->vecSingleData.size(); j++)
|
||
{
|
||
SingleData singleDataMiddle = pInferenceResultDataMiddle->vecSingleData[j];
|
||
if (singleDataMiddle.iTargetType != singleDataBack.iTargetType)
|
||
{
|
||
continue;
|
||
}
|
||
int iCenterBack = singleDataBack.fLTX + (singleDataBack.fRBX - singleDataBack.fLTX) / 2;
|
||
int iCenterMiddle = singleDataMiddle.fLTX + (singleDataMiddle.fRBX - singleDataMiddle.fLTX) / 2;
|
||
|
||
// 位置比较大于10个像素,则表示有移动。再判断时正向移动,还是倒车
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " " << iCenterBack << "-" << iCenterMiddle
|
||
<< "=" << abs(iCenterBack - iCenterMiddle) << " 目标差值:" << this->identifyConfig_.iChkstopPx;
|
||
|
||
if (abs(iCenterBack - iCenterMiddle) > this->identifyConfig_.iChkstopPx)
|
||
{
|
||
if ((iCenterBack > iCenterMiddle && g_come_direction == DIRECTION_LEFT) ||
|
||
(iCenterBack < iCenterMiddle && g_come_direction == DIRECTION_RIGHT))
|
||
{
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 检测到火车倒车";
|
||
return TRAINSTATUS_BACK;
|
||
}
|
||
else
|
||
{
|
||
LogDebug << "frameId:" << this->pInferenceResultDataPre_->iFrameId << " 正常行驶";
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// LogDebug << "frameId:" << pProcessData->iFrameId << " back2";
|
||
return iTrainStatus_;
|
||
}
|
||
}
|
||
// LogDebug << "frameId:" << pProcessData->iFrameId << " iNotChgCount_:" << iNotChgCount_ << " run run";
|
||
return TRAINSTATUS_RUN;
|
||
}
|
||
|
||
/**
|
||
* 计算行车方向新
|
||
*/
|
||
void TrainStep1FilterEngine::calculateDirection()
|
||
{
|
||
/*
|
||
连续3帧同目标识别框信息
|
||
判断位置差异是否超过10px(判停车参数),且两两之间都是线性。如果符合则计算方向。
|
||
上述条件不符合则剔除第一个元素,再次累计连续3帧处理。
|
||
*/
|
||
|
||
for (auto iter = this->pInferenceResultDataPre_->vecSingleData.begin();
|
||
iter != this->pInferenceResultDataPre_->vecSingleData.end(); iter++)
|
||
{
|
||
// 火车车头和集装箱号 暂不参与方向判断
|
||
if (iter->iClassId == CONTAINERNUM
|
||
|| iter->iClassId == TRAIN_HEAD) continue;
|
||
|
||
CalculateInfo calInfo;
|
||
calInfo.iFrameId = this->pInferenceResultDataPre_->iFrameId;
|
||
calInfo.iBigClassId = iter->iClassId;
|
||
calInfo.fCenterX = iter->fLTX + (iter->fRBX - iter->fLTX) / 2;
|
||
calInfo.fTargetWidth = iter->fRBX - iter->fLTX;
|
||
|
||
auto iterSubMap = this->mapCalDirection_.find(iter->iClassId);
|
||
if (iterSubMap == this->mapCalDirection_.end())
|
||
{
|
||
std::vector<CalculateInfo> vecTemp;
|
||
this->mapCalDirection_.insert(std::make_pair(iter->iClassId, vecTemp));
|
||
iterSubMap = this->mapCalDirection_.find(iter->iClassId);
|
||
}
|
||
iterSubMap->second.emplace_back(calInfo);
|
||
|
||
if (iterSubMap->second.size() > 2)
|
||
{
|
||
LogDebug << " frameid:" << this->pInferenceResultDataPre_->iFrameId
|
||
<< " last:" << iterSubMap->second.at(2).iFrameId << " " << iterSubMap->second.at(2).fCenterX
|
||
<< " mid:" << iterSubMap->second.at(1).iFrameId << " " << iterSubMap->second.at(1).fCenterX
|
||
<< " pre:" << iterSubMap->second.at(0).iFrameId << " " << iterSubMap->second.at(0).fCenterX;
|
||
//如果帧号连续,且移动位置大于15px,则计算方向
|
||
if (iterSubMap->second.at(2).iFrameId - iterSubMap->second.at(1).iFrameId != 1 ||
|
||
iterSubMap->second.at(1).iFrameId - iterSubMap->second.at(0).iFrameId != 1)
|
||
{
|
||
iterSubMap->second.erase(iterSubMap->second.begin());
|
||
continue;
|
||
}
|
||
if (abs(iterSubMap->second.at(0).fTargetWidth -
|
||
iterSubMap->second.at(2).fTargetWidth) >= 1.5*this->identifyConfig_.iChkstopPx) {
|
||
iterSubMap->second.erase(iterSubMap->second.begin());
|
||
continue;
|
||
}
|
||
|
||
int iLast = iterSubMap->second.at(2).fCenterX;
|
||
int iMid = iterSubMap->second.at(1).fCenterX;
|
||
int iPre = iterSubMap->second.at(0).fCenterX;
|
||
if (abs(iPre - iLast) <= this->identifyConfig_.iChkstopPx)
|
||
{
|
||
iterSubMap->second.erase(iterSubMap->second.begin());
|
||
continue;
|
||
}
|
||
if (iPre <= iMid && iMid <= iLast)
|
||
{
|
||
g_come_direction = DIRECTION_RIGHT;
|
||
}
|
||
else if (iPre >= iMid && iMid >= iLast)
|
||
{
|
||
g_come_direction = DIRECTION_LEFT;
|
||
}
|
||
else
|
||
{
|
||
iterSubMap->second.erase(iterSubMap->second.begin());
|
||
continue;
|
||
}
|
||
|
||
// LogDebug << " frameid:" << pInferenceResultDataPre_->iFrameId << " iDirection_:" << g_come_direction;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TrainStep1FilterEngine::sendComeTrain(const std::string strTrainDate, const std::string strTrainName, const int iDirection) {
|
||
std::string message = "{\"cometime\":\"" + strTrainDate + " " + strTrainName + "\",\"type\":\"1\",\"direction\":" + std::to_string(iDirection == this->dataSourceConfig_.iDirection ? 1:-1) + "}";
|
||
LogWarn << message;
|
||
outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_1"]->push(std::static_pointer_cast<void>(std::make_shared<std::string>(message)));
|
||
}
|
||
|
||
/**
|
||
* 根据当前帧数据,处理上一帧数据
|
||
* inParam : std::shared_ptr<ProcessData> pProcessData :当前帧数据
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainStep1FilterEngine::dealProcessDataPre(std::shared_ptr<InferenceResultData> pInferenceResultData)
|
||
{
|
||
/*
|
||
目标框是否是连续识别,只识别到一帧的目标框认为误识别,过滤掉。
|
||
判断上一帧,当前帧 是否有框
|
||
上一帧有框,当前帧有框,说明连续识别,正常处理。
|
||
上一帧有框,当前帧无框,则非连续识别,过滤大框
|
||
上一帧无框,当前帧有框,则连续识别个数置零。
|
||
上一帧无框,当前帧无框,则连续识别个数置零。
|
||
*/
|
||
|
||
if (!this->pInferenceResultDataPre_) return;
|
||
|
||
int iHeadContinueCnt = 0;
|
||
int iProContinueCnt = 0;
|
||
int iNumContinueCnt = 0;
|
||
int iSpaceContinueCnt = 0;
|
||
int iTrainSpaceContinueCnt = 0;
|
||
int iContainerContinueCnt = 0;
|
||
|
||
for (int i = 0; i < pInferenceResultData->vecSingleData.size(); i++)
|
||
{
|
||
if (pInferenceResultData->vecSingleData[i].iTargetType == HEAD)
|
||
{
|
||
iHeadContinueCnt++;
|
||
}
|
||
else if (pInferenceResultData->vecSingleData[i].iTargetType == PRO)
|
||
{
|
||
iProContinueCnt++;
|
||
}
|
||
else if (pInferenceResultData->vecSingleData[i].iTargetType == NUM)
|
||
{
|
||
iNumContinueCnt++;
|
||
}
|
||
else if (pInferenceResultData->vecSingleData[i].iTargetType == SPACE)
|
||
{
|
||
iSpaceContinueCnt++;
|
||
}
|
||
else if (pInferenceResultData->vecSingleData[i].iTargetType == TRAINSPACE)
|
||
{
|
||
iTrainSpaceContinueCnt++;
|
||
}
|
||
else if (pInferenceResultData->vecSingleData[i].iTargetType == CONTAINER)
|
||
{
|
||
iContainerContinueCnt++;
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < this->pInferenceResultDataPre_->vecSingleData.size(); i++)
|
||
{
|
||
if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == HEAD)
|
||
{
|
||
iHeadContinueCnt++;
|
||
}
|
||
else if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == PRO)
|
||
{
|
||
iProContinueCnt++;
|
||
}
|
||
else if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == NUM)
|
||
{
|
||
iNumContinueCnt++;
|
||
}
|
||
else if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == SPACE)
|
||
{
|
||
iSpaceContinueCnt++;
|
||
}
|
||
else if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == TRAINSPACE)
|
||
{
|
||
iTrainSpaceContinueCnt++;
|
||
}
|
||
else if (this->pInferenceResultDataPre_->vecSingleData[i].iTargetType == CONTAINER)
|
||
{
|
||
iContainerContinueCnt++;
|
||
}
|
||
}
|
||
|
||
//非连续识别的情况,认为误识别,剔除误识别的大框信息
|
||
for (std::vector<SingleData>::iterator it = pInferenceResultDataPre_->vecSingleData.begin(); it != pInferenceResultDataPre_->vecSingleData.end();)
|
||
{
|
||
if (iHeadContinueCnt < 2 && it->iTargetType == HEAD)
|
||
{
|
||
LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " Head 框因非连续识别而过滤";
|
||
it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
continue;
|
||
}
|
||
if (iProContinueCnt < 2 && it->iTargetType == PRO)
|
||
{
|
||
LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " PRO 框因非连续识别而过滤";
|
||
it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
continue;
|
||
}
|
||
if (iNumContinueCnt < 2 && it->iTargetType == NUM)
|
||
{
|
||
LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " NUM 框因非连续识别而过滤";
|
||
it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
continue;
|
||
}
|
||
if (iSpaceContinueCnt < 2 && it->iTargetType == SPACE)
|
||
{
|
||
LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " SPACE 框因非连续识别而过滤";
|
||
it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
continue;
|
||
}
|
||
if (iTrainSpaceContinueCnt < 2 && it->iTargetType == TRAINSPACE)
|
||
{
|
||
LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " TRAINSPACE 框因非连续识别而过滤";
|
||
it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
continue;
|
||
}
|
||
// if (iTrainSpaceContinueCnt < 2 && it->iTargetType == CONTAINER)
|
||
// {
|
||
// LogDebug << " frameId:" << pInferenceResultDataPre_->iFrameId << " CONTAINER 框因非连续识别而过滤";
|
||
// it = pInferenceResultDataPre_->vecSingleData.erase(it);
|
||
// continue;
|
||
// }
|
||
it++;
|
||
}
|
||
|
||
//判定行驶方向, 记录Direction文件信息
|
||
if (g_come_direction == DIRECTION_UNKNOWN)
|
||
{
|
||
LogInfo << "暂未判断出来车方向";
|
||
this->calculateDirection();
|
||
// if (g_come_direction != DIRECTION_UNKNOWN) this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_);
|
||
}
|
||
|
||
if (g_come_direction != DIRECTION_UNKNOWN)
|
||
{
|
||
std::string strFilePath = this->baseConfig_.strDebugResultPath + "/"
|
||
+ pInferenceResultDataPre_->strTrainDate + "/"
|
||
+ StringUtil::getins()->replace_all_distinct(pInferenceResultDataPre_->strTrainTime, ":", "-") + "/"
|
||
+ "jpg/"
|
||
+ std::to_string(pInferenceResultDataPre_->iFrameId) + ".json";
|
||
Json::Value jvJsonInfo;
|
||
if (!this->readJson(strFilePath, jvJsonInfo, 10))
|
||
{
|
||
LogError << "读取JSON失败,需检查是否占用";
|
||
}
|
||
jvJsonInfo["direction"] = g_come_direction.load();
|
||
if (!FileUtil::getins()->writeJsonInfo(jvJsonInfo, strFilePath))
|
||
{
|
||
LogError << "来车方向存储失败:" << strFilePath;
|
||
}
|
||
else
|
||
{
|
||
LogDebug << "来车方向为(1左,2右):" << g_come_direction;
|
||
}
|
||
}
|
||
|
||
//主摄像头校验是否停车
|
||
int iTrainStatusTemp = iTrainStatus_;
|
||
|
||
iTrainStatus_ = this->getTrainStatus();
|
||
|
||
iTrainStatusTemp = iTrainStatus_;
|
||
|
||
if (iTrainStatus_ == TRAINSTATUS_STOP)
|
||
{
|
||
//停车
|
||
}
|
||
else if (iTrainStatus_ == TRAINSTATUS_BACK)
|
||
{
|
||
//倒车
|
||
addBackInfo();
|
||
iTrainStatusTemp = TRAINSTATUS_STOP;
|
||
}
|
||
else if(iTrainStatus_ == TRAINSTATUS_RUN)
|
||
{
|
||
/*
|
||
正向行驶需先把倒车产生的倒车数据处理完毕,即使车辆回到原倒车点,再开始识别行驶数据
|
||
*/
|
||
if(!this->isEndDealBackInfo())
|
||
{
|
||
iTrainStatusTemp = TRAINSTATUS_STOP;
|
||
}
|
||
}
|
||
LogDebug << " 帧:" << this->pInferenceResultDataPre_->iFrameId
|
||
<< " 火车实时运行状态:" << iTrainStatus_ << "(0无车,1运行,2停车,3倒车) 转换后运行状态:" << iTrainStatusTemp;
|
||
this->pInferenceResultDataPre_->iTrainStatus = iTrainStatusTemp;
|
||
|
||
// this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_);
|
||
|
||
//上一帧,push端口0
|
||
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pInferenceResultDataPre_));
|
||
}
|
||
|
||
bool TrainStep1FilterEngine::readJson(std::string &strFilePath, Json::Value &jvInfo, int i)
|
||
{
|
||
i--;
|
||
if (access(strFilePath.c_str(), F_OK) != 0)
|
||
{
|
||
LogWarn << "文件:" << strFilePath << " 不存在";
|
||
return i > 0 ? this->readJson(strFilePath, jvInfo, i) : false;
|
||
}
|
||
|
||
if (!FileUtil::getins()->readJsonInfo(jvInfo, strFilePath))
|
||
{
|
||
LogError << "读取json文件失败:" << strFilePath;
|
||
return i > 0 ? this->readJson(strFilePath, jvInfo, i) : false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
APP_ERROR TrainStep1FilterEngine::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<InferenceResultData> pInferenceResultData = std::static_pointer_cast<InferenceResultData>(pVoidData0);
|
||
|
||
// 不识别集装箱的情况下,1帧最多识别4个大框。[(车头、车厢间隔、间隔、车号); (车号、车厢间隔、间隔、属性)]
|
||
if (pInferenceResultData->vecSingleData.size() > 5 && !this->identifyConfig_.bContainerDetect)
|
||
{
|
||
LogWarn << " frameId:" << pInferenceResultData->iFrameId
|
||
<< " 识别到的目标个数超出预期 size:" << pInferenceResultData->vecSingleData.size();
|
||
pInferenceResultData->vecSingleData.clear();
|
||
continue;
|
||
}
|
||
// 识别集装箱的情况下,1帧最多识别5个大框。[(车头、车厢间隔、间隔、车号、集装箱); (车号、车厢间隔、间隔、属性、集装箱)]
|
||
if (pInferenceResultData->vecSingleData.size() > 5 && this->identifyConfig_.bContainerDetect)
|
||
{
|
||
LogWarn << " frameId:" << pInferenceResultData->iFrameId
|
||
<< " 识别到的目标个数超出预期 size:" << pInferenceResultData->vecSingleData.size();
|
||
pInferenceResultData->vecSingleData.clear();
|
||
continue;
|
||
}
|
||
|
||
// 根据当前帧数据,处理上一帧数据
|
||
this->dealProcessDataPre(pInferenceResultData);
|
||
|
||
this->pInferenceResultDataPre_ = pInferenceResultData;
|
||
|
||
if (pInferenceResultData->bIsEnd)
|
||
{
|
||
// 结束帧,push端口0
|
||
LogDebug << " frameid:" << pInferenceResultData->iFrameId << " isEnd:" << pInferenceResultData->bIsEnd;
|
||
outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pInferenceResultData), true);
|
||
this->initParam();
|
||
}
|
||
}
|
||
return APP_ERR_OK;
|
||
}
|
||
|