generated from zhangwei/Train_Identify
1685 lines
62 KiB
C++
1685 lines
62 KiB
C++
#include "TrainAnaEngine.h"
|
||
|
||
#define SHOW_RECTANGLE
|
||
|
||
using namespace ai_matrix;
|
||
|
||
unsigned int num=0;
|
||
|
||
TrainAnaEngine::TrainAnaEngine() {}
|
||
|
||
TrainAnaEngine::~TrainAnaEngine() {}
|
||
|
||
APP_ERROR TrainAnaEngine::Init()
|
||
{
|
||
LogInfo << "TrainAnaEngine Init start";
|
||
// 初始化相机帧率
|
||
nFrameRate = FRAME_RATE;
|
||
nRecIndex = 0;
|
||
nPicAreaChangeing = 0x00;
|
||
|
||
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
|
||
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
|
||
dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_);
|
||
strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path");
|
||
strResultPath_for_test = MyYaml::GetIns()->GetPathValue("gc_result_path_for_test");
|
||
|
||
// 获取算法参数的文件路径
|
||
std::string strsettingpath = MyYaml::GetIns()->GetStringValue("method_setting");
|
||
// 读取算法参数的内容
|
||
getsetting(strsettingpath);
|
||
// 获取动态检测参数的数量
|
||
int nMethodCount = lstAction.size();
|
||
// LogInfo << "TrainAnaEngine Init method list count:" << nMethodCount;
|
||
if (nMethodCount > 2)
|
||
{
|
||
//计算变化值
|
||
nRightComeFlagR3 = 0x00000001 << (lstAction.size() - 3);
|
||
nRightComeFlagR2 = 0x00000001 << (lstAction.size() - 2) + nRightComeFlagR3;
|
||
nRightComeFlagR1 = 0x00000001 << (lstAction.size() - 1) + nRightComeFlagR2;
|
||
// LogInfo << "TrainAnaEngine Init nRightComeFlagR3:" << nRightComeFlagR3;
|
||
// LogInfo << "TrainAnaEngine Init nRightComeFlagR2:" << nRightComeFlagR2;
|
||
// LogInfo << "TrainAnaEngine Init nRightComeFlagR1:" << nRightComeFlagR1;
|
||
}
|
||
// 获取尾部车钩的偏移量
|
||
nTailPixOffset = getTailPixOffset();
|
||
// LogInfo << "TrainAnaEngine Init nTailPixOffset:" << nTailPixOffset;
|
||
//初始化来车检测状态
|
||
nStatus=TRAIN_INIT_STATUS;
|
||
// 初始化引擎相关的参数
|
||
vResetPartion();
|
||
|
||
LogInfo << "TrainAnaEngine Init ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
APP_ERROR TrainAnaEngine::DeInit()
|
||
{
|
||
LogInfo << "TrainAnaEngine DeInit ok";
|
||
return APP_ERR_OK;
|
||
}
|
||
|
||
|
||
/**
|
||
* 参数初始化(列车结束时需调用)
|
||
* inParam : N/A
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainAnaEngine::InitParam()
|
||
{
|
||
LogInfo << "TrainAnaEngine InitParam start";
|
||
strTrainData_ = "";
|
||
strTrainName_ = "";
|
||
LogInfo << "TrainAnaEngine InitParam end";
|
||
}
|
||
|
||
|
||
/**
|
||
* 初始化车厢分割信息
|
||
* inParam : N/A
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainAnaEngine::vResetPartion()
|
||
{
|
||
LogInfo << "TrainAnaEngine vResetPartion start";
|
||
InitParam();
|
||
// //行车状态为初始化
|
||
// nStatus = TRAIN_INIT_STATUS;
|
||
// nPreStatus = TRAIN_INIT_STATUS;
|
||
|
||
//设定检测动态区域均为未发生变化
|
||
nPicAreaChangeing = 0x00;
|
||
nPrePicAreaChangeing = 0x00;
|
||
//清空车厢划分列表
|
||
lstPartInfo.clear();
|
||
//初始化开始帧
|
||
nLatestFrame = 0;
|
||
|
||
// 根据帧率计算检测到车钩以后忽略检测的帧数
|
||
// 1.默认车辆3.9秒通过
|
||
// 2.默认车体长度 14.5(TRAIN_WIDTH)
|
||
// 3.单位:米/秒
|
||
fdefaultspeed = (TRAIN_WIDTH / 3.9);
|
||
|
||
// 车体的三分之一作为忽略标准
|
||
// 车体三分之一的通过时间
|
||
float fpasstime = (TRAIN_WIDTH / 3.0) / fdefaultspeed;
|
||
// 忽略帧数:时间*帧率
|
||
nSamePartionIgnoreCount = fpasstime * nFrameRate;
|
||
|
||
nPartionPassFrameCount = 0;
|
||
|
||
LogInfo << "TrainAnaEngine vResetPartion start";
|
||
}
|
||
|
||
/**
|
||
* 格式化算分配置文件内容
|
||
* inParam : 单个算法配置分割后的字符信息
|
||
* outParam: 结构化的算法配置信息
|
||
* return : N/A
|
||
*/
|
||
void TrainAnaEngine::vformatStructAnalyseInfo(std::vector<std::string> elems, AnalyseInfo &info)
|
||
{
|
||
LogInfo << "TrainAnaEngine vformatStructAnalyseInfo start";
|
||
//以下内容为文件读取的结果
|
||
//算法类型 1动态检测 2车厢划分
|
||
info.nType = -1;
|
||
//检测敏感区域开始位置的X值
|
||
info.nAreaX1 = -1;
|
||
//检测敏感区域开始位置的Y值
|
||
info.nAreaY1 = -1;
|
||
//检测敏感区域结束位置的X值
|
||
info.nAreaX2 = -1;
|
||
//检测敏感区域结束位置的Y值
|
||
info.nAreaY2 = -1;
|
||
//算法结果等级相同做AND处理,不同做OR处理
|
||
info.bOrLevel = -1;
|
||
//是否以不同作为判断结果
|
||
info.bDiff = false;
|
||
//算法是否有效 1有效 0无效
|
||
info.bOn = false;
|
||
//判断相同的阈值
|
||
info.dSameThresholdVal = 0.0;
|
||
//判断不同的阈值
|
||
info.dDiffThresholdVal = 0.0;
|
||
//判断停车的累计帧数阈值
|
||
info.nPauseMaxCoumt = 0;
|
||
//图像增强的算法(位运算)
|
||
//0x01 灰度化
|
||
//0x02 直方图均衡化
|
||
//0x04 自定义
|
||
info.npicimprovetype = -1;
|
||
//OPENCV模板对比算法
|
||
info.templemethod = -1;
|
||
//直方图对比算法
|
||
info.histmethod = -1;
|
||
//自定义算法
|
||
info.specmethod = -1;
|
||
//图像比对的方法(位运算)
|
||
//0x01 OPENCV模板对比
|
||
//0x02 直方图对比
|
||
//0x04 自定义
|
||
info.compmethod = -1;
|
||
//对比的基准图的路径
|
||
info.baseImagePath = "";
|
||
|
||
//以下内容为初始化结果
|
||
//图像对比数值
|
||
info.dComparePoint = 0.0;
|
||
//上一帧对比数值
|
||
info.dPreComparePoint = 0.0;
|
||
//图像与基础状态是否发生变化
|
||
info.bChanged = 0.0;
|
||
//上一帧图像与基础状态是否发生变化
|
||
info.bPreChanged = 0.0;
|
||
//图像变化后(保持在一个平衡状态即值不变的状态)累计值
|
||
info.nSameCount = 0;
|
||
|
||
char *chrevptr;
|
||
if (elems.size() == IMAGEANALYSE_NUM)
|
||
{
|
||
info.nType = atoi(elems[0].c_str());
|
||
info.nAreaX1 = atoi(elems[1].c_str());
|
||
info.nAreaY1 = atoi(elems[2].c_str());
|
||
info.nAreaX2 = atoi(elems[3].c_str());
|
||
info.nAreaY2 = atoi(elems[4].c_str());
|
||
info.bOrLevel = atoi(elems[5].c_str());
|
||
info.bDiff = (atoi(elems[6].c_str()) == 1) ? true : false;
|
||
info.bOn = (atoi(elems[7].c_str()) == 1) ? true : false;
|
||
info.dSameThresholdVal = strtod(elems[8].c_str(), &chrevptr);
|
||
info.dDiffThresholdVal = strtod(elems[9].c_str(), &chrevptr);
|
||
info.nPauseMaxCoumt = atoi(elems[10].c_str());
|
||
info.npicimprovetype = atoi(elems[11].c_str());
|
||
info.templemethod = atoi(elems[12].c_str());
|
||
info.histmethod = atoi(elems[13].c_str());
|
||
info.specmethod = atoi(elems[14].c_str());
|
||
info.compmethod = atoi(elems[15].c_str());
|
||
info.baseImagePath = elems[16];
|
||
}
|
||
LogInfo << "TrainAnaEngine vformatStructAnalyseInfo end";
|
||
}
|
||
|
||
/**
|
||
* 获取图像比对的结果值
|
||
* inParam : 算法配置信息
|
||
* inParam : 当前图像的Mat值
|
||
* inParam : 比对基础图像的Mat值
|
||
* outParam: N/A
|
||
* return : 比对值的数组
|
||
*/
|
||
std::vector<double> TrainAnaEngine::getCompPoint(AnalyseInfo info, cv::Mat baseimg, cv::Mat tarpic)
|
||
{
|
||
LogInfo << "TrainAnaEngine getCompPoint start";
|
||
std::vector<double> dRetVal;
|
||
cv::Point cvOutPoint;
|
||
|
||
LogInfo << "TrainAnaEngine getCompPoint info.compmethod:" << info.compmethod;
|
||
if ((info.compmethod & IMAGE_COMP_BY_SPEC) == IMAGE_COMP_BY_SPEC)
|
||
{
|
||
double dHistPoint = anapicbySpec(baseimg);
|
||
dRetVal.push_back(dHistPoint);
|
||
}
|
||
//OPENCV模型比对方法
|
||
if ((info.compmethod & IMAGE_COMP_BY_TEMPLE) == IMAGE_COMP_BY_TEMPLE)
|
||
{
|
||
double dtemplePoint = anapicbyTemple(baseimg, tarpic, info.templemethod, cvOutPoint);
|
||
dRetVal.push_back(dtemplePoint);
|
||
}
|
||
//直方图比对方法
|
||
if ((info.compmethod & IMAGE_COMP_BY_HIST) == IMAGE_COMP_BY_HIST)
|
||
{
|
||
double dHistPoint = anapicbyHist(baseimg, tarpic, info.histmethod);
|
||
dRetVal.push_back(dHistPoint);
|
||
}
|
||
|
||
|
||
LogInfo << "TrainAnaEngine getCompPoint end:" << dRetVal[0];
|
||
return dRetVal;
|
||
}
|
||
|
||
/**
|
||
* 获取算法配置文件的内容
|
||
* inParam : 算法配置文件路径
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainAnaEngine::getsetting(string strFilePath)
|
||
{
|
||
//LogInfo << "TrainAnaEngine getsetting start";
|
||
std::string strLineInfo;
|
||
std::ifstream finfile(strFilePath);
|
||
int nindex = 0;
|
||
//按行读取
|
||
while (std::getline(finfile, strLineInfo))
|
||
{
|
||
//LogInfo << "TrainAnaEngine getsetting nindex:" << nindex;
|
||
//首行作为注释不读取
|
||
if (nindex == 0)
|
||
{
|
||
nindex++;
|
||
continue;
|
||
}
|
||
nindex++;
|
||
std::vector<std::string> elems;
|
||
//每行以逗号, 作为分隔符
|
||
elems = MyUtils::getins()->split(strLineInfo, ",");
|
||
|
||
AnalyseInfo strTempInfo;
|
||
//根据逗号分割的列表数据 初始化算法配置信息
|
||
vformatStructAnalyseInfo(elems, strTempInfo);
|
||
//LogInfo << "TrainAnaEngine getsetting strTempInfo.nType :" << strTempInfo.nType ;
|
||
//保存动态检测的算法到集合中
|
||
if (strTempInfo.nType == TRAIN_ACTION)
|
||
{
|
||
lstAction.push_back(strTempInfo);
|
||
}
|
||
//保存车厢划分的算法到集合中
|
||
else if(strTempInfo.nType == TRAIN_PARTION)
|
||
{
|
||
lstPartion.push_back(strTempInfo);
|
||
}
|
||
}
|
||
//LogInfo << "TrainAnaEngine getsetting end";
|
||
}
|
||
|
||
/**
|
||
* 根据直方图做比对
|
||
* inParam : 当前图像的Mat值
|
||
* inParam : 比对基础图像的Mat值
|
||
* inParam : 比对算法
|
||
* outParam: N/A
|
||
* return : 比对值
|
||
*/
|
||
double TrainAnaEngine::anapicbySpec(cv::Mat baseimg)
|
||
{
|
||
LogInfo << "TrainAnaEngine anapicbySpec start";
|
||
double match = 0.0;
|
||
int nmean = 0;
|
||
Mat tmp_m, tmp_sd;
|
||
cv::Mat mtTempImage = mtresizeImage(baseimg, (int)(baseimg.cols / 4), (int)(baseimg.rows / 4));
|
||
|
||
|
||
cv::Mat mtOutImage;
|
||
cv::meanStdDev(mtTempImage, tmp_m, tmp_sd);
|
||
nmean = (int)tmp_m.at<double>(0,0);
|
||
int nwidth = mtTempImage.cols;
|
||
int nHeight = mtTempImage.rows;
|
||
std::vector<int> elems;
|
||
int nmax = 0;
|
||
int nmin = 0;
|
||
for(int i = 0;i < nHeight;i++) {
|
||
int ncheckval = 0;
|
||
for(int j = 0; j < nwidth;j++) {
|
||
ncheckval = ncheckval + mtTempImage.at<uchar>(i,j);
|
||
}
|
||
ncheckval = (int)(ncheckval / nwidth) - nmean;
|
||
if(ncheckval > nmax){
|
||
nmax = ncheckval;
|
||
}
|
||
if(ncheckval < nmin){
|
||
nmin = ncheckval;
|
||
}
|
||
elems.push_back(ncheckval);
|
||
}
|
||
|
||
int nstartindex = 6;
|
||
int nendindex = 24;
|
||
int nblackcount = 0;
|
||
for(int i = nstartindex + 1;i < nendindex;i++) {
|
||
if(elems[i] < 0 && elems[i - 1] < 0){
|
||
nblackcount++;
|
||
} else {
|
||
//nblackcount = 0;
|
||
}
|
||
}
|
||
LogInfo << "TrainAnaEngine anapicbySpec nblackcount:" << nblackcount;
|
||
if (nblackcount > ((nendindex - nstartindex) / 2)) {
|
||
for(int i = 0;i < nHeight;i++) {
|
||
elems[i] = 0 - elems[i];
|
||
}
|
||
}
|
||
|
||
int nfirstpot = -1;
|
||
int nsecondpot = -1;
|
||
int nthirdpot = -1;
|
||
int nfirstpotsum = 0;
|
||
int nsecondpotsum = 0;
|
||
int nthirdpotsum = 0;
|
||
|
||
int npremax = 0;
|
||
int npremin = 0;
|
||
int nfirstmax = 0;
|
||
int nfirstmin = 0;
|
||
int nsecondmax = 0;
|
||
int nsecondmin = 0;
|
||
|
||
for(int i = 2; i < nHeight; i++) {
|
||
LogInfo << "TrainAnaEngine elems[i] :" << elems[i];
|
||
if (elems[i -2] < elems[i - 1] && elems[i - 1] < elems[i] && nfirstpot == -1 && elems[i] > 0) {
|
||
nfirstpot = i;
|
||
}
|
||
if (nfirstpot == -1) {
|
||
if(npremax < elems[i]){
|
||
npremax = elems[i];
|
||
}
|
||
if(npremin > elems[i]){
|
||
npremin = elems[i];
|
||
}
|
||
continue;
|
||
}
|
||
if (elems[i -2] > elems[i - 1] && elems[i - 1] > elems[i] && nsecondpot == -1 && elems[i] < 0) {
|
||
nsecondpot = i;
|
||
}
|
||
if (nsecondpot == -1 && elems[i] > 0) {
|
||
nfirstpotsum++;
|
||
if(nfirstmax < elems[i]){
|
||
nfirstmax = elems[i];
|
||
}
|
||
if(nfirstmin > elems[i]){
|
||
nfirstmin = elems[i];
|
||
}
|
||
}
|
||
if (nsecondpot == -1) {
|
||
continue;
|
||
}
|
||
if (nthirdpot == -1 && elems[i] < 0) {
|
||
nsecondpotsum++;
|
||
if(nsecondmax < elems[i]){
|
||
nsecondmax = elems[i];
|
||
}
|
||
if(nsecondmin > elems[i]){
|
||
nsecondmin = elems[i];
|
||
}
|
||
}
|
||
if (elems[i -2] < elems[i - 1] && elems[i - 1] < elems[i] && nthirdpot == -1 && elems[i] > 0) {
|
||
nthirdpot = i;
|
||
}
|
||
if (nthirdpot != -1) {
|
||
nthirdpotsum++;
|
||
}
|
||
}
|
||
|
||
LogInfo << "TrainAnaEngine nHeight :" << nHeight;
|
||
LogInfo << "TrainAnaEngine nfirstpot :" << nfirstpot;
|
||
LogInfo << "TrainAnaEngine nsecondpot :" << nsecondpot;
|
||
LogInfo << "TrainAnaEngine nthirdpot :" << nthirdpot;
|
||
LogInfo << "TrainAnaEngine nmax :" << nmax;
|
||
LogInfo << "TrainAnaEngine nmin :" << nmin;
|
||
LogInfo << "TrainAnaEngine npremin :" << npremin;
|
||
LogInfo << "TrainAnaEngine npremax :" << npremax;
|
||
LogInfo << "TrainAnaEngine nfirstmax :" << nfirstmax;
|
||
LogInfo << "TrainAnaEngine nfirstmin :" << nfirstmin;
|
||
LogInfo << "TrainAnaEngine nsecondmax :" << nsecondmax;
|
||
LogInfo << "TrainAnaEngine nsecondmin :" << nsecondmin;
|
||
if (
|
||
(nfirstpot < (int)(nHeight / 3))
|
||
&& (nsecondpot > (int)(nHeight / 2)) && (nsecondpot < (int)(nHeight *2 / 3))
|
||
&& (nthirdpot > (int)(nHeight * 3/ 4))
|
||
&& (npremin < 0)
|
||
&& (nfirstmax > 0)
|
||
&& (nsecondmin < 0)
|
||
//&& (nfirstpotsum > (nsecondpot - nfirstpot - 2))
|
||
//&& (nsecondpotsum > (nthirdpot - nsecondpot - 2))
|
||
//&& (nthirdpotsum >= (nHeight - nthirdpot - 1))
|
||
//&& (nmax- nfirstmax > nmax/2)
|
||
//&& (nsecondmin < nmin/2)
|
||
){
|
||
match = 1.0;
|
||
double firstsinoffset = 180.0/nfirstpot;
|
||
double secondsinoffset = 180.0/(nsecondpot - nfirstpot);
|
||
double thirdsinoffset = 180.0/(nthirdpot - nsecondpot);
|
||
double dbaseoffset = 1.0 / (nHeight * 1.0);
|
||
double dmaxoffset = (nmax-nmin) * 1.0 ;
|
||
LogInfo << "TrainAnaEngine firstsinoffset :" << firstsinoffset;
|
||
LogInfo << "TrainAnaEngine secondsinoffset :" << secondsinoffset;
|
||
LogInfo << "TrainAnaEngine thirdsinoffset :" << thirdsinoffset;
|
||
LogInfo << "TrainAnaEngine dbaseoffset :" << dbaseoffset;
|
||
LogInfo << "TrainAnaEngine dmaxoffset :" << dmaxoffset;
|
||
double dtmp = 0.0;
|
||
for (int i = 0; i < nHeight; i++) {
|
||
if (i < nfirstpot){
|
||
dtmp = dbaseoffset * abs(elems[i] - sin((i)*firstsinoffset)*(npremin* 1.0))/ dmaxoffset;
|
||
} else if(i>= nfirstpot && i < nsecondpot){
|
||
dtmp = dbaseoffset * abs(elems[i] - sin((i - nfirstpot)*secondsinoffset)*(nfirstmax * 1.0)) / dmaxoffset;
|
||
} else if(i>= nsecondpot && i < nthirdpotsum){
|
||
dtmp = dbaseoffset * abs(elems[i] - sin((i - nsecondpot)*thirdsinoffset)*(nsecondmin * 1.0)) / dmaxoffset;
|
||
} else if(i >= nthirdpotsum){
|
||
dtmp = 0.0;
|
||
}
|
||
LogInfo << "TrainAnaEngine befor match :" << match;
|
||
LogInfo << "TrainAnaEngine dtmp :" << dtmp;
|
||
match = match - dtmp;
|
||
LogInfo << "TrainAnaEngine after match :" << match;
|
||
}
|
||
//match = 1.0;
|
||
}
|
||
if (strResultPath_for_test != "")
|
||
{
|
||
std::ostringstream ossfloat,ossint;
|
||
ossfloat<<(int)(match * 1000);
|
||
ossint<<ncurtime;
|
||
std::string strscore(ossfloat.str());
|
||
std::string strindex(ossint.str());
|
||
std::string strtestpath = strResultPath_for_test + strindex + "_______" + strscore + ".jpg";
|
||
LogInfo << "TrainAnaEngine anapicbySpec image to" << strtestpath;
|
||
cv::imwrite(strtestpath, mtTempImage);
|
||
|
||
}
|
||
LogInfo << "TrainAnaEngine anapicbySpec end:" << match;
|
||
return match;
|
||
}
|
||
|
||
/**
|
||
* 根据直方图做比对
|
||
* inParam : 当前图像的Mat值
|
||
* inParam : 比对基础图像的Mat值
|
||
* inParam : 比对算法
|
||
* outParam: N/A
|
||
* return : 比对值
|
||
*/
|
||
double TrainAnaEngine::anapicbyHist(cv::Mat baseimg, cv::Mat tarpic, int method)
|
||
{
|
||
LogInfo << "TrainAnaEngine anapicbyHist start";
|
||
float hranges[] = {0, 180};
|
||
float sranges[] = {0, 255};
|
||
const float *ranges[] = {hranges, sranges};
|
||
int hbins = 60, sbins = 64;
|
||
int histSize[] = {hbins, sbins};
|
||
int channels[] = {0};
|
||
cv::Mat hist1, hist2;
|
||
//获取直方图信息
|
||
cv::calcHist(&baseimg, 1, channels, Mat(), hist1, 2, histSize, ranges);
|
||
cv::calcHist(&tarpic, 1, channels, Mat(), hist2, 2, histSize, ranges);
|
||
|
||
double match = cv::compareHist(hist1, hist2, method);
|
||
LogInfo << "TrainAnaEngine anapicbyHist end:" << match;
|
||
return match;
|
||
}
|
||
|
||
/**
|
||
* 根据模板做比对
|
||
* inParam : 当前图像的Mat值
|
||
* inParam : 比对基础图像的Mat值
|
||
* inParam : 比对算法
|
||
* outParam: 目标的坐标
|
||
* return : 比对值
|
||
*/
|
||
double TrainAnaEngine::anapicbyTemple(cv::Mat baseimg, cv::Mat tarpic, int method, cv::Point &pPos)
|
||
{
|
||
LogInfo << "TrainAnaEngine anapicbyTemple start";
|
||
double dRetVal = 0.0;
|
||
cv::Mat img_match;
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple baseimg.cols:" << baseimg.cols;
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple baseimg.rows:" << baseimg.rows;
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple tarpic.cols:" << tarpic.cols;
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple tarpic.rows:" << tarpic.rows;
|
||
|
||
cv::matchTemplate(baseimg, tarpic, img_match, method);
|
||
|
||
double minval, maxval;
|
||
cv::Point minloc, maxloc;
|
||
cv::minMaxLoc(img_match, &minval, &maxval, &minloc, &maxloc);
|
||
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple method:" << method;
|
||
//TM_SQDIFF算法和TM_SQDIFF_NORMED算法最小值为最匹配的数值
|
||
if (
|
||
method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED)
|
||
{
|
||
dRetVal = minval;
|
||
pPos = minloc;
|
||
}
|
||
//TM_CCORR TM_CCORR_NORMED TM_CCOEFF TM_CCOEFF_NORMED算法最大值为最匹配的数值
|
||
else if (
|
||
method == cv::TM_CCORR || method == cv::TM_CCORR_NORMED || method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
|
||
{
|
||
dRetVal = maxval;
|
||
pPos = maxloc;
|
||
}
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple end" << dRetVal;
|
||
//if (strResultPath_for_test != "" && nLatestFrame != 0)
|
||
if(false)
|
||
{
|
||
cv::Mat cvdes = Mat(baseimg.rows, baseimg.cols + tarpic.cols, baseimg.type());
|
||
cv::Mat cvleft = cvdes(cv::Rect(0, 0, baseimg.cols, baseimg.rows));
|
||
baseimg.copyTo(cvleft);
|
||
cv::Mat cvright = cvdes(cv::Rect(baseimg.cols, 0, tarpic.cols, tarpic.rows));
|
||
tarpic.copyTo(cvright);
|
||
|
||
std::ostringstream ossfloat,ossint;
|
||
ossfloat<<(int)(dRetVal*1000);
|
||
ossint<<nLatestFrame;
|
||
std::string strscore(ossfloat.str());
|
||
std::string strindex(ossint.str());
|
||
std::string strtestpath = strResultPath_for_test + strindex + "_" + strscore + ".jpg";
|
||
//LogInfo << "TrainAnaEngine anapicbyTemple image to" << strtestpath;
|
||
cv::imwrite(strtestpath, cvdes);
|
||
|
||
}
|
||
return dRetVal;
|
||
}
|
||
|
||
/**
|
||
* 读取图像文件并转化为Mat值
|
||
* inParam : 读取文件的路径
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtdecodeImageDatabyFile(string path)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtdecodeImageDatabyFile start";
|
||
//LogInfo << "TrainAnaEngine mtdecodeImageDatabyFile path:" << path;
|
||
std::ifstream imagefile(path, std::ios::binary);
|
||
std::vector<char> imagedata;
|
||
imagefile >> std::noskipws;
|
||
std::copy(std::istream_iterator<char>(imagefile), std::istream_iterator<char>(), std::back_inserter(imagedata));
|
||
cv::Mat jpegimage = cv::imdecode(Mat(imagedata), cv::IMREAD_COLOR);
|
||
imagefile.close();
|
||
LogInfo << "TrainAnaEngine mtdecodeImageDatabyFile end";
|
||
return jpegimage;
|
||
}
|
||
|
||
|
||
/**
|
||
* 将图像二进制数据转化为Mat值
|
||
* inParam : 二进制数据指针
|
||
* inParam : 二进制数据长度
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtdecodeImageDatabyBin(LPVOID lpimgdata, int imglen)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtdecodeImageDatabyBin start";
|
||
//LogInfo << "TrainAnaEngine mtdecodeImageDatabyBin imglen:" << imglen;
|
||
const char *buffer = static_cast<char *>(lpimgdata);
|
||
vector<uchar>::size_type size = imglen;
|
||
|
||
std::vector<unsigned char> imagedata(buffer, buffer + size);
|
||
cv::Mat jpegimage = imdecode(imagedata, cv::IMREAD_COLOR);
|
||
LogInfo << "TrainAnaEngine mtdecodeImageDatabyBin end";
|
||
return jpegimage;
|
||
}
|
||
|
||
|
||
/**
|
||
* 图像增强
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : 算法配置信息
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtImproveImage(cv::Mat inImage, AnalyseInfo info, bool bcvread)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtImproveImage start";
|
||
cv::Mat mtOutImage = inImage;
|
||
//cv::Mat mtOutImage;
|
||
int x1 = info.nAreaX1;
|
||
int y1 = info.nAreaY1;
|
||
int width = info.nAreaX2 - info.nAreaX1;
|
||
int height = info.nAreaY2 - info.nAreaY1;
|
||
int type = info.nType;
|
||
int mode = (bcvread == false) ? cv::COLOR_YUV2GRAY_420 : cv::COLOR_RGB2GRAY;
|
||
|
||
//LogInfo << "TrainAnaEngine mtImproveImage x1:"<<x1;
|
||
//LogInfo << "TrainAnaEngine mtImproveImage y1:"<<y1;
|
||
//LogInfo << "TrainAnaEngine mtImproveImage width:"<<width;
|
||
//LogInfo << "TrainAnaEngine mtImproveImage height:"<<height;
|
||
//LogInfo << "TrainAnaEngine mtImproveImage type:"<<type;
|
||
|
||
//图像灰度处理
|
||
if (((info.npicimprovetype & IMAGE_GRAY) == IMAGE_GRAY) && (mode != -1))
|
||
{
|
||
mtOutImage = mtgrayImage(mtOutImage, mode);
|
||
}
|
||
//图像直方图均衡化处理
|
||
if ((info.npicimprovetype & IMAGE_EQUALIZE) == IMAGE_EQUALIZE)
|
||
{
|
||
mtOutImage = mtequalizeImage(mtOutImage);
|
||
}
|
||
//图像进行gamma变换
|
||
if ((info.npicimprovetype & IMAGE_GAMMA) == IMAGE_GAMMA)
|
||
{
|
||
mtOutImage = mtGammaImage(mtOutImage, 1.0);
|
||
}
|
||
//自定义处理
|
||
if ((info.npicimprovetype & IMAGE_SPEC) == IMAGE_SPEC)
|
||
{
|
||
mtOutImage = mtspecImage(mtOutImage);
|
||
}
|
||
LogInfo << "TrainAnaEngine mtImproveImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
/**
|
||
* 修改图像尺寸
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : 目标宽度
|
||
* inParam : 目标高度
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtresizeImage(cv::Mat inImage, int width, int height)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtresizeImage start";
|
||
//LogInfo << "TrainAnaEngine mtresizeImage width:"<<width;
|
||
//LogInfo << "TrainAnaEngine mtresizeImage height:"<<height;
|
||
cv::Mat mtTempImage = inImage;
|
||
cv::Mat mtOutImage;
|
||
|
||
cv::resize(mtTempImage, mtOutImage, cv::Size(width, height));
|
||
LogInfo << "TrainAnaEngine mtresizeImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
/**
|
||
* 裁剪图像
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : 开始位置的X值
|
||
* inParam : 开始位置的Y值
|
||
* inParam : 结束位置的X值
|
||
* inParam : 结束位置的Y值
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtareaImage(cv::Mat inImage, int x1, int y1, int x2, int y2)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtareaImage start";
|
||
//LogInfo << "TrainAnaEngine mtareaImage x1:"<<x1;
|
||
//LogInfo << "TrainAnaEngine mtareaImage y1:"<<y1;
|
||
//LogInfo << "TrainAnaEngine mtareaImage x2:"<<x2;
|
||
//LogInfo << "TrainAnaEngine mtareaImage y2:"<<y2;
|
||
cv::Mat mtTempImage = inImage;
|
||
|
||
cv::Rect recArea = cv::Rect(x1, y1, abs(x2 - x1), abs(y2 - y1));
|
||
cv::Mat mtOutImage = mtTempImage(recArea);
|
||
|
||
//LogInfo << "TrainAnaEngine mtareaImage out cols:"<< mtOutImage.cols;
|
||
//LogInfo << "TrainAnaEngine mtareaImage out rows:"<< mtOutImage.rows;
|
||
LogInfo << "TrainAnaEngine mtareaImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
/**
|
||
* 图像灰度化
|
||
* inParam : 原始图片的Mat值
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtgrayImage(cv::Mat inImage, int mode)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtgrayImage start";
|
||
cv::Mat mtTempImage = inImage;
|
||
cv::Mat mtOutImage;
|
||
cv::cvtColor(mtTempImage, mtOutImage, mode);
|
||
LogInfo << "TrainAnaEngine mtgrayImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
/**
|
||
* 图像直方图均衡化
|
||
* inParam : 原始图片的Mat值
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtequalizeImage(cv::Mat inImage)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtequalizeImage start";
|
||
cv::Mat mtTempImage = inImage;
|
||
cv::Mat mtOutImage;
|
||
|
||
cv::equalizeHist(mtTempImage, mtOutImage);
|
||
LogInfo << "TrainAnaEngine mtequalizeImage end";
|
||
return mtOutImage;
|
||
}
|
||
/**
|
||
* 图像进行gamma变换
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : gamma值
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtGammaImage(cv::Mat inImage, float fgamma = 1.0)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtGammaImage start";
|
||
//LogInfo << "TrainAnaEngine mtGammaImage fgamma:"<<fgamma;
|
||
cv::Mat mtTempImage = inImage;
|
||
cv::Mat mtOutImage;
|
||
|
||
for (int i = 0; i < mtTempImage.rows; i++){
|
||
for (int j = 0; j < mtTempImage.cols; j++) {
|
||
mtTempImage.at<uchar>(i, j) = 6*pow((double)inImage.at<unsigned char>(i, j), fgamma);
|
||
}
|
||
}
|
||
cv::normalize(mtTempImage, mtTempImage, 0, 255, NORM_MINMAX);
|
||
cv::convertScaleAbs(mtTempImage, mtOutImage);
|
||
LogInfo << "TrainAnaEngine mtGammaImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
|
||
/**
|
||
* 图像进行自定义处理
|
||
* inParam : 原始图片的Mat值
|
||
* outParam: N/A
|
||
* return : 图像Mat值
|
||
*/
|
||
cv::Mat TrainAnaEngine::mtspecImage(cv::Mat inImage)
|
||
{
|
||
LogInfo << "TrainAnaEngine mtspecImage start";
|
||
cv::Mat mtTempImage = inImage;
|
||
cv::Mat mtOutImage;
|
||
//中值滤波,降采样
|
||
cv::medianBlur(inImage,mtTempImage,3);
|
||
cv::resize(mtTempImage, mtOutImage, Size((int)(mtTempImage.rows*0.5),(int)(mtTempImage.cols*0.5) ), INTER_LINEAR);
|
||
LogInfo << "TrainAnaEngine mtspecImage end";
|
||
return mtOutImage;
|
||
}
|
||
|
||
/*
|
||
* 获取最近100帧的dComparePoint的最大值与最小值之差
|
||
* inParam : 第i个方框的dComparePoint值
|
||
* inParam : 第i个框的索引
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
float TrainAnaEngine::GetPointMaxReduceMin(float dComparePoint,int index){
|
||
static float array[20] ={0.0};
|
||
switch (index)
|
||
{
|
||
case 0:
|
||
static int num_count1=0;
|
||
static float array1[20] ={0.0};
|
||
array1[num_count1]=dComparePoint;
|
||
num_count1++;
|
||
if (num_count1>19){
|
||
num_count1=0;
|
||
}
|
||
for(int i=0;i<=19;i++){
|
||
array[i]=array1[i];
|
||
}
|
||
break;
|
||
|
||
|
||
case 1:
|
||
static int num_count2=0;
|
||
static float array2[20] ={0.0};
|
||
array2[num_count2]=dComparePoint;
|
||
num_count2++;
|
||
if (num_count2>19){
|
||
num_count2=0;
|
||
}
|
||
for(int i=0;i<=19;i++){
|
||
array[i]=array2[i];
|
||
}
|
||
break;
|
||
|
||
|
||
case 2:
|
||
static int num_count3=0;
|
||
static float array3[20] ={0.0};
|
||
array3[num_count3]=dComparePoint;
|
||
num_count3++;
|
||
if (num_count3>19){
|
||
num_count3=0;
|
||
}
|
||
for(int i=0;i<=19;i++){
|
||
array[i]=array3[i];
|
||
}
|
||
break;
|
||
}
|
||
|
||
sort(array,array+20);
|
||
return (array[19]-array[0]);
|
||
}
|
||
/**
|
||
* 来车动态检测
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : 原始图片的时间戳
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
void TrainAnaEngine::checkAction(cv::Mat baseimg, uint64_t i64TimeStamp)
|
||
{
|
||
#ifdef SHOW_RECTANGLE
|
||
cv::Mat img=baseimg.clone();
|
||
cv::Scalar sca(0,0,255);
|
||
#endif
|
||
|
||
|
||
//count[5]记录选择区域的状态为来车所保持的帧数,当帧数大于5时,改变选择区域的状态为来车
|
||
static int count[5]={0};
|
||
LogInfo << "TrainAnaEngine checkAction start";
|
||
// 记录上一帧的行车状态
|
||
nPreStatus = nStatus;
|
||
// 记录上一帧的动态变化情况
|
||
nPrePicAreaChangeing = nPicAreaChangeing;
|
||
// 初始化当前帧的动态变化情况
|
||
nPicAreaChangeing = 0x00;
|
||
// 检测区域数量
|
||
int nlistlen = lstAction.size();
|
||
//LogInfo << "TrainAnaEngine checkAction nlistlen:" << nlistlen;
|
||
//LogInfo << "TrainAnaEngine checkAction i64TimeStamp:" << i64TimeStamp;
|
||
|
||
|
||
for (int i = 0; i < nlistlen; i++)
|
||
{
|
||
// 根据检测区域切分当前帧
|
||
cv::Mat cvImg1 = mtareaImage(baseimg, lstAction[i].nAreaX1, lstAction[i].nAreaY1, lstAction[i].nAreaX2, lstAction[i].nAreaY2);
|
||
cvImg1 = mtImproveImage(cvImg1, lstAction[i], false);
|
||
// 根据检测区域切分基础帧
|
||
cv::Mat cvImg2 = mtareaImage(cvFirstImg, lstAction[i].nAreaX1+5, lstAction[i].nAreaY1+5, lstAction[i].nAreaX2-5, lstAction[i].nAreaY2-5);
|
||
cvImg2 = mtImproveImage(cvImg2, lstAction[i], false);
|
||
// 获取比对数值
|
||
std::vector<double> lstRet = getCompPoint(lstAction[i], cvImg1, cvImg2);
|
||
// 记录上一帧比对数值
|
||
lstAction[i].dPreComparePoint = lstAction[i].dComparePoint;
|
||
// 记录当前帧比对数值
|
||
lstAction[i].dComparePoint = lstRet[0];
|
||
//LogInfo << "TrainAnaEngine checkAction i:" << i;
|
||
//LogInfo << "TrainAnaEngine checkAction nlistlen:" << nlistlen;
|
||
//LogInfo << "TrainAnaEngine checkAction nStatus:" << nStatus;
|
||
//LogInfo << "TrainAnaEngine checkAction lstAction[i].dComparePoint:" << lstAction[i].dComparePoint;
|
||
//LogInfo << "TrainAnaEngine checkAction lstAction[i].dSameThresholdVal:" << lstAction[i].dSameThresholdVal;
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
//方框的位置
|
||
cv::Rect rect(lstAction[i].nAreaX1,lstAction[i].nAreaY1,(lstAction[i].nAreaX2-lstAction[i].nAreaX1),(lstAction[i].nAreaY2-lstAction[i].nAreaY1));
|
||
//point1当前的方框状态显示的位置
|
||
cv::Point point(lstAction[i].nAreaX1,lstAction[i].nAreaY1-90);
|
||
//point2时当前的方框相似度的值显示的位置
|
||
cv::Point point2(lstAction[i].nAreaX1,lstAction[i].nAreaY1-60);
|
||
//point2时当前的方框累加的值显示的位置
|
||
cv::Point point3(lstAction[i].nAreaX1,lstAction[i].nAreaY1-30);
|
||
cv::rectangle(img,rect,sca,3);
|
||
#endif
|
||
|
||
// 比对数值小于设定的阈值则判断检测区域发生变化
|
||
if (lstAction[i].dComparePoint < lstAction[i].dSameThresholdVal){
|
||
//LogInfo << "TrainAnaEngine checkAction start nPicAreaChangeing:" << nPicAreaChangeing;
|
||
// 设定状态 当前区域存在变化
|
||
count[i]++;
|
||
if(count[i]>=5){
|
||
// nPicAreaChangeing += 0x00000001 << i;
|
||
lstAction[i].bChanged = true;
|
||
if(count[i]>10)
|
||
count[i]=10;
|
||
}
|
||
//LogInfo << "TrainAnaEngine checkAction end nPicAreaChangeing:" << nPicAreaChangeing;
|
||
}else{
|
||
count[i]--;
|
||
if(count[i]<=0){
|
||
count[i]=0;
|
||
//nPicAreaChangeing =(nPicAreaChangeing&(~(0x00000001<<i)));
|
||
lstAction[i].bChanged = false;
|
||
}
|
||
}
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
if( lstAction[i].bChanged){
|
||
cv::putText(img,"yes",point,5,1.5,sca,3);
|
||
LogInfo<<"current img id "<<num << " yes";
|
||
}else{
|
||
cv::putText(img,"no",point,5,1.5,sca,3);
|
||
LogInfo<<"current img id "<<num << " no";
|
||
}
|
||
cv::putText(img,"similarity: "+to_string((int)((lstAction[i].dComparePoint)*1000)),point2,5,1.5,sca,3);
|
||
LogInfo<<"current img id "<<num << " similarity: "<<(int)((lstAction[i].dComparePoint)*1000);
|
||
#endif
|
||
|
||
|
||
|
||
// 如果最近100帧的最大值与最小值小于0.03视为无变化
|
||
if (GetPointMaxReduceMin(lstAction[i].dComparePoint,i)< 0.03){
|
||
lstAction[i].fluctuationFlag=true;
|
||
}else{
|
||
lstAction[i].fluctuationFlag=false;
|
||
}
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
if(lstAction[i].fluctuationFlag){
|
||
cv::putText(img,"fluctuation Low",point3,5,1.5,sca,3);
|
||
LogInfo<<"current img id "<<num << " fluctuation Low";
|
||
}else{
|
||
cv::putText(img,"fluctuation High",point3,5,1.5,sca,3);
|
||
LogInfo<<"current img id "<<num << " fluctuation High";
|
||
}
|
||
#endif
|
||
|
||
lstAction[i].bPreChanged = lstAction[i].bChanged;
|
||
}
|
||
|
||
//LogInfo << "TrainAnaEngine checkAction nStatus:" << nStatus;
|
||
//LogInfo << "TrainAnaEngine checkAction nPicAreaChangeing:" << nPicAreaChangeing;
|
||
//LogInfo << "TrainAnaEngine checkAction nPrePicAreaChangeing:" << nPrePicAreaChangeing;
|
||
|
||
|
||
|
||
|
||
|
||
/************************************************状态切换****************************************************************/
|
||
// 状态无车(并进行基础帧替换) -> 检测有车
|
||
if (nStatus == TRAIN_INIT_STATUS){
|
||
//LogInfo << "TrainAnaEngine checkAction TRAIN_INIT_STATUS start";
|
||
// 动态检测区域状态是否发生变化 true 发生 false 未发生
|
||
bool bStatuschanged = false;
|
||
//根据方框的编号以及对应的状态判断当前来车的方向以及有无来车
|
||
//0对应左侧方框一,1对应中间方框
|
||
if((lstAction[0].bChanged&&lstAction[1].bChanged&&(!lstAction[2].bChanged))||(lstAction[0].bChanged&(!lstAction[1].bChanged)&lstAction[2].bChanged)){
|
||
nStatus = TRAIN_RIGHT_RUN;
|
||
bStatuschanged = true;
|
||
}else if(lstAction[1].bChanged&&lstAction[2].bChanged&&(!lstAction[0].bChanged)){
|
||
nStatus = TRAIN_LEFT_RUN;
|
||
bStatuschanged = true;
|
||
}
|
||
// }else if(lstAction[0].bChanged&&lstAction[1].bChanged&&lstAction[2].bChanged){
|
||
// nStatus = TRAIN_RIGHT_RUN;
|
||
// bStatuschanged = true;
|
||
// }
|
||
|
||
// 状态发生变化
|
||
if (bStatuschanged == true) {
|
||
// 开始记录车厢划分信息/添加一节车厢划分信息
|
||
PartionInfo stTempInfo;
|
||
stTempInfo.nindex = 1;
|
||
stTempInfo.startframe = 1;
|
||
stTempInfo.i64StartTimeStamp = i64TimeStamp;
|
||
lstPartInfo.push_back(stTempInfo);
|
||
}
|
||
|
||
//基础帧替换的第一种情况。
|
||
//用于计算高校相似度保持的帧数,当帧数保持10帧以上则进行帧替换
|
||
static int count_num=0;
|
||
bool bEmpty1=true;
|
||
for (int i = 0; i < nlistlen; i++) {
|
||
bEmpty1=bEmpty1&&(lstAction[i].dPreComparePoint>=0.95);
|
||
}
|
||
if (bEmpty1){
|
||
count_num++;
|
||
if(count_num>=10) {
|
||
// 没有发生变化,则将该帧作为基础帧
|
||
cvFirstImg = baseimg;
|
||
|
||
count_num=0;
|
||
}
|
||
}else{
|
||
count_num=0;
|
||
}
|
||
|
||
|
||
//基础帧替换的第二种情况,过车后引起的相似度下降,需要最近100帧相似度波动小于0.03
|
||
bool bEmpty2=true;
|
||
static int count_num2=0;
|
||
for (int i = 0; i < nlistlen; i++) {
|
||
bEmpty2=bEmpty2&&(!lstAction[i].bChanged);
|
||
bEmpty2=bEmpty2&&(lstAction[i].fluctuationFlag);
|
||
}
|
||
if(bEmpty2){
|
||
count_num2++;
|
||
if(count_num2>100){
|
||
cvFirstImg = baseimg;
|
||
count_num2=0;
|
||
}
|
||
}else{
|
||
count_num2=0;
|
||
}
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " train no";
|
||
cv::putText(img,"train no",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
|
||
}else if(nStatus == TRAIN_LEFT_RUN){
|
||
bool bpaused = false;
|
||
bool bpassed = false;
|
||
bool noFluctuationFlag = true;
|
||
unsigned short int bpaused_count = 0;
|
||
|
||
|
||
//0,1,2全部无改变,相似度较高,视为车辆已经过去
|
||
//0改变,1,2无变化仍视为车辆已经过去
|
||
if(
|
||
(!lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(!lstAction[2].bChanged)||
|
||
(lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(!lstAction[2].bChanged)){
|
||
bpassed=true;
|
||
|
||
}
|
||
|
||
for (int i = 0; i < nlistlen; i++)
|
||
{
|
||
//任意两个及以上改变视为停车
|
||
if(lstAction[i].bChanged){
|
||
bpaused_count++;
|
||
}
|
||
noFluctuationFlag = (noFluctuationFlag && lstAction[i].fluctuationFlag);
|
||
}
|
||
|
||
bpaused=((bpaused_count>=2 )&& noFluctuationFlag);
|
||
bpassed=(bpassed && noFluctuationFlag);
|
||
|
||
//计算累计帧数
|
||
static unsigned short int count1=0;
|
||
static unsigned short int count2=0;
|
||
// 状态 有车 -> 停车
|
||
if (bpaused == true)
|
||
{
|
||
count1++;
|
||
if(count1>50){
|
||
nStatus = TRAIN_PAUSE;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count1=0;
|
||
}
|
||
// 状态 有车 -> 完全通过
|
||
if (bpassed == true)
|
||
{
|
||
count2++;
|
||
if(count2>50){
|
||
nStatus = TRAIN_PASSED;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count2=0;
|
||
|
||
}
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " director left ";
|
||
cv::putText(img,"director left",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
|
||
}else if (nStatus == TRAIN_RIGHT_RUN){
|
||
bool bpaused = false;
|
||
bool bpassed = false;
|
||
bool noFluctuationFlag = true;
|
||
unsigned short int bpaused_count = 0;
|
||
|
||
//0,1,2全部无改变,相似度较高,视为车辆已经过去
|
||
//2改变,0,1无变化仍视为车辆已经过去
|
||
if(
|
||
(!lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(!lstAction[2].bChanged)||
|
||
(!lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(lstAction[2].bChanged)){
|
||
bpassed=true;
|
||
}
|
||
|
||
for (int i = 0; i < nlistlen; i++)
|
||
{
|
||
//任意两个及以上改变视为停车
|
||
if(lstAction[i].bChanged){
|
||
bpaused_count++;
|
||
}
|
||
noFluctuationFlag = (noFluctuationFlag && lstAction[i].fluctuationFlag);
|
||
}
|
||
|
||
bpaused=((bpaused_count>=2 )&& noFluctuationFlag);
|
||
bpassed=(bpassed && noFluctuationFlag);
|
||
|
||
//计算累计帧数
|
||
static unsigned short int count1=0;
|
||
static unsigned short int count2=0;
|
||
// 状态 有车 -> 停车
|
||
if (bpaused == true)
|
||
{
|
||
count1++;
|
||
if(count1>50){
|
||
nStatus = TRAIN_PAUSE;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count1=0;
|
||
}
|
||
// 状态 有车 -> 完全通过
|
||
if (bpassed == true)
|
||
{
|
||
count2++;
|
||
if(count2>50){
|
||
nStatus = TRAIN_PASSED;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count2=0;
|
||
}
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " director right ";
|
||
cv::putText(img,"director right",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
}else if (nStatus == TRAIN_UNKOWN_RUN){
|
||
|
||
bool bpaused = false;
|
||
bool bpassed = false;
|
||
bool noFluctuationFlag = true;
|
||
unsigned short int bpaused_count = 0;
|
||
//0,1,2全部无改变,相似度较高,视为车辆已经过去
|
||
//2改变,0,1无变化仍视为车辆已经过去,或者0给改变,12无变化
|
||
if(
|
||
(!lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(!lstAction[2].bChanged)||
|
||
(!lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(lstAction[2].bChanged)||
|
||
(lstAction[0].bChanged)&&(!lstAction[1].bChanged)&&(!lstAction[2].bChanged)
|
||
){
|
||
bpassed=true;
|
||
}
|
||
|
||
for (int i = 0; i < nlistlen; i++)
|
||
{
|
||
//任意两个及以上改变视为停车
|
||
if(lstAction[i].bChanged){
|
||
bpaused_count++;
|
||
}
|
||
noFluctuationFlag = (noFluctuationFlag && lstAction[i].fluctuationFlag);
|
||
}
|
||
|
||
bpaused=((bpaused_count>=2 )&& noFluctuationFlag);
|
||
bpassed=(bpassed && noFluctuationFlag);
|
||
|
||
//计算累计帧数
|
||
static unsigned short int count1=0;
|
||
static unsigned short int count2=0;
|
||
// 状态 有车 -> 停车
|
||
if (bpaused == true)
|
||
{
|
||
count1++;
|
||
if(count1>50){
|
||
nStatus = TRAIN_PAUSE;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count1=0;
|
||
}
|
||
// 状态 有车 -> 完全通过
|
||
if (bpassed == true)
|
||
{
|
||
count2++;
|
||
if(count2>50){
|
||
nStatus = TRAIN_PASSED;
|
||
count1=0;
|
||
count2=0;
|
||
}
|
||
}else{
|
||
count2=0;
|
||
}
|
||
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " director unkonw ";
|
||
cv::putText(img,"director unkonw",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
}else if(nStatus == TRAIN_PAUSE){
|
||
static short int count=0;
|
||
//停车状态只检测波动,三块全部波动保持20帧即重启
|
||
if(!lstAction[0].fluctuationFlag&&!lstAction[1].fluctuationFlag&&!lstAction[2].fluctuationFlag){
|
||
if(count>20){
|
||
nStatus=TRAIN_RESTART;
|
||
count=0;
|
||
}
|
||
count++;
|
||
}
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " train stop ";
|
||
cv::putText(img,"train stop",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
}else if(nStatus == TRAIN_RESTART){
|
||
//切换到TRAIN_UNKOWN_RUN
|
||
nStatus=TRAIN_UNKOWN_RUN;
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " train restort ";
|
||
cv::putText(img,"train restort",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
}else if(nStatus == TRAIN_PASSED){
|
||
//切换回TRAIN_INIT_STATUS状态
|
||
nStatus = TRAIN_INIT_STATUS;
|
||
#ifdef SHOW_RECTANGLE
|
||
LogInfo<<"current img id "<<num << " train passed ";
|
||
cv::putText(img,"train passed",cv::Point(150,200),5,4,sca,3);
|
||
#endif
|
||
}
|
||
|
||
if(nStatus!=TRAIN_INIT_STATUS){
|
||
#ifdef SHOW_RECTANGLE
|
||
if(num%4==0){
|
||
LogInfo<<"current img id "<<num << " state: "<<nStatus;
|
||
cv::putText(img,"state: "+to_string(nStatus),cv::Point(150,400),5,4,sca,5);
|
||
imwrite(to_string(num)+".jpg",img);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
LogInfo << "TrainAnaEngine checkAction end";
|
||
}
|
||
|
||
/**
|
||
* 车厢划分检测
|
||
* inParam : 原始图片的Mat值
|
||
* inParam : 原始图片的时间戳
|
||
* outParam: N/A
|
||
* return : N/A
|
||
*/
|
||
bool TrainAnaEngine::checkPartion(cv::Mat baseimg, uint64_t i64TimeStamp)
|
||
{
|
||
LogInfo << "TrainAnaEngine checkPartion start";
|
||
// 初始化是否有划分信息
|
||
bool bPartion = false;
|
||
// 记录上一帧的判断等级(相同作and处理 不同作or处理)
|
||
int nPreOrLevel = 1;
|
||
// LogInfo << "TrainAnaEngine checkPartion nStatus:" << nStatus;
|
||
// 停车状态不进行划分信息检测
|
||
//if(false){
|
||
if ((nStatus == TRAIN_PAUSE)
|
||
|| (nStatus == TRAIN_INIT_STATUS)
|
||
|| (nStatus == TRAIN_PASSED)){
|
||
return bPartion;
|
||
}
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion.size():" << lstPartion.size();
|
||
// 根据判断算法的数量进行循环比对
|
||
bPartion = true;
|
||
for (int i = 0; i < lstPartion.size(); i++)
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion i:" << i;
|
||
// 算法不开启则跳过
|
||
if (lstPartion[i].bOn == false)
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion[i].bOn i:" << i;
|
||
continue;
|
||
}
|
||
|
||
// 对当前帧图片进行切割
|
||
cv::Mat baseimgin = mtareaImage(baseimg, lstPartion[i].nAreaX1, lstPartion[i].nAreaY1, lstPartion[i].nAreaX2, lstPartion[i].nAreaY2);
|
||
// 对当前帧图片进行画面增强
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 cols:" << baseimgin.cols;
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 rows:" << baseimgin.rows;
|
||
cv::Mat cvImg1 = mtImproveImage(baseimgin, lstPartion[i], false);
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 cols:" << cvImg1.cols;
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 rows:" << cvImg1.rows;
|
||
cv::Mat cvImg2;
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion[i].baseImagePath:" << lstPartion[i].baseImagePath;
|
||
if (lstPartion[i].baseImagePath == "None")
|
||
{
|
||
cv::Mat cvFirstImgin = mtareaImage(cvFirstImg, lstPartion[i].nAreaX1 - 10, lstPartion[i].nAreaY1 -10, lstPartion[i].nAreaX2 -10, lstPartion[i].nAreaY2 -10);
|
||
// 设定为None 用基础图像进行比对
|
||
cvImg2 = mtImproveImage(cvFirstImgin, lstPartion[i], false);
|
||
}
|
||
else
|
||
{
|
||
// 设定有路径则读取路径的文件进行比对
|
||
cvImg2 = cv::imread(lstPartion[i].baseImagePath, cv::IMREAD_GRAYSCALE);
|
||
// cvImg2 = mtdecodeImageDatabyFile(lstPartion[i].baseImagePath);
|
||
// 图像增强
|
||
cvImg2 = mtImproveImage(cvImg2, lstPartion[i], true);
|
||
}
|
||
// 获取比对值
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 cols:" << cvImg1.cols;
|
||
//LogInfo << "TrainAnaEngine checkPartion cvImg1 rows:" << cvImg2.rows;
|
||
|
||
std::vector<double> lstRet = getCompPoint(lstPartion[i], cvImg1, cvImg2);
|
||
lstPartion[i].dComparePoint = lstRet[0];
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion[i].dComparePoint:" << lstPartion[i].dComparePoint;
|
||
|
||
// 获取是相同还是不同作为判断标准
|
||
bool bCurrentRet = (lstPartion[i].bDiff == true) ? lstPartion[i].dComparePoint < lstPartion[i].dDiffThresholdVal : lstPartion[i].dComparePoint > lstPartion[i].dSameThresholdVal;
|
||
// 对比等级不同 进行判断结果OR处理
|
||
if (lstPartion[i].bOrLevel != nPreOrLevel)
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion[i].bOrLevel != nPreOrLevel";
|
||
bPartion = bPartion || bCurrentRet;
|
||
}
|
||
// 比对等级相同 进行判断结果AND处理
|
||
else
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartion[i].bOrLevel == nPreOrLevel";
|
||
bPartion = bPartion && bCurrentRet;
|
||
}
|
||
// 判断结果存在false的情况 直接停止判断确定没有车厢划分信息
|
||
if (bPartion == false)
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == false";
|
||
break;
|
||
}
|
||
}
|
||
// 存在车厢划分信息
|
||
if (bPartion == true)
|
||
{
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true for end";
|
||
// nPartionPassFrameCount = 0;
|
||
// 获取最新的车厢节数
|
||
int nPrePartionIndex = lstPartInfo.size() - 1;
|
||
|
||
// 获取时间戳
|
||
lstPartInfo[nPrePartionIndex].i64EndTimeStamp = i64TimeStamp;
|
||
// 根据开始帧时间戳和结束帧时间错 计算当节车厢的行车速度
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true lstPartInfo[nPrePartionIndex].ftime:" << abs(lstPartInfo[nPrePartionIndex].i64EndTimeStamp - lstPartInfo[nPrePartionIndex].i64StartTimeStamp);
|
||
// 根据时间戳计算时间差
|
||
float nTimePassed = (abs(lstPartInfo[nPrePartionIndex].i64EndTimeStamp - lstPartInfo[nPrePartionIndex].i64StartTimeStamp)) * 1.0;
|
||
lstPartInfo[nPrePartionIndex].fspeed = (TRAIN_WIDTH * 1000.0) /nTimePassed;
|
||
//
|
||
//nSamePartionIgnoreCount = (nTimePassed / (3 * 5000)) * nFrameRate;
|
||
// 结束帧为当前帧再往后 (除以2的原因:中间为车钩,车钩后的车体宽度为整个镜头的宽度除以2)
|
||
lstPartInfo[nPrePartionIndex].endframe = nLatestFrame + getOffsetFrame(lstPartInfo[nPrePartionIndex].fspeed, (TRAIN_IN_CAMERA_WIDTH / 2), nFrameRate);
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true lstPartInfo[nPrePartionIndex].endframe" << lstPartInfo[nPrePartionIndex].endframe;
|
||
lstPartInfo[nPrePartionIndex].bfuncconfirmed = true;
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true lstPartInfo[nPrePartionIndex].i64EndTimeStamp:" << lstPartInfo[nPrePartionIndex].i64EndTimeStamp;
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true lstPartInfo[nPrePartionIndex].i64StartTimeStamp:" << lstPartInfo[nPrePartionIndex].i64StartTimeStamp;
|
||
// 如果时间戳相同则不是划分信息
|
||
if (lstPartInfo[nPrePartionIndex].i64EndTimeStamp == lstPartInfo[nPrePartionIndex].i64StartTimeStamp) {
|
||
bPartion = false;
|
||
return bPartion;
|
||
}
|
||
|
||
|
||
//LogInfo << "TrainAnaEngine checkPartion nPrePartionIndex" << nPrePartionIndex;
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartInfo[nPrePartionIndex].i64EndTimeStamp" << lstPartInfo[nPrePartionIndex].i64EndTimeStamp;
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartInfo[nPrePartionIndex].nLatestFrame" << nLatestFrame;
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartInfo[nPrePartionIndex].fspeed:" << lstPartInfo[nPrePartionIndex].fspeed;
|
||
//LogInfo << "TrainAnaEngine checkPartion lstPartInfo[nPrePartionIndex].endframe" << lstPartInfo[nPrePartionIndex].endframe;
|
||
//LogInfo << "TrainAnaEngine checkPartion bPartion == true lstPartInfo[nPrePartionIndex].fspeed:" << lstPartInfo[nPrePartionIndex].fspeed;
|
||
}
|
||
LogInfo << "TrainAnaEngine checkPartion end";
|
||
return bPartion;
|
||
}
|
||
|
||
/**
|
||
* 计算车钩从中间到边缘的间隔帧
|
||
* inParam : 行车速度(单位:米/秒)
|
||
* inParam : 宽度
|
||
* inParam : 相机帧率(单位:帧/秒)
|
||
* outParam: N/A
|
||
* return : 间隔帧
|
||
*/
|
||
int TrainAnaEngine::getOffsetFrame(float fspeed, int width, int nFrameRate)
|
||
{
|
||
LogInfo << "TrainAnaEngine getOffsetFrame start";
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame fspeed:" << fspeed;
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame width:" << width;
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame nFrameRate:" << nFrameRate;
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame nLatestFrame:" << nLatestFrame;
|
||
//偏移值 = (中间到边缘的宽度(米) / 速度(米/秒)->时间(秒))* 帧率(帧/秒)
|
||
float ftmp = width * (float) nFrameRate;
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame start end:" << ftmp;
|
||
ftmp = ftmp / fspeed;
|
||
//LogInfo << "TrainAnaEngine getOffsetFrame start end:" << ftmp;
|
||
int nRet = (int) ftmp;
|
||
LogInfo << "TrainAnaEngine getOffsetFrame start end:" << nRet;
|
||
return nRet;
|
||
}
|
||
|
||
|
||
/**
|
||
* 计算车钩移动的像素值
|
||
* inParam : 行车速度(单位:米/秒)
|
||
* inParam : 宽度
|
||
* inParam : 相机帧率(单位:帧/秒)
|
||
* outParam: N/A
|
||
* return : 间隔帧
|
||
*/
|
||
int TrainAnaEngine::getCouplerOffsetPosition(float fspeed, int nframeindex)
|
||
{
|
||
LogInfo << "TrainAnaEngine getCouplerOffsetPosition start";
|
||
//LogInfo << "TrainAnaEngine getCouplerOffsetPosition fspeed:" << fspeed;
|
||
//LogInfo << "TrainAnaEngine getCouplerOffsetPosition start:" << nframeindex;
|
||
//单位换算
|
||
// 米/秒 -> 米/帧
|
||
// 米/帧 = 米/秒 * 秒/帧(即:1/帧率)
|
||
float fmeter_frame = fspeed / nFrameRate;
|
||
//LogInfo << "TrainAnaEngine getCouplerOffsetPosition fmeter_frame:" << fmeter_frame;
|
||
// 米/帧 -> 像素/帧
|
||
// 像素/帧 = 米/帧 * 像素/米
|
||
float fpix_frame = fmeter_frame * (METHOD_BASE_WIDTH / TRAIN_IN_CAMERA_WIDTH);
|
||
//LogInfo << "TrainAnaEngine getCouplerOffsetPosition fpix_frame:" << fpix_frame;
|
||
|
||
int nretPixOffet = (int)fpix_frame;
|
||
nretPixOffet = nretPixOffet * nframeindex;
|
||
//LogInfo << "TrainAnaEngine getCouplerOffsetPosition nretPixOffet:" << nretPixOffet;
|
||
LogInfo << "TrainAnaEngine getCouplerOffsetPosition end";
|
||
return nretPixOffet;
|
||
}
|
||
|
||
int TrainAnaEngine::getTailPixOffset()
|
||
{
|
||
LogInfo << "TrainAnaEngine getTailPixOffset start";
|
||
// 单位计算
|
||
// 帧宽像素/米
|
||
float fframewidth_meter = ((METHOD_BASE_WIDTH * 1.0) / (TRAIN_IN_CAMERA_WIDTH));
|
||
//LogInfo << "TrainAnaEngine getTailPixOffset fframewidth_meter:" << fframewidth_meter;
|
||
// 车尾车钩像素位置
|
||
float fOffsetPosistion = TRAIN_WIDTH * fframewidth_meter;
|
||
//LogInfo << "TrainAnaEngine getTailPixOffset fOffsetPosistion:" << fOffsetPosistion;
|
||
|
||
int nretOffset = (int)fOffsetPosistion;
|
||
//LogInfo << "TrainAnaEngine getTailPixOffset nretOffset:" << nretOffset;
|
||
//LogInfo << "TrainAnaEngine getTailPixOffset end";
|
||
return nretOffset;
|
||
}
|
||
|
||
|
||
APP_ERROR TrainAnaEngine::Process()
|
||
{
|
||
int iRet = APP_ERR_OK;
|
||
//程序启动标志位
|
||
bool bInited = false;
|
||
while (!isStop_)
|
||
{
|
||
std::shared_ptr<void> pVoidData0 = nullptr;
|
||
inputQueMap_[strPort0_]->pop(pVoidData0);
|
||
if (nullptr == pVoidData0)
|
||
{
|
||
usleep(1000); //1ms
|
||
continue;
|
||
}
|
||
|
||
LogInfo << "TrainAnaEngine Process start";
|
||
std::shared_ptr<DecodedData> pDecodeData = std::static_pointer_cast<DecodedData>(pVoidData0);
|
||
std::shared_ptr<void> pHostData = nullptr;
|
||
|
||
//获取图像数据
|
||
cv::Mat matYUV(pDecodeData->iHeight * 3 / 2, pDecodeData->iWidth, CV_8UC1);
|
||
int iCopySize = pDecodeData->iWidth * pDecodeData->iHeight * 3 / 2;
|
||
memcpy(matYUV.data, pHostData.get(), iCopySize);
|
||
|
||
// 将YUV格式灰度化之后修改图像尺寸
|
||
cv::Mat cvtemp;
|
||
cv::cvtColor(matYUV, cvtemp, cv::COLOR_YUV2GRAY_420);
|
||
//cv::imwrite("/home/HwHiAiUser/1.jpg",cvtemp);
|
||
matYUV = mtresizeImage(cvtemp, METHOD_BASE_WIDTH, METHOD_BASE_HEIGHT);
|
||
//来车
|
||
//cv::Mat baseimg = mtdecodeImageDatabyBin(lpimgdata, imglen);
|
||
//cv::Mat baseimg = matYUV.data;
|
||
//程序启动第一帧跳过 保存为基础图像
|
||
if (bInited == false) {
|
||
cvFirstImg = matYUV;
|
||
bInited = true;
|
||
nFrameRate = pDecodeData->iRate;
|
||
continue;
|
||
}
|
||
LogInfo << "TrainAnaEngine Process pDecodeData.i64TimeStamp:" << pDecodeData->i64TimeStamp;
|
||
ncurtime = pDecodeData->i64TimeStamp;
|
||
//来车状态检测
|
||
checkAction(matYUV, pDecodeData->i64TimeStamp);
|
||
|
||
//判断是否有来车
|
||
pDecodeData->iStatus = (nStatus == TRAIN_LEFT_RUN || nStatus == TRAIN_RIGHT_RUN || nStatus == TRAIN_UNKOWN_RUN || nStatus == TRAIN_RESTART) ? 1 : ( nStatus == TRAIN_PAUSE)? 2 : 0;
|
||
//判断来车方向 0 方向未知/无车 1右侧来车(向左行驶:模型识别用) 2左侧来车(向右行驶:模型识别用)
|
||
pDecodeData->iDirection = ((nStatus == TRAIN_LEFT_RUN) ? 1 : ((nStatus == TRAIN_RIGHT_RUN) ? 2 : 0));
|
||
//列车是否通过
|
||
pDecodeData->bIsEnd = (nStatus == TRAIN_PASSED || nStatus == TRAIN_RESTART ) ? true : false;
|
||
LogInfo << "TrainAnaEngine Process pDecodeData->iStatus:" << pDecodeData->iStatus;
|
||
//LogInfo << "TrainAnaEngine Process pDecodeData->iDirection:" << pDecodeData->iDirection;
|
||
//新过车创建文件夹
|
||
if ((nStatus != TRAIN_INIT_STATUS && nPreStatus == TRAIN_INIT_STATUS) ||
|
||
( nPreStatus == TRAIN_RESTART && nStatus == TRAIN_UNKOWN_RUN))
|
||
{
|
||
strTrainData_ = MyUtils::getins()->GetDate();
|
||
strTrainName_ = MyUtils::getins()->GetTime();
|
||
std::string strTrainPath = strResultPath_ + strTrainData_ + "/" + strTrainName_ + "/";
|
||
MyUtils::getins()->CreateDirPath(strTrainPath);
|
||
}
|
||
//过车日期
|
||
pDecodeData->strTrainDate = strTrainData_;
|
||
//过车时间
|
||
pDecodeData->strTrainName = strTrainName_;
|
||
|
||
// iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pDecodeData));
|
||
|
||
//当前帧是否有划分信息
|
||
bool bPartionExist = false;
|
||
|
||
//有车的状态进行车厢划分检测
|
||
if (nStatus != TRAIN_INIT_STATUS){
|
||
//LogInfo << "TrainAnaEngine Process nPartionPassFrameCount:" << nPartionPassFrameCount;
|
||
//LogInfo << "TrainAnaEngine Process nSamePartionIgnoreCount:" << nSamePartionIgnoreCount;
|
||
//检测到划分状态的情况下 进行跳帧处理
|
||
//跳帧值为计算的车体通过三分之一之后的帧
|
||
if (nPartionPassFrameCount < nSamePartionIgnoreCount) {
|
||
nPartionPassFrameCount++;
|
||
} else {
|
||
//超过跳帧进行车厢划分检测
|
||
bPartionExist = checkPartion(matYUV, pDecodeData->i64TimeStamp);
|
||
//如果检测到车厢划分信息则检测跳帧的值
|
||
if (bPartionExist == true) {
|
||
nPartionPassFrameCount = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// write json info to file
|
||
|
||
//先读取文本内容,追加新的信息后再写入
|
||
//划分信息 JSON格式
|
||
Json::Value jvPartionInfo;
|
||
//JSON保存路径
|
||
std::string strFilePath;
|
||
//当然车厢通过的数量
|
||
int nPartionIndex = lstPartInfo.size() - 1;
|
||
|
||
LogInfo << "TrainAnaEngine Process nPartionIndex:" << nPartionIndex;
|
||
LogInfo << "TrainAnaEngine Process bPartionExist:" << bPartionExist;
|
||
//检测到车厢划分信息
|
||
if ((bPartionExist == true)) {
|
||
strFilePath = strResultPath_ + pDecodeData->strTrainDate + "/" + pDecodeData->strTrainName + "/"
|
||
+ std::to_string(nPartionIndex + 1) + ".txt";
|
||
// 记录过车日期
|
||
jvPartionInfo["trainDate"] = pDecodeData->strTrainDate;
|
||
// 记录过车时间
|
||
jvPartionInfo["trainName"] = pDecodeData->strTrainName;
|
||
// 记录车厢节数 (索引从0开始 所以这里+1)
|
||
jvPartionInfo["trainNo"] = nPartionIndex + 1;
|
||
// 记录行车开始帧
|
||
jvPartionInfo["startFrameId"] = lstPartInfo[nPartionIndex].startframe;
|
||
// 记录行车结束帧
|
||
jvPartionInfo["endFrameId"] = lstPartInfo[nPartionIndex].endframe;
|
||
// 记录车厢是否完全通过
|
||
jvPartionInfo["isEnd"] = pDecodeData->bIsEnd;
|
||
|
||
// 首部车钩的偏移位置 (单位帧)
|
||
int headpos = 0;
|
||
// 尾部车钩的偏移位置 (单位帧)
|
||
int tailpos = (0 - nTailPixOffset);
|
||
|
||
if (nPartionIndex == 0)
|
||
{
|
||
headpos = METHOD_BASE_WIDTH / 2;
|
||
tailpos = tailpos + headpos;
|
||
}
|
||
// 是否位右侧来车
|
||
bool brightcome = false;
|
||
if (nStatus == TRAIN_RIGHT_RUN)
|
||
{
|
||
brightcome = true;
|
||
// 右侧来车 首部车钩从画面最右侧开始
|
||
headpos = METHOD_BASE_WIDTH;
|
||
// 右侧来车 尾部车钩从画面最右侧+车厢宽的像素值
|
||
tailpos = METHOD_BASE_WIDTH + nTailPixOffset;
|
||
|
||
if (nPartionIndex == 0)
|
||
{
|
||
headpos = METHOD_BASE_WIDTH / 2;
|
||
tailpos = tailpos - headpos;
|
||
}
|
||
}
|
||
|
||
|
||
//LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].startframe:" << lstPartInfo[nPartionIndex].startframe ;
|
||
//LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].endframe:" << lstPartInfo[nPartionIndex].endframe;
|
||
//从当节车厢的开始帧到结束帧计算首部车钩和尾部车钩的偏移值
|
||
for (int nplayframe = lstPartInfo[nPartionIndex].startframe; nplayframe <= lstPartInfo[nPartionIndex].endframe; nplayframe++)
|
||
{
|
||
Json::Value jvposInfo;
|
||
// 当前车厢的第几几帧
|
||
int noffsetindex = (nplayframe - lstPartInfo[nPartionIndex].startframe);
|
||
// 根据车速计算车钩位置量(单位 像素)
|
||
int noffsetpos = getCouplerOffsetPosition(lstPartInfo[nPartionIndex].fspeed, noffsetindex);
|
||
// 初始化首部车钩偏移量(单位 像素)
|
||
jvposInfo["headpos"] = -1;
|
||
// 初始化尾部车钩偏移量(单位 像素)
|
||
jvposInfo["tailpos"] = -1;
|
||
|
||
if (brightcome == false) {
|
||
// 左侧来车
|
||
// 首部车钩和尾部车钩 每帧加 车钩偏移值
|
||
jvposInfo["headpos"] = (headpos + noffsetpos);
|
||
jvposInfo["tailpos"] = (tailpos + noffsetpos);
|
||
} else {
|
||
// 右侧来车
|
||
// 首部车钩和尾部车钩 每帧减 车钩偏移值
|
||
jvposInfo["headpos"] = (headpos - noffsetpos);
|
||
jvposInfo["tailpos"] = (tailpos - noffsetpos);
|
||
}
|
||
//LogInfo << "TrainAnaEngine Process jvposInfo[headpos]" << jvposInfo["headpos"];
|
||
// LogInfo << "TrainAnaEngine Process jvposInfo[tailpos]:" << jvposInfo["tailpos"];
|
||
//LogInfo << "TrainAnaEngine Process jvPartionListInfo.append";
|
||
jvPartionInfo[std::to_string(nplayframe)] = jvposInfo;
|
||
}
|
||
|
||
PartionInfo stTempInfo;
|
||
// 开始记录新的一节车厢信息(从索引变成序号+1 ,新增一节车厢信息+1)
|
||
stTempInfo.nindex = nPartionIndex + 2;
|
||
// 上一节车厢的结束帧 - (偏移帧 = (镜头内的车体宽度/ (速度) -> 通过时间) * 帧/秒 ) 作为下一节车厢的开始帧
|
||
int ntempOffsetFrame = lstPartInfo[nPartionIndex].endframe - (int)(((TRAIN_IN_CAMERA_WIDTH) / lstPartInfo[nPartionIndex].fspeed) * nFrameRate);
|
||
//LogInfo << "TrainAnaEngine Process ntempOffsetFrame:" << ntempOffsetFrame;
|
||
stTempInfo.startframe = (ntempOffsetFrame > nSamePartionIgnoreCount) ? ntempOffsetFrame : nSamePartionIgnoreCount;
|
||
stTempInfo.i64StartTimeStamp = pDecodeData->i64TimeStamp;
|
||
// 初始化下一节的结束帧
|
||
//stTempInfo.endframe = 0;
|
||
|
||
lstPartInfo.push_back(stTempInfo);
|
||
// 记录当前车厢的信息到JSON文件
|
||
//MyUtils::getins()->WriteJsonInfo(jvPartionInfo, strFilePath);
|
||
std::shared_ptr<TrainRange> pTrainRange = std::make_shared<TrainRange>();
|
||
pTrainRange->strTrainDate = jvPartionInfo["trainDate"].asString();
|
||
pTrainRange->strTrainName = jvPartionInfo["trainName"].asString();
|
||
pTrainRange->iTrainIndex = jvPartionInfo["trainNo"].asInt();
|
||
pTrainRange->iStartFrameId = jvPartionInfo["startFrameId"].asInt();
|
||
pTrainRange->iEndFrameId = jvPartionInfo["endFrameId"].asInt();
|
||
pTrainRange->bIsEnd = jvPartionInfo["isEnd"].asBool();
|
||
//iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainRange));
|
||
}
|
||
|
||
// 有车的情况下。记录帧数:累加1
|
||
if (nStatus != TRAIN_INIT_STATUS)
|
||
{
|
||
nLatestFrame = nLatestFrame + 1;
|
||
}
|
||
//停车或无车(初始化相关参数)
|
||
|
||
|
||
/*
|
||
if ((nStatus == TRAIN_INIT_STATUS
|
||
&& (nStatus != TRAIN_INIT_STATUS)) || pDecodeData->bIsEnd)
|
||
{
|
||
vResetPartion();
|
||
}
|
||
*/
|
||
// 车厢通过初始化状态
|
||
if (pDecodeData->bIsEnd) {
|
||
vResetPartion();
|
||
}
|
||
LogError<<"current img id "<<num;
|
||
num++;
|
||
|
||
LogInfo << "TrainAnaEngine Process end";
|
||
}
|
||
return APP_ERR_OK;
|
||
}
|