diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f983336..484b089 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,10 @@ aux_source_directory(${PROJECT_SRC_ROOT}/engine/DecodeEngine DecodeEngine_SRC) include_directories(${PROJECT_SRC_ROOT}/engine/MoveEngine) aux_source_directory(${PROJECT_SRC_ROOT}/engine/MoveEngine MoveEngine_SRC) +# SaveImageEngine +include_directories(${PROJECT_SRC_ROOT}/engine/SaveImageEngine) +aux_source_directory(${PROJECT_SRC_ROOT}/engine/SaveImageEngine SaveImageEngine_SRC) + # 其他头文件 include_directories( #base include @@ -179,6 +183,7 @@ file( ${DataSourceEngine_SRC} ${DecodeEngine_SRC} ${MoveEngine_SRC} + ${SaveImageEngine_SRC} ) # 服务端 diff --git a/src/base/AppCommon.h b/src/base/AppCommon.h index 1919dc8..d97bde4 100644 --- a/src/base/AppCommon.h +++ b/src/base/AppCommon.h @@ -203,14 +203,24 @@ typedef struct // 识别区域坐标 typedef struct { - int iLine = -1; //字段代号(仅第二步使用) - int iClassId = -1; //大小框的类别 - float fScore = 0; //分数 - float fClear = 0; //清晰度 - float fLTX = 0; //左上X坐标 Left Top x - float fLTY = 0; //左上y坐标 Left Top y - float fRBX = 0; //右下y坐标 Right Bottom x - float fRBY = 0; //右下y坐标 Right Bottom y + // 字段代号(仅第二步使用) + int iLine = -1; + // 大小框的类别 + int iClassId = -1; + // 框的名称 + std::string strClassName; + // 分数 + float fScore = 0; + // 清晰度 + float fClear = 0; + // 左上X坐标 Left Top x + float fLTX = 0; + // 左上y坐标 Left Top y + float fLTY = 0; + // 右下y坐标 Right Bottom x + float fRBX = 0; + // 右下y坐标 Right Bottom y + float fRBY = 0; } VCoordinate; // 集装箱信息 @@ -299,16 +309,24 @@ typedef struct // 存图数据 typedef struct { + // 车厢位置状态 + std::string strTrainStage; + // 行车方向 + std::string strDirection; + // 车厢运动状态 + std::string strTrainStatus; + // 帧图像数据 VFrameData frameData; - uint32_t iFrameId = 0; - - std::string strImgPath; - std::string strImgName; - bool bIsEnd = false; // 列车结束标识 - std::shared_ptr pDecodeData = nullptr; - // 车厢位置阶段(车头、头身交接、车身、车尾、无车) - int iTrainStage = MONITOR_MODEL_INIT_STATE; + // 图片存储目录 + std::string strImgPath; + // 图片名字 + std::string strImgName; + // 图片需要标记的框坐标 + std::vector vecCoordinate; } SaveImgData; +// 0 = 停止识别; 1 = 开始识别 extern std::atomic g_identify_type; +// -1 = 未知方向; 1 = 向左行驶; 2 = 向右行驶 +extern std::atomic g_come_direction; #endif \ No newline at end of file diff --git a/src/config/matrix.yaml b/src/config/matrix.yaml index d325c0d..f48ecc9 100644 --- a/src/config/matrix.yaml +++ b/src/config/matrix.yaml @@ -8,8 +8,10 @@ engines: VideoEngine: 0 VideoDecodeEngine: 0 MoveEngine: 0 + SaveImageEngine: 0 #engine连接 connects: VideoEngine_0_0: "VideoDecodeEngine_0_0 1024" VideoDecodeEngine_0_0: "MoveEngine_0_0 1024" + MoveEngine_0_0: "SaveImageEngine_0_0 1024" diff --git a/src/engine/DecodeEngine/VideoDecodeEngine.cpp b/src/engine/DecodeEngine/VideoDecodeEngine.cpp index 97d543b..8f45223 100644 --- a/src/engine/DecodeEngine/VideoDecodeEngine.cpp +++ b/src/engine/DecodeEngine/VideoDecodeEngine.cpp @@ -1 +1 @@ -/** * 视频流解码引擎 * */ #include "VideoDecodeEngine.h" using namespace std; using namespace cv; using namespace ai_matrix; VideoDecodeEngine::VideoDecodeEngine() {} VideoDecodeEngine::~VideoDecodeEngine() {} APP_ERROR VideoDecodeEngine::Init() { dataSourceConfig_ = Config::getins()->getDataSourceConfig(); strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; LogInfo << "VideoDecodeEngine Init ok"; return APP_ERR_OK; } APP_ERROR VideoDecodeEngine::DeInit() { if (harddecoder_ != nullptr) { harddecoder_->hardDecoderDeInit(); delete harddecoder_; harddecoder_ = nullptr; } LogInfo << "VideoDecodeEngine DeInit ok"; return APP_ERR_OK; } APP_ERROR VideoDecodeEngine::Process() { int iRet = APP_ERR_OK; int iSkipCount = 1; while (!isStop_) { //从上一引擎接收图像数据 std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); // if (iSkipCount++ % dataSourceConfig_.iSkipInterval != 0) // { // continue; // } // iSkipCount = 1; if (pProcessData->bIsTrainEnd) { iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "push the decode yuv420m frame data failed..."; } continue; } //创建解码类 if (harddecoder_ == nullptr) { harddecoder_ = new HardDecode; int iRet = harddecoder_->hardDecoderInit(pProcessData->dataSourceInfo.iWidth, pProcessData->dataSourceInfo.iHeight, pProcessData->dataSourceInfo.iRate, pProcessData->pCodecParameters_); if (!iRet) { LogError << "engineId:" << engineId_ << " HardH264FFmpegDecoderInit Failed"; if (harddecoder_) { delete harddecoder_; harddecoder_ = nullptr; } continue; } } // 构造YUV420M数据 unsigned int pYUV420MBuffer_Size = pProcessData->dataSourceInfo.iWidth * pProcessData->dataSourceInfo.iHeight * 3 / 2; void *pYUV420MBuffer = nullptr; pYUV420MBuffer = new uint8_t[pYUV420MBuffer_Size]; std::shared_ptr pYUVData; // 智能指针管理内存 pYUVData.reset(pYUV420MBuffer, [](void *data){if(data) {delete[] data; data = nullptr;}}); // 这里填入一个指向完整H264数据帧的指针 harddecoder_->pPacket_->data = static_cast(pProcessData->sourceFrameData.pData.get()); // 这个填入H264数据帧的大小 harddecoder_->pPacket_->size = pProcessData->sourceFrameData.iSize; int iDecodeRet = harddecoder_->hardDecoder(pYUV420MBuffer, &pYUV420MBuffer_Size); if (iDecodeRet) { //硬解码YUV转BGR cv::Mat matYUV(pProcessData->dataSourceInfo.iHeight * 3 / 2, pProcessData->dataSourceInfo.iWidth, CV_8UC1); memcpy(matYUV.data, static_cast(pYUVData.get()), pYUV420MBuffer_Size); cv::Mat matBGR(pProcessData->dataSourceInfo.iHeight, pProcessData->dataSourceInfo.iWidth, CV_8UC3); cv::cvtColor(matYUV, matBGR, cv::COLOR_YUV2BGR_I420); cv::resize(matBGR, matBGR, cv::Size(IMAGE_WIDTH, IMAGE_HEIGHT)); unsigned int iResizeSize = IMAGE_WIDTH * IMAGE_HEIGHT * 3; void *pResizeBGRBuffer = nullptr; pResizeBGRBuffer = new uint8_t[iResizeSize]; memcpy(pResizeBGRBuffer, matBGR.data, iResizeSize); pProcessData->sourceFrameData.pData.reset(pResizeBGRBuffer, [](void *data) {if(data) {delete[] data; data = nullptr;} }); pProcessData->sourceFrameData.iSize = iResizeSize; pProcessData->dataSourceInfo.iWidth = IMAGE_WIDTH; pProcessData->dataSourceInfo.iHeight = IMAGE_HEIGHT; // vector compression_params; // compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg // compression_params.push_back(100); //图片质量 // cv::imwrite("./jpg/" + std::to_string(pProcessData->sourceFrameData.i64TimeStamp) + ".jpg", matBGR, compression_params); iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "push the decode yuv420m frame data failed..."; } } else { LogError << "engineId:" << engineId_ << " HardH264FFmpegDecoderV2 failed...iDecodeRet:" << iDecodeRet; } } } \ No newline at end of file +/** * 视频流解码引擎 * */ #include "VideoDecodeEngine.h" using namespace std; using namespace cv; using namespace ai_matrix; VideoDecodeEngine::VideoDecodeEngine() {} VideoDecodeEngine::~VideoDecodeEngine() {} APP_ERROR VideoDecodeEngine::Init() { dataSourceConfig_ = Config::getins()->getDataSourceConfig(); strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; LogInfo << "VideoDecodeEngine Init ok"; return APP_ERR_OK; } APP_ERROR VideoDecodeEngine::DeInit() { if (harddecoder_ != nullptr) { harddecoder_->hardDecoderDeInit(); delete harddecoder_; harddecoder_ = nullptr; } LogInfo << "VideoDecodeEngine DeInit ok"; return APP_ERR_OK; } APP_ERROR VideoDecodeEngine::Process() { int iRet = APP_ERR_OK; int iSkipCount = 1; while (!isStop_) { //从上一引擎接收图像数据 std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); // if (iSkipCount++ % dataSourceConfig_.iSkipInterval != 0) // { // continue; // } // iSkipCount = 1; if (pProcessData->bIsTrainEnd) { iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "push the decode yuv420m frame data failed..."; } continue; } //创建解码类 if (harddecoder_ == nullptr) { harddecoder_ = new HardDecode; int iRet = harddecoder_->hardDecoderInit(pProcessData->dataSourceInfo.iWidth, pProcessData->dataSourceInfo.iHeight, pProcessData->dataSourceInfo.iRate, pProcessData->pCodecParameters_); if (!iRet) { LogError << " 硬解码初始化失败!"; if (harddecoder_) { delete harddecoder_; harddecoder_ = nullptr; } continue; } } // 构造YUV420M数据 unsigned int pYUV420MBuffer_Size = pProcessData->dataSourceInfo.iWidth * pProcessData->dataSourceInfo.iHeight * 3 / 2; void *pYUV420MBuffer = nullptr; pYUV420MBuffer = new uint8_t[pYUV420MBuffer_Size]; std::shared_ptr pYUVData; // 智能指针管理内存 pYUVData.reset(pYUV420MBuffer, [](void *data){if(data) {delete[] data; data = nullptr;}}); // 这里填入一个指向完整H264数据帧的指针 harddecoder_->pPacket_->data = static_cast(pProcessData->sourceFrameData.pData.get()); // 这个填入H264数据帧的大小 harddecoder_->pPacket_->size = pProcessData->sourceFrameData.iSize; int iDecodeRet = harddecoder_->hardDecoder(pYUV420MBuffer, &pYUV420MBuffer_Size); if (iDecodeRet) { //硬解码YUV转BGR cv::Mat matYUV(pProcessData->dataSourceInfo.iHeight * 3 / 2, pProcessData->dataSourceInfo.iWidth, CV_8UC1); memcpy(matYUV.data, static_cast(pYUVData.get()), pYUV420MBuffer_Size); cv::Mat matBGR(pProcessData->dataSourceInfo.iHeight, pProcessData->dataSourceInfo.iWidth, CV_8UC3); cv::cvtColor(matYUV, matBGR, cv::COLOR_YUV2BGR_I420); cv::resize(matBGR, matBGR, cv::Size(IMAGE_WIDTH, IMAGE_HEIGHT)); unsigned int iResizeSize = IMAGE_WIDTH * IMAGE_HEIGHT * 3; void *pResizeBGRBuffer = nullptr; pResizeBGRBuffer = new uint8_t[iResizeSize]; memcpy(pResizeBGRBuffer, matBGR.data, iResizeSize); pProcessData->sourceFrameData.pData.reset(pResizeBGRBuffer, [](void *data) {if(data) {delete[] data; data = nullptr;} }); pProcessData->sourceFrameData.iSize = iResizeSize; pProcessData->dataSourceInfo.iWidth = IMAGE_WIDTH; pProcessData->dataSourceInfo.iHeight = IMAGE_HEIGHT; // vector compression_params; // compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg // compression_params.push_back(100); //图片质量 // cv::imwrite("./jpg/" + std::to_string(pProcessData->sourceFrameData.i64TimeStamp) + ".jpg", matBGR, compression_params); iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "push the decode yuv420m frame data failed..."; } } else { LogError << " 硬解码失败... 返回失败信息:" << iDecodeRet; } } } \ No newline at end of file diff --git a/src/engine/MoveEngine/MoveEngine.cpp b/src/engine/MoveEngine/MoveEngine.cpp index de18ae7..aa05256 100644 --- a/src/engine/MoveEngine/MoveEngine.cpp +++ b/src/engine/MoveEngine/MoveEngine.cpp @@ -156,17 +156,16 @@ void MoveEngine::SingleDeviceProcess(std::shared_ptr pProcessData, pProcessData->iDataNO = iMoveDataNO_++; //push端口,存图 std::shared_ptr pSaveImgData = std::make_shared(); - pSaveImgData->iFrameId = pProcessData->iFrameId; // 帧号 - pSaveImgData->strImgPath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainTime; - pSaveImgData->strImgName = std::to_string(pSaveImgData->iFrameId) + ".jpg"; - pSaveImgData->bIsEnd = pProcessData->bIsTrainEnd; - pSaveImgData->iTrainStage = iType; + pSaveImgData->strImgPath = baseConfig_.strDebugResultPath + "/" + pProcessData->strTrainDate + "/" + + StringUtil::getins()->replace_all_distinct(pProcessData->strTrainTime, ":", "-"); + pSaveImgData->strImgName = std::to_string(pProcessData->iFrameId) + ".jpg"; +// pSaveImgData->strTrainStage = intTrainStage_2_str(iType); pSaveImgData->frameData.pData = pProcessData->sourceFrameData.pData; pSaveImgData->frameData.iSize = pProcessData->sourceFrameData.iSize; pSaveImgData->frameData.iWidth = pProcessData->dataSourceInfo.iWidth; pSaveImgData->frameData.iHeight = pProcessData->dataSourceInfo.iHeight; pSaveImgData->frameData.i64TimeStamp = pProcessData->sourceFrameData.i64TimeStamp; -// outputQueMap_[strPort0_]->push(std::static_pointer_cast(pSaveImgData)); + outputQueMap_[strPort0_]->push(std::static_pointer_cast(pSaveImgData)); } APP_ERROR MoveEngine::Process() @@ -231,10 +230,10 @@ APP_ERROR MoveEngine::Process() // LogDebug <<"模型得分 车头:"<< fReturnVal[0] << " 车头车身交接:" << fReturnVal[1] <<" 无车:"<< fReturnVal[2]<<" 车尾:"<< fReturnVal[3]<<" 有车:"<< fReturnVal[4]; switch (iType) { case MONITOR_MODEL_TRAIN_HEAD: - LogDebug << "来车状态:有车头"; + LogDebug << "来车状态:车头"; break; case MONITOR_MODEL_HEAD_FIRST: - LogDebug << "来车状态:有车头"; + LogDebug << "来车状态:车头车身之间"; break; case MONITOR_MODEL_NO_TRAIN: LogDebug << "来车状态:无车"; @@ -243,15 +242,13 @@ APP_ERROR MoveEngine::Process() LogDebug << "来车状态:车尾"; break; case MONITOR_MODEL_TRAIN_BODY: - LogDebug << "来车状态:有车"; + LogDebug << "来车状态:车厢"; break; default: LogDebug << "来车状态:未定义"; break; } - - if (this->identifyConfig_.bTrainHeardDetect) { bGetTrainExist = (iType == MONITOR_MODEL_TRAIN_BODY @@ -330,3 +327,21 @@ APP_ERROR MoveEngine::Process() } } +std::string MoveEngine::intTrainStage_2_str(int iTrainStage) +{ + switch (iTrainStage) { + case MONITOR_MODEL_TRAIN_HEAD: + return "train_head"; + case MONITOR_MODEL_HEAD_FIRST: + return "head_and_carriage"; + case MONITOR_MODEL_NO_TRAIN: + return "no_train"; + case MONITOR_MODEL_TRAIN_TAIL: + return "train_tail"; + case MONITOR_MODEL_TRAIN_BODY: + return "carriage"; + default: + return ""; + } +} + diff --git a/src/engine/MoveEngine/MoveEngine.h b/src/engine/MoveEngine/MoveEngine.h index e8565c5..d85f242 100644 --- a/src/engine/MoveEngine/MoveEngine.h +++ b/src/engine/MoveEngine/MoveEngine.h @@ -42,6 +42,8 @@ private: //使用单device处理 void SingleDeviceProcess(std::shared_ptr pProcessData, int nType); + std::string intTrainStage_2_str(int iTrainStage); + void sendComeTrain(); void sendEndTrain(); @@ -51,8 +53,8 @@ private: ai_matrix::ModelConfig modelConfig_; ai_matrix::IdentifyConfig identifyConfig_; ai_matrix::BaseConfig baseConfig_; - std::string strResultPath_; - std::string strBestPath_; +// std::string strResultPath_; +// std::string strBestPath_; YoloV8Inference yolov8model; int iStepInter_ = 0; //(0:不识别; 1:开始识别; 2:结束识别) @@ -76,7 +78,7 @@ private: unsigned int input_size = STEP0_INPUT_SIZE; unsigned int output_size = STEP0_OUTPUT_SIZE; unsigned int det_size = STEP0_CLASS_NUM + STEP0_CLEAR_NUM + 5; - unsigned int batch_size = STEP0_BATCH_SIZE; + unsigned int batch_size = STEP0_BATCH_SIZE; YoloV5ModelInfo modelinfo; std::queue> queProcessData_;