Train_Identify/nvidia_ascend_engine/common_engine/TrainAnaEngine/TrainAnaEngine.cpp

1685 lines
62 KiB
C++
Raw Normal View History

2024-01-23 02:46:26 +00:00
#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;
}
/*
* 100dComparePoint的最大值与最小值之差
* 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改变12无变化仍视为车辆已经过去
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;
}