From f18e10f8f32fb9af5c868bf830f29efe4d8968ed Mon Sep 17 00:00:00 2001 From: "Mr.V" Date: Mon, 12 Aug 2024 09:41:48 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E5=88=87=E5=88=86=E6=95=88=E6=9E=9C=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=8A=A5=E8=AD=A6=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 236 +---- config.yaml | 4 +- nvidia_ascend_engine/common/AppCommon.h | 81 +- .../DataDealEngine/DataDealEngine.cpp | 2 +- .../DataDealEngine/DataDealEngine.h | 1 + .../DataSourceEngine/CameraEngine.cpp | 2 +- .../DataSourceEngine/CameraEngine.h | 4 +- .../DataSourceEngine/ReadImgEngine.cpp | 2 +- .../DeviceStatusUpSerEngine.cpp | 270 +----- .../ResultToHttpSrvEngine.cpp | 2 +- .../DeleteExpiredFolderEngine.cpp | 2 +- .../DeleteExpiredFolderEngine.h | 1 + .../FilterEngine/FilterTrainStepOneEngine.cpp | 2 +- .../FilterEngine/FilterTrainStepOneEngine.h | 4 +- .../MergerEngine/MergerAllEngine.cpp | 40 +- .../SaveEngine/SaveCsvEngine.cpp | 2 +- .../SaveEngine/SaveImgEngine.cpp | 12 +- .../SaveEngine/SaveStepOneResultEngine.cpp | 706 +-------------- .../SelectBestEngine/SelectBestEngine.cpp | 766 +--------------- .../SocketEngine/SocketEngine.cpp | 666 +++++++------- .../TrainAnaEngine/TrainParationMgr.cpp | 2 +- .../TransEngine/TransTrainEngine.cpp | 841 +----------------- .../nvidia_engine/MoveEngine/MoveEngine.cpp | 12 +- .../TrainStepOneEngine/TrainStepOneEngine.cpp | 30 +- .../TrainStepTwoEngine/TrainStepTwoEngine.cpp | 247 +---- 25 files changed, 469 insertions(+), 3468 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04908e9..f6dc5a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,235 +1 @@ -cmake_minimum_required(VERSION 3.5) -cmake_policy(SET CMP0074 NEW) - -message("NVIDIA NX PLATFORM") -set(PROJECT_NAME train) -project(${PROJECT_NAME} VERSION 1.0) - - -add_definitions(-std=c++11) -add_definitions(-DAPI_EXPORTS) - -set(CMAKE_CXX_STANDARD 11) -#set(CMAKE_BUILD_TYPE Debug) -#set(CMAKE_BUILD_TYPE Release) -#add_definitions("-Wall -g") - - -#opencv -find_package(OpenCV REQUIRED) -# message(STATUS "${OpenCV_LIBS}") -# message(STATUS "${OpenCV_INCLUDE_DIRS}") - -find_package(CUDA REQUIRED) - -# 设置编译工具 -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_C_COMPILER "gcc") -set(CMAKE_CXX_COMPILER "g++") - - -# 设置项目生成目录 -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/app) - -# 设置调用库文件的位置 -set(CMAKE_SKIP_BUILD_RPATH FALSE) -set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -set(CMAKE_INSTALL_RPATH "./lib") - -set(SYS_USR_INCLUDE_DIR "/usr/include") -set(SYS_USR_LIB_DIR "/usr/lib") -set(SYS_USR_LOCAL_INCLUDE_DIR "/usr/local/include") -set(SYS_USR_LOCAL_LIB_DIR "/usr/local/lib") -# -- X86下使用 -- -set(AARCH64_LINUX_INCLUDE_DIR "/usr/include/x86_64-linux-gnu") -set(AARCH64_LINUX_LIB_DIR "/usr/lib/x86_64-linux-gnu") -# -- ARM下使用 -- -#set(AARCH64_LINUX_INCLUDE_DIR "/usr/include/aarch64-linux-gnu") -#set(AARCH64_LINUX_LIB_DIR "/usr/lib/aarch64-linux-gnu") - - -#opencv3.2.0的库文件在/usr/lib/aarch64-linux-gnu下 头文件路径在/usr/include/opencv2 -#opencv4.5.5的库文件在/usr/local/lib下 头文件路径在/usr/local/include/opencv4 -#目前使用最新版opencv4.5.5 -set(OPENCV_INCLUDE_DIR ${SYS_USR_LOCAL_INCLUDE_DIR}/opencv4) -set(OPENCV_LIB_DIR ${SYS_USR_LOCAL_LIB_DIR}) - -set(CUDA_DIR "/usr/local/cuda-11.7") -set(CUDA_INCLUDE_DIR ${CUDA_DIR}/include) -set(CUDA_LIB_DIR ${CUDA_DIR}/lib64) - -set(TENSORRT_INCLUDE_DIR ${AARCH64_LINUX_INCLUDE_DIR}) #tensorrt的头文件在/usr/include/aarch64-linux-gnu下 -set(TENSORRT_LIB_DIR ${AARCH64_LINUX_LIB_DIR}) #tensorrt的库文件在/usr/lib/aarch64-linux-gnu下 - -set(DRM_INCLUDE_DIR ${SYS_USR_INCLUDE_DIR}/libdrm) #DRM的头文件在/usr/include/libdrm下 - -set(TEGRA_LIB_DIR ${AARCH64_LINUX_LIB_DIR}/tegra) #tegra库文件路径/usr/lib/aarch64-linux-gnu/tegra - -#set(PCL_INCLUDE ${SYS_USR_LOCAL_INCLUDE_DIR}/pcl-1.7) #pcl头文件路径 - - -# nvidia ascend common include -include_directories( - #ai_matrix include - ${PROJECT_SOURCE_DIR}/ai_matrix - ${PROJECT_SOURCE_DIR}/ai_matrix/framework - ${PROJECT_SOURCE_DIR}/ai_matrix/myftp - ${PROJECT_SOURCE_DIR}/ai_matrix/myhttp - ${PROJECT_SOURCE_DIR}/ai_matrix/myJson - ${PROJECT_SOURCE_DIR}/ai_matrix/myJson/json - ${PROJECT_SOURCE_DIR}/ai_matrix/mylog - ${PROJECT_SOURCE_DIR}/ai_matrix/pcl - ${PROJECT_SOURCE_DIR}/ai_matrix/myqueue - ${PROJECT_SOURCE_DIR}/ai_matrix/myshell - ${PROJECT_SOURCE_DIR}/ai_matrix/myutils - - #nvidia ascend common cann include - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/BlockingQueue - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CBase64 - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommandParser - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommonDataType - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ConfigParser - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ErrorCode - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/FileManager - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/Log - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ - - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common - #common engine include - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/ControlEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataUploadEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/FilterEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/MergerEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SaveEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SelectBestEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TrainAnaEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TransEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataDealEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine - - #common tools rtsp_server include - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/3rdpart/md5 - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/net/ - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/xop/ -) - - -include_directories( - #nvidia engine include - - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepOneEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepTwoEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ContainerEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/DecodeEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MoveEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MyYaml - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine - - #nvidia_tools yolov5 include - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/include - - #third party include - ${CUDA_INCLUDE_DIR} - ${TENSORRT_INCLUDE_DIR} - ${DRM_INCLUDE_DIR} - ${OpenCV_DIR} - ${AARCH64_LINUX_INCLUDE_DIR} - ${SYS_USR_LOCAL_INCLUDE_DIR} -# ${PCL_INCLUDE} -) - - - -link_directories(${SYS_USR_LOCAL_LIB_DIR} - ${AARCH64_LINUX_LIB_DIR} - ${OPENCV_LIB_DIR} - ${CUDA_LIB_DIR} - ${TENSORRT_LIB_DIR} - ${TEGRA_LIB_DIR} -) - -#源文件 -#公共源文件 -file(GLOB_RECURSE COMMON_SRCS_LISTS - main.cpp - #ai_matrix src - ${PROJECT_SOURCE_DIR}/ai_matrix/framework/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myftp/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myhttp/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myJson/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/mylog/*.cpp - #${PROJECT_SOURCE_DIR}/ai_matrix/mypcl/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myqueue/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myshell/*.cpp - ${PROJECT_SOURCE_DIR}/ai_matrix/myutils/*.cpp - - #common cann src - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommandParser/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ConfigParser/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ErrorCode/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/FileManager/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/Log/*.cpp - - #common engine src - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine/*.cpp - - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/ControlEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataUploadEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/FilterEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/MergerEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SelectBestEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TrainAnaEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TransEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataDealEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SaveEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/*.cpp - - #common tools rtsp_server src - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/net/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/xop/*.cpp -) - -file(GLOB_RECURSE SRCS_LISTS - #nvidia engine src - #nvidia engine include - - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepOneEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepTwoEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MyYaml/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ContainerEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/DecodeEngine/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MoveEngine/*.cpp - - ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/*.cpp - - #nvidia tools yolov5 src - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/src/*.cpp - ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/src/*.cu -) - -cuda_add_executable(${PROJECT_NAME} ${COMMON_SRCS_LISTS} ${SRCS_LISTS}) - -target_link_libraries(${PROJECT_NAME} pthread) #other -target_link_libraries(${PROJECT_NAME} nvinfer nvonnxparser nvcaffe_parser nvinfer_plugin) #TensorRT -target_link_libraries(${PROJECT_NAME} cudart cuda) #CUDA - -target_link_libraries(${PROJECT_NAME} - ${OpenCV_LIBS} #third party librarys -# ${PCL_LIBRARY_DIRS} -# pcl_common pcl_io_ply pcl_keypoints pcl_registration pcl_segmentation pcl_features pcl_io pcl_octree #pcl -# pcl_sample_consensus pcl_surface pcl_filters pcl_kdtree pcl_recognition pcl_search pcl_tracking - avformat avcodec avutil avfilter swresample swscale postproc #VideoCodecV2 - yaml-cpp https_sn - jsoncpp curl boost_system boost_filesystem ssh2 - -Wl,-z,relro,-z,now,-z,noexecstack -pie -s -) +cmake_minimum_required(VERSION 3.5) cmake_policy(SET CMP0074 NEW) message("NVIDIA NX PLATFORM") set(PROJECT_NAME train) project(${PROJECT_NAME} VERSION 1.0) add_definitions(-std=c++11) add_definitions(-DAPI_EXPORTS) set(CMAKE_CXX_STANDARD 11) #set(CMAKE_BUILD_TYPE Debug) #set(CMAKE_BUILD_TYPE Release) #add_definitions("-Wall -g") #opencv find_package(OpenCV REQUIRED) # message(STATUS "${OpenCV_LIBS}") # message(STATUS "${OpenCV_INCLUDE_DIRS}") find_package(CUDA REQUIRED) # 设置编译工具 set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_C_COMPILER "gcc") set(CMAKE_CXX_COMPILER "g++") # 设置项目生成目录 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/app) # 设置调用库文件的位置 set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_INSTALL_RPATH "./lib") set(SYS_USR_INCLUDE_DIR "/usr/include") set(SYS_USR_LIB_DIR "/usr/lib") set(SYS_USR_LOCAL_INCLUDE_DIR "/usr/local/include") set(SYS_USR_LOCAL_LIB_DIR "/usr/local/lib") set(AARCH64_LINUX_INCLUDE_DIR "/usr/include/x86_64-linux-gnu") set(AARCH64_LINUX_LIB_DIR "/usr/lib/x86_64-linux-gnu") #opencv3.2.0的库文件在/usr/lib/aarch64-linux-gnu下 头文件路径在/usr/include/opencv2 #opencv4.5.5的库文件在/usr/local/lib下 头文件路径在/usr/local/include/opencv4 #目前使用最新版opencv4.5.5 set(OPENCV_INCLUDE_DIR ${SYS_USR_LOCAL_INCLUDE_DIR}/opencv4) set(OPENCV_LIB_DIR ${SYS_USR_LOCAL_LIB_DIR}) set(CUDA_DIR "/usr/local/cuda-11.7") set(CUDA_INCLUDE_DIR ${CUDA_DIR}/include) set(CUDA_LIB_DIR ${CUDA_DIR}/lib64) set(TENSORRT_INCLUDE_DIR ${AARCH64_LINUX_INCLUDE_DIR}) #tensorrt的头文件在/usr/include/aarch64-linux-gnu下 set(TENSORRT_LIB_DIR ${AARCH64_LINUX_LIB_DIR}) #tensorrt的库文件在/usr/lib/aarch64-linux-gnu下 set(DRM_INCLUDE_DIR ${SYS_USR_INCLUDE_DIR}/libdrm) #DRM的头文件在/usr/include/libdrm下 set(TEGRA_LIB_DIR ${AARCH64_LINUX_LIB_DIR}/tegra) #tegra库文件路径/usr/lib/aarch64-linux-gnu/tegra set(PCL_INCLUDE ${SYS_USR_LOCAL_INCLUDE_DIR}/pcl-1.7) #pcl头文件路径 # nvidia ascend common include include_directories( #ai_matrix include ${PROJECT_SOURCE_DIR}/ai_matrix ${PROJECT_SOURCE_DIR}/ai_matrix/framework ${PROJECT_SOURCE_DIR}/ai_matrix/myftp ${PROJECT_SOURCE_DIR}/ai_matrix/myhttp ${PROJECT_SOURCE_DIR}/ai_matrix/myJson ${PROJECT_SOURCE_DIR}/ai_matrix/myJson/json ${PROJECT_SOURCE_DIR}/ai_matrix/mylog ${PROJECT_SOURCE_DIR}/ai_matrix/pcl ${PROJECT_SOURCE_DIR}/ai_matrix/myqueue ${PROJECT_SOURCE_DIR}/ai_matrix/myshell ${PROJECT_SOURCE_DIR}/ai_matrix/myutils #nvidia ascend common cann include ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/BlockingQueue ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CBase64 ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommandParser ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommonDataType ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ConfigParser ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ErrorCode ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/FileManager ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/Log ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common #common engine include ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/ControlEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataUploadEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/FilterEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/MergerEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/PixelFormatConvertEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SaveEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SelectBestEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TrainAnaEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TransEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataDealEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine #common tools rtsp_server include ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/3rdpart/md5 ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/net/ ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/xop/ ) include_directories( #nvidia engine include ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepOneEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepTwoEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ContainerEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/DecodeEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MoveEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MyYaml ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine #nvidia_tools yolov5 include ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/include #third party include ${CUDA_INCLUDE_DIR} ${TENSORRT_INCLUDE_DIR} ${DRM_INCLUDE_DIR} ${OpenCV_DIR} ${AARCH64_LINUX_INCLUDE_DIR} ${SYS_USR_LOCAL_INCLUDE_DIR} ${PCL_INCLUDE} ) link_directories(${SYS_USR_LOCAL_LIB_DIR} ${AARCH64_LINUX_LIB_DIR} ${OPENCV_LIB_DIR} ${CUDA_LIB_DIR} ${TENSORRT_LIB_DIR} ${TEGRA_LIB_DIR} ) #源文件 #公共源文件 file(GLOB_RECURSE COMMON_SRCS_LISTS main.cpp #ai_matrix src ${PROJECT_SOURCE_DIR}/ai_matrix/framework/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myftp/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myhttp/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myJson/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/mylog/*.cpp #${PROJECT_SOURCE_DIR}/ai_matrix/mypcl/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myqueue/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myshell/*.cpp ${PROJECT_SOURCE_DIR}/ai_matrix/myutils/*.cpp #common cann src ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/CommandParser/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ConfigParser/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/ErrorCode/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/FileManager/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_base/Base/Log/*.cpp #common engine src ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/PixelFormatConvertEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/ControlEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataUploadEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/FilterEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/MergerEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SelectBestEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TrainAnaEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/TransEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataDealEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SocketEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DataSourceEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/PixelFormatConvertEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/SaveEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/*.cpp #common tools rtsp_server src ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/net/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/common_tools/rtsp_server/xop/*.cpp ) file(GLOB_RECURSE SRCS_LISTS #nvidia engine src #nvidia engine include ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepOneEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ChkDateStepTwoEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MyYaml/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/ContainerEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/DecodeEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/MoveEngine/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_engine/nvidia_engine/*.cpp #nvidia tools yolov5 src ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/src/*.cpp ${PROJECT_SOURCE_DIR}/nvidia_ascend_tools/nvidia_tools/yolov5/src/*.cu ) cuda_add_executable(${PROJECT_NAME} ${COMMON_SRCS_LISTS} ${SRCS_LISTS}) target_link_libraries(${PROJECT_NAME} pthread) #other target_link_libraries(${PROJECT_NAME} nvinfer nvonnxparser nvcaffe_parser nvinfer_plugin) #TensorRT target_link_libraries(${PROJECT_NAME} cudart cuda) #CUDA target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} #third party librarys ${PCL_LIBRARY_DIRS} pcl_common pcl_io_ply pcl_keypoints pcl_registration pcl_segmentation pcl_features pcl_io pcl_octree #pcl pcl_sample_consensus pcl_surface pcl_filters pcl_kdtree pcl_recognition pcl_search pcl_tracking avformat avcodec avutil avfilter swresample swscale postproc #VideoCodecV2 yaml-cpp https_sn jsoncpp curl boost_system boost_filesystem ssh2 -Wl,-z,relro,-z,now,-z,noexecstack -pie -s ) \ No newline at end of file diff --git a/config.yaml b/config.yaml index b236405..aa16c5e 100644 --- a/config.yaml +++ b/config.yaml @@ -114,7 +114,7 @@ model: gc_http_open: 1 username: "guest_01" -password: "d55b0f642e817eea24725d2f2a31dd08" # 神东 +password: "0a1688bce402a5f6a4279abbfc89c203" # 神东 d55b0f642e817eea24725d2f2a31dd08 gc_http_url: "http://192.168.2.211:20004/api/train-carriage/identification/video-save" gc_gettoken_url: "http://192.168.2.211:20004/api/blade-auth/oauth/token" gc_image_srv: "http://192.168.2.211:9010/" @@ -182,5 +182,5 @@ gc_c_space_frame_width: 500 # 是否识别车头 gc_train_heard_detect: true -#过期文件夹天数 +# 识别结果保存天数 gc_days_for_result_expire_folder: 3 diff --git a/nvidia_ascend_engine/common/AppCommon.h b/nvidia_ascend_engine/common/AppCommon.h index 2cdea93..3c20bd9 100644 --- a/nvidia_ascend_engine/common/AppCommon.h +++ b/nvidia_ascend_engine/common/AppCommon.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -459,10 +459,10 @@ typedef struct std::shared_ptr pSrcData; // Smart pointer of data(源数据) 推理时,RGB数据会拷贝一份,源数据不变用于传送到后处理引擎画框,另一份数据用于resize成640x640并归一化到0-1 uint64_t i64TimeStamp = 0; //帧数据时间戳 Step1Location step1Location; //step2 use - int iTargetType; //目标类别 (0:车号; 1:属性; 2:车头; 3:定检期; 4:集装箱) + int iTargetType; //目标类别 (0:车号; 1:属性; 2:车头; 3:定检期; 4:集装箱) int iBigClassId = -1; //大框id (给第二步用 1-属性 23456-编号) int iCarXH = 0; //当前大框所属车厢 - + } InferenceData; @@ -491,7 +491,7 @@ typedef struct std::shared_ptr pData = nullptr; // Smart pointer of data uint64_t i64TimeStamp = 0; //帧数据时间戳 bool bHostMemory = false; //数据解码后内存是否在Host侧 - std::string strPicFilePath; + std::string strPicFilePath; std::string strTrainDate; //过车日期 (格式:YYYY-MM-DD) std::string strTrainName; //车次 (格式:HH-MM-SS) bool bIsEnd = false; //列车结束标识 @@ -756,7 +756,7 @@ typedef struct std::string strTrainDate; //过车日期 (格式:YYYY-MM-DD) std::string strTrainName; //车次 (格式:HH-MM-SS) std::string strContainerNo; //集装箱号 - std::string strBestImg; //集装箱最优图 + std::string strBestImg; //集装箱最优图 float fScoreSum = 0; //集装箱最优图总得分, 取最优帧用 uint64_t i64TimeStamp = 0; //集装箱最优图时间戳 Step1Location step1Location; //原图上大框坐标 @@ -832,30 +832,30 @@ typedef struct imganalyse { // from file /////////下述设定取自csv文件 - int nType; //算法目的 0:动态检测 1:车厢划分 - int nAreaX1; //算法监测区域 开始位置x坐标 - int nAreaY1; //算法监测区域 开始位置y坐标 - int nAreaX2; //算法监测区域 结束位置x坐标 - int nAreaY2; //算法监测区域 结束位置y坐标 - int bOrLevel; //算法结果融合等级 相同值进行与运算 不同值进行或运算 - bool bDiff; //是否以不同作为判断条件 false:以匹配度相同作为判定条件 true:以匹配度不同作为判定条件 - bool bOn; //是否启用改区域匹配监测(该算法是否有效) false:不启用(无效) true:启用(有效) - double dSameThresholdVal; //判定匹配相同的阈值 - double dDiffThresholdVal; //判定匹配不同的阈值 - int nPauseMaxCoumt; //判定为停车的最大计量(超过设定值判定为停车) - int npicimprovetype; //图像改善处理(包含 灰度化/均衡化直方图/gamma变换/自定义) - int templemethod; //模型比对模式 - int histmethod; //直方图比对模式 - int specmethod; //自定义比对模式 - int compmethod; //对比类型(模型比对/模型比对/自定义比对,可多选) - std::string baseImagePath; //基准图片路径 + int nType; //算法目的 0:动态检测 1:车厢划分 + int nAreaX1; //算法监测区域 开始位置x坐标 + int nAreaY1; //算法监测区域 开始位置y坐标 + int nAreaX2; //算法监测区域 结束位置x坐标 + int nAreaY2; //算法监测区域 结束位置y坐标 + int bOrLevel; //算法结果融合等级 相同值进行与运算 不同值进行或运算 + bool bDiff; //是否以不同作为判断条件 false:以匹配度相同作为判定条件 true:以匹配度不同作为判定条件 + bool bOn; //是否启用改区域匹配监测(该算法是否有效) false:不启用(无效) true:启用(有效) + double dSameThresholdVal; //判定匹配相同的阈值 + double dDiffThresholdVal; //判定匹配不同的阈值 + int nPauseMaxCoumt; //判定为停车的最大计量(超过设定值判定为停车) + int npicimprovetype; //图像改善处理(包含 灰度化/均衡化直方图/gamma变换/自定义) + int templemethod; //模型比对模式 + int histmethod; //直方图比对模式 + int specmethod; //自定义比对模式 + int compmethod; //对比类型(模型比对/模型比对/自定义比对,可多选) + std::string baseImagePath; //基准图片路径 /////////下述设定为处理识别变量 - double dComparePoint; //比对值 + double dComparePoint; //比对值 double dPreComparePoint; //比对值 - bool bChanged; //与基准图对比值 是否发生变化 true:发生变化 false:没有发生变化 - bool bPreChanged; //上一帧与基准图对比值 + bool bChanged; //与基准图对比值 是否发生变化 true:发生变化 false:没有发生变化 + bool bPreChanged; //上一帧与基准图对比值 bool fluctuationFlag; //最近100帧的最大值与最小值的波动标志 - int nSameCount; //比对值没有发生变化的计数 + int nSameCount; //比对值没有发生变化的计数 int iIndex; //第几个配置项 }AnalyseInfo; @@ -866,25 +866,25 @@ typedef struct trainpartion { std::string strTrainDate; std::string strTrainName; - int nindex; //车厢顺位 - uint64_t i64StartTimeStamp; //当节车厢出现的开始帧时间 - uint64_t i64EndTimeStamp; //当节车厢出现的结束帧时间 - float fspeed; //当节车厢的车速 - int startframe; //当节车厢出现的开始帧帧号 - int endframe; //当节车厢出现的结束帧帧号 + int nindex; //车厢顺位 + uint64_t i64StartTimeStamp; //当节车厢出现的开始帧时间 + uint64_t i64EndTimeStamp; //当节车厢出现的结束帧时间 + float fspeed; //当节车厢的车速 + int startframe; //当节车厢出现的开始帧帧号 + int endframe; //当节车厢出现的结束帧帧号 int modelSpaceFrame; - bool bfuncconfirmed; //是否算法划分完成 true:是 false:否 - bool bmodelconfirmed; //是否根据第一次识别结果确认完成 true:是 false:否 - float fLTX; //车钩开始位置X值 - float fLTY; //车钩开始位置y值 - float fRBX; //车钩结束位置X值 - float fRBY; //车钩结束位置y值 + bool bfuncconfirmed; //是否算法划分完成 true:是 false:否 + bool bmodelconfirmed; //是否根据第一次识别结果确认完成 true:是 false:否 + float fLTX; //车钩开始位置X值 + float fLTY; //车钩开始位置y值 + float fRBX; //车钩结束位置X值 + float fRBY; //车钩结束位置y值 bool bIsEnd = false; //是否最后一节 int nStatus; //方向(0:未知,1:向左行驶,2:向右行驶) int iRate; //帧率 }PartionInfo; -typedef struct +typedef struct { std::shared_ptr processData; std::string strAllClassType; @@ -895,7 +895,8 @@ typedef struct { int iBigClassId = -1; //大框id (给第二步用 1-属性 23456-编号) uint32_t iFrameId = 0; //帧号 - float fCenterX; //第一步识别目标中心点X坐标 + float fCenterX; //第一步识别目标中心点X坐标 + float fTargetWidth; // 第一步识别目标X坐标宽度 } CalculateInfo; diff --git a/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.cpp b/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.cpp index 4692fcf..8e38767 100644 --- a/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.cpp @@ -1 +1 @@ -#include "DataDealEngine.h" using namespace ai_matrix; extern std::atomic_uint64_t g_i64ReRunTimeStamp; extern std::atomic_uint32_t g_iReRunOrigFrameId; extern std::atomic_uint32_t g_iReRunFrameId; DataDealEngine::DataDealEngine() {} DataDealEngine::~DataDealEngine() {} APP_ERROR DataDealEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); iPushDirection_ = MyYaml::GetIns()->GetIntValue("gc_push_direction"); dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); //获取摄像机参数 iIntervalTime_ = (dataSourceConfig_.iSkipInterval - 1) * 40 * 1000; mapUseDataSouceCfg_ = MyYaml::GetIns()->GetUseDataSourceConfig(); std::string delimiter(","); for (auto iter = mapUseDataSouceCfg_.begin(); iter!=mapUseDataSouceCfg_.end(); iter++) { int iSourceId = iter->first; std::vector vecSplit = MyUtils::getins()->split(iter->second.strTarget, delimiter); std::vector vecPushPorts; for (auto iter = vecSplit.begin(); iter != vecSplit.end(); iter++) { if (*iter == "NUM") { vecPushPorts.push_back(strPort0_); } else if (*iter == "CHKDATE") { vecPushPorts.push_back(strPort1_); } else if(*iter == "CONTAINER" || *iter == "CONTAINER_T") { vecPushPorts.push_back(strPort2_); } } mapSourcePushPort_[iSourceId] = vecPushPorts; } InitParam(); LogInfo << "engineId_:" << engineId_ << " DataDealEngine Init ok"; return APP_ERR_OK; } APP_ERROR DataDealEngine::DeInit() { LogInfo << "engineId_:" << engineId_ << " DataDealEngine DeInit ok"; return APP_ERR_OK; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void DataDealEngine::InitParam() { iOrigDataNO_ = 1; strDataDir_ = ""; moveData_.i64TimeStamp = 0; moveData_.bHasTrain = false; moveData_.bIsEnd = false; iDataNO_ = 1; strTrainDate_ = ""; strTrainName_ = ""; iDirection_ = DIRECTION_UNKNOWN; bNotPushFlag_ = false; } /** * 图片数据解码 * inParam : RawData &rawData :图片数据 * outParam: std::shared_ptr pDecodedData :解码数据 * return : true(编码成功)/false(编码失败) */ bool DataDealEngine::GetJpegdOut(std::shared_ptr pDecodedData, RawData &rawData) { return true; } /** * 读取图片和文本 * inParam : N/A * outParam: N/A * return : N/A */ bool DataDealEngine::ReadFileInfo(Json::Value &jvFrameInfo, RawData &rawData, std::string &strFileName, std::string &strImgName) { //图片或文件不存在时,休眠10ms直接return,重新获取。 if (access(strFileName.c_str(), F_OK) != 0 || access(strImgName.c_str(), F_OK) != 0) { LogWarn << "txt:" << strFileName << " or image:" << strImgName << " no exist"; return false; } if (!MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFileName)) { LogError << "Failed to read txt:" << strFileName; return false; } //读取图片内容 // int iRet = ReadFile(strImgName, rawData); // if (iRet != APP_ERR_OK) // { // LogError << "Failed to read image:" << strImgName; // return false; // } return true; } /** * push数据到队列,队列满时则休眠一段时间再push。 * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void DataDealEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } /** * 构造处理数据并push * inParam : N/A * outParam: N/A * return : N/A */ void DataDealEngine::MakeProcessData() { int iRet = APP_ERR_OK; uint64_t i64TimeStampTemp = 0; bool bIsEndByStop = false; uint64_t i64ReRunTimeStamp = 0; uint32_t iReRunOrigFrameId = 0; uint32_t iReRunFrameId = 0; if (g_iReRunOrigFrameId != 0) { LogDebug << "g_i64ReRunTimeStamp:" << g_i64ReRunTimeStamp << " g_iReRunOrigFrameId:" << g_iReRunOrigFrameId << " g_iReRunFrameId:" << g_iReRunFrameId; i64ReRunTimeStamp = g_i64ReRunTimeStamp; iReRunOrigFrameId = g_iReRunOrigFrameId; iReRunFrameId = g_iReRunFrameId; g_i64ReRunTimeStamp = 0; g_iReRunOrigFrameId = 0; g_iReRunFrameId = 0; bIsEndByStop = true; } for (auto iter = mapUseDataSouceCfg_.begin(); iter!=mapUseDataSouceCfg_.end(); iter++) { int iSourceId = iter->first; char szCameraNo[5] = {0}; sprintf(szCameraNo, "%03d/", iSourceId + 1); uint32_t iOrigFrameId = iOrigDataNO_ * dataSourceConfig_.iSkipInterval; uint32_t iFrameId = iDataNO_ * dataSourceConfig_.iSkipInterval; bool bIsEndFlag = (moveData_.bIsEnd && moveData_.iFrameId == iOrigFrameId); if (bIsEndByStop) { bIsEndFlag = true; iOrigFrameId = iReRunOrigFrameId; iFrameId = iReRunFrameId; } LogInfo << "sourceid:" << iSourceId << " MakeProcessData origtime:" << moveData_.strTrainName << " iOrigFrameId:" << iOrigFrameId << " time:" << strTrainName_ << " iFrameId:" << iFrameId << " bIsEndFlag:" << bIsEndFlag; std::string strImgName = strDataDir_ + szCameraNo + std::to_string(iOrigFrameId); strImgName += (iter->second.iRotate != 0) ? "_rotate.jpg" : ".jpg"; std::string strFileName = strDataDir_ + szCameraNo + std::to_string(iOrigFrameId) + ".txt"; //摄像头读取失败后重试30次。 Json::Value jvFrameInfo; RawData rawData; bool bRet = false; int iNoDataCnt = 0; while (!isStop_ && iNoDataCnt < 30) { bRet = ReadFileInfo(jvFrameInfo, rawData, strFileName, strImgName); if (bRet) { break; } usleep(500 * 1000); // 500ms iNoDataCnt++; } //组织数据 std::shared_ptr pProcessData = std::make_shared(); pProcessData->iDataSource = iSourceId; pProcessData->iFrameId = iFrameId; pProcessData->strPicFilePath = strImgName; pProcessData->i64TimeStamp = i64TimeStampTemp; pProcessData->strOrigTrainDate = moveData_.strTrainDate; pProcessData->strOrigTrainName = moveData_.strTrainName; pProcessData->iOrigFrameId = iOrigFrameId; pProcessData->strTrainDate = strTrainDate_; pProcessData->strTrainName = strTrainName_; pProcessData->iStatus = TRAINSTATUS_RUN; pProcessData->bIsEnd = bIsEndFlag; pProcessData->iDataNO = iDataNO_; if (bRet) { i64TimeStampTemp = jvFrameInfo["timeStamp"].asUInt64(); pProcessData->i64TimeStamp = i64TimeStampTemp; pProcessData->iWidth = jvFrameInfo["width"].asInt(); pProcessData->iHeight = jvFrameInfo["height"].asInt(); pProcessData->iDirection = jvFrameInfo["direction"].asInt(); pProcessData->iRate = jvFrameInfo["rate"].asInt(); pProcessData->nMonitorState = jvFrameInfo["moveType"].asInt(); cv::Mat cvframe = cv::imread(pProcessData->strPicFilePath); int iBufferSize = pProcessData->iWidth * pProcessData->iHeight * 3; void* pBGRBufferobj = nullptr; pBGRBufferobj = new uint8_t[iBufferSize]; memcpy(pBGRBufferobj, cvframe.data, iBufferSize); pProcessData->pData.reset(pBGRBufferobj, [](void* data){if(data) {delete[] data; data = nullptr;}}); pProcessData->iSize = iBufferSize; } std::vector vecPushPorts = mapSourcePushPort_[iSourceId]; for (int iPort = 0; iPort < vecPushPorts.size(); iPort++) { if (iPort == vecPushPorts.size() - 1) { //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast(pProcessData)); PushData(vecPushPorts[iPort], pProcessData); continue; } std::shared_ptr pNewProcessData = std::make_shared(); *pNewProcessData = *pProcessData; //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast(pNewProcessData)); PushData(vecPushPorts[iPort], pNewProcessData); } } iOrigDataNO_++; iDataNO_++; //每组处理数据需间隔一定时间 usleep(iIntervalTime_); if (bIsEndByStop) { iDataNO_ = 1; iOrigDataNO_ = iReRunOrigFrameId / dataSourceConfig_.iSkipInterval; std::string strDateTime = MyUtils::getins()->GetDateTimeByMilliSeconds(i64ReRunTimeStamp); strTrainDate_ = strDateTime.substr(0, 10); strTrainName_ = strDateTime.substr(11, strDateTime.length()); std::string strTrainPath = strResultPath_ + strTrainDate_ + "/" + strTrainName_ + "/"; MyUtils::getins()->CreateDirPath(strTrainPath); LogDebug << "rerun traindate:" << strTrainDate_ << " trainname:" << strTrainName_; } } APP_ERROR DataDealEngine::Process() { int iRet = APP_ERR_OK; //return APP_ERR_OK; while (!isStop_) { //获取主摄像头检测的状态 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr != pVoidData0) { std::shared_ptr pMoveData = std::static_pointer_cast(pVoidData0); // queuwMoveData_.push(*pMoveData); moveData_ = *pMoveData; LogDebug << "traindate:" << moveData_.strTrainDate << " trainname:" << moveData_.strTrainName << " MoveData frameid:" << moveData_.iFrameId << " IsEnd:" << moveData_.bIsEnd; } // LogDebug << "【帧号】" << (iDataNO_ * dataSourceConfig_.iSkipInterval); // if (queuwMoveData_.size() > 0 && (iDataNO_ * dataSourceConfig_.iSkipInterval) >= queuwMoveData_.front().iFrameId) // { // moveData_ = queuwMoveData_.front(); // queuwMoveData_.pop(); // LogDebug << "!!!--- moveDate 更新"; // } if (!moveData_.bHasTrain) { usleep(1000); //1ms continue; } //第一个数据,休眠1s,等待图片存入本地 if (iOrigDataNO_ == 1) { usleep(1000 * 1000); //1s } if (strDataDir_.empty()) { strDataDir_ = strResultPath_ + moveData_.strTrainDate + "/" + moveData_.strTrainName + "/"; strTrainDate_ = moveData_.strTrainDate; strTrainName_ = moveData_.strTrainName; } //如果设置了方向,则方向不对直接过滤,但结束帧不能过滤,需流转到后面Engine,保证后面处理正确。 if (iDirection_ == DIRECTION_UNKNOWN) { std::string strFilePath = strResultPath_ + strTrainDate_ + "/" + strTrainName_ + "/" + "direction.txt"; Json::Value jvDirectionInfo; if (MyUtils::getins()->ReadJsonInfo(jvDirectionInfo, strFilePath, 0)) { iDirection_ = jvDirectionInfo["direction"].asInt(); } } if (!moveData_.bIsEnd) { if (iDirection_ == DIRECTION_UNKNOWN || iDirection_ == iPushDirection_ || iPushDirection_ == DIRECTION_UNKNOWN) { MakeProcessData(); } else { LogDebug << "traindate:" << strTrainDate_ << " trainname:" << strTrainName_ << " iOrigDataNO_:" << iOrigDataNO_ << " continue."; bNotPushFlag_ = true; usleep(iIntervalTime_); //每组处理数据需间隔一定时间 continue; } } else { if (bNotPushFlag_) { iOrigDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; iDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; } if (iOrigDataNO_ * dataSourceConfig_.iSkipInterval > moveData_.iFrameId) { LogDebug << "dealFrameid:" << iOrigDataNO_ * dataSourceConfig_.iSkipInterval << " moveFrameid:" << moveData_.iFrameId; iOrigDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; MakeProcessData(); } else { while (!isStop_ && iOrigDataNO_ * dataSourceConfig_.iSkipInterval <= moveData_.iFrameId) { //继续处理 MakeProcessData(); } } InitParam(); } } return APP_ERR_OK; } \ No newline at end of file +#include "DataDealEngine.h" using namespace ai_matrix; extern std::atomic_uint64_t g_i64ReRunTimeStamp; extern std::atomic_uint32_t g_iReRunOrigFrameId; extern std::atomic_uint32_t g_iReRunFrameId; DataDealEngine::DataDealEngine() {} DataDealEngine::~DataDealEngine() {} APP_ERROR DataDealEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); iPushDirection_ = MyYaml::GetIns()->GetIntValue("gc_push_direction"); dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); //获取摄像机参数 iIntervalTime_ = (dataSourceConfig_.iSkipInterval - 1) * 40 * 1000; mapUseDataSouceCfg_ = MyYaml::GetIns()->GetUseDataSourceConfig(); std::string delimiter(","); for (auto iter = mapUseDataSouceCfg_.begin(); iter!=mapUseDataSouceCfg_.end(); iter++) { int iSourceId = iter->first; std::vector vecSplit = MyUtils::getins()->split(iter->second.strTarget, delimiter); std::vector vecPushPorts; for (auto iter = vecSplit.begin(); iter != vecSplit.end(); iter++) { if (*iter == "NUM") { vecPushPorts.push_back(strPort0_); } else if (*iter == "CHKDATE") { vecPushPorts.push_back(strPort1_); } else if(*iter == "CONTAINER" || *iter == "CONTAINER_T") { vecPushPorts.push_back(strPort2_); } } mapSourcePushPort_[iSourceId] = vecPushPorts; } InitParam(); LogInfo << "engineId_:" << engineId_ << " DataDealEngine Init ok"; return APP_ERR_OK; } APP_ERROR DataDealEngine::DeInit() { LogInfo << "engineId_:" << engineId_ << " DataDealEngine DeInit ok"; return APP_ERR_OK; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void DataDealEngine::InitParam() { iOrigDataNO_ = 1; strDataDir_ = ""; moveData_.i64TimeStamp = 0; moveData_.bHasTrain = false; moveData_.bIsEnd = false; iDataNO_ = 1; strTrainDate_ = ""; strTrainName_ = ""; iDirection_ = DIRECTION_UNKNOWN; bNotPushFlag_ = false; } /** * 图片数据解码 * inParam : RawData &rawData :图片数据 * outParam: std::shared_ptr pDecodedData :解码数据 * return : true(编码成功)/false(编码失败) */ bool DataDealEngine::GetJpegdOut(std::shared_ptr pDecodedData, RawData &rawData) { return true; } /** * 读取图片和文本 * inParam : N/A * outParam: N/A * return : N/A */ bool DataDealEngine::ReadFileInfo(Json::Value &jvFrameInfo, RawData &rawData, std::string &strFileName, std::string &strImgName) { //图片或文件不存在时,休眠10ms直接return,重新获取。 if (access(strFileName.c_str(), F_OK) != 0 || access(strImgName.c_str(), F_OK) != 0) { LogWarn << "txt:" << strFileName << " or image:" << strImgName << " no exist"; return false; } if (!MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFileName)) { LogError << "Failed to read txt:" << strFileName; return false; } //读取图片内容 // int iRet = ReadFile(strImgName, rawData); // if (iRet != APP_ERR_OK) // { // LogError << "Failed to read image:" << strImgName; // return false; // } return true; } /** * push数据到队列,队列满时则休眠一段时间再push。 * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void DataDealEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } /** * 构造处理数据并push * inParam : N/A * outParam: N/A * return : N/A */ void DataDealEngine::MakeProcessData() { int iRet = APP_ERR_OK; uint64_t i64TimeStampTemp = 0; bool bIsEndByStop = false; uint64_t i64ReRunTimeStamp = 0; uint32_t iReRunOrigFrameId = 0; uint32_t iReRunFrameId = 0; if (g_iReRunOrigFrameId != 0) { LogDebug << "g_i64ReRunTimeStamp:" << g_i64ReRunTimeStamp << " g_iReRunOrigFrameId:" << g_iReRunOrigFrameId << " g_iReRunFrameId:" << g_iReRunFrameId; i64ReRunTimeStamp = g_i64ReRunTimeStamp; iReRunOrigFrameId = g_iReRunOrigFrameId; iReRunFrameId = g_iReRunFrameId; g_i64ReRunTimeStamp = 0; g_iReRunOrigFrameId = 0; g_iReRunFrameId = 0; bIsEndByStop = true; } for (auto iter = mapUseDataSouceCfg_.begin(); iter!=mapUseDataSouceCfg_.end(); iter++) { int iSourceId = iter->first; char szCameraNo[5] = {0}; sprintf(szCameraNo, "%03d/", iSourceId + 1); uint32_t iOrigFrameId = iOrigDataNO_ * dataSourceConfig_.iSkipInterval; uint32_t iFrameId = iDataNO_ * dataSourceConfig_.iSkipInterval; bool bIsEndFlag = (moveData_.bIsEnd && moveData_.iFrameId == iOrigFrameId); if (bIsEndByStop) { bIsEndFlag = true; iOrigFrameId = iReRunOrigFrameId; iFrameId = iReRunFrameId; } LogInfo << "sourceid:" << iSourceId << " MakeProcessData origtime:" << moveData_.strTrainName << " iOrigFrameId:" << iOrigFrameId << " time:" << strTrainName_ << " iFrameId:" << iFrameId << " bIsEndFlag:" << bIsEndFlag; std::string strImgName = strDataDir_ + szCameraNo + std::to_string(iOrigFrameId); strImgName += (iter->second.iRotate != 0) ? "_rotate.jpg" : ".jpg"; std::string strFileName = strDataDir_ + szCameraNo + std::to_string(iOrigFrameId) + ".txt"; //摄像头读取失败后重试30次。 Json::Value jvFrameInfo; RawData rawData; bool bRet = false; int iNoDataCnt = 0; while (!isStop_ && iNoDataCnt < 30) { bRet = ReadFileInfo(jvFrameInfo, rawData, strFileName, strImgName); if (bRet) { break; } usleep(500 * 1000); // 500ms iNoDataCnt++; } //组织数据 std::shared_ptr pProcessData = std::make_shared(); pProcessData->iDataSource = iSourceId; pProcessData->iFrameId = iFrameId; pProcessData->strPicFilePath = strImgName; pProcessData->i64TimeStamp = i64TimeStampTemp; pProcessData->strOrigTrainDate = moveData_.strTrainDate; pProcessData->strOrigTrainName = moveData_.strTrainName; pProcessData->iOrigFrameId = iOrigFrameId; pProcessData->strTrainDate = strTrainDate_; pProcessData->strTrainName = strTrainName_; pProcessData->iStatus = TRAINSTATUS_RUN; pProcessData->bIsEnd = bIsEndFlag; pProcessData->iDataNO = iDataNO_; // pProcessData->nMonitorState = moveData_.nMonitorState; pProcessData->nMonitorState = jvFrameInfo["moveType"].asInt(); if (bRet) { i64TimeStampTemp = jvFrameInfo["timeStamp"].asUInt64(); pProcessData->i64TimeStamp = i64TimeStampTemp; pProcessData->iWidth = jvFrameInfo["width"].asInt(); pProcessData->iHeight = jvFrameInfo["height"].asInt(); pProcessData->iDirection = jvFrameInfo["direction"].asInt(); pProcessData->iRate = jvFrameInfo["rate"].asInt(); cv::Mat cvframe = cv::imread(pProcessData->strPicFilePath); int iBufferSize = pProcessData->iWidth * pProcessData->iHeight * 3; void* pBGRBufferobj = nullptr; pBGRBufferobj = new uint8_t[iBufferSize]; memcpy(pBGRBufferobj, cvframe.data, iBufferSize); pProcessData->pData.reset(pBGRBufferobj, [](void* data){if(data) {delete[] data; data = nullptr;}}); pProcessData->iSize = iBufferSize; } std::vector vecPushPorts = mapSourcePushPort_[iSourceId]; for (int iPort = 0; iPort < vecPushPorts.size(); iPort++) { if (iPort == vecPushPorts.size() - 1) { //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast(pProcessData)); PushData(vecPushPorts[iPort], pProcessData); continue; } std::shared_ptr pNewProcessData = std::make_shared(); *pNewProcessData = *pProcessData; //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast(pNewProcessData)); PushData(vecPushPorts[iPort], pNewProcessData); } } iOrigDataNO_++; iDataNO_++; //每组处理数据需间隔一定时间 usleep(iIntervalTime_); if (bIsEndByStop) { iDataNO_ = 1; iOrigDataNO_ = iReRunOrigFrameId / dataSourceConfig_.iSkipInterval; std::string strDateTime = MyUtils::getins()->GetDateTimeByMilliSeconds(i64ReRunTimeStamp); strTrainDate_ = strDateTime.substr(0, 10); strTrainName_ = strDateTime.substr(11, strDateTime.length()); std::string strTrainPath = strResultPath_ + strTrainDate_ + "/" + strTrainName_ + "/"; MyUtils::getins()->CreateDirPath(strTrainPath); LogDebug << "rerun traindate:" << strTrainDate_ << " trainname:" << strTrainName_; } } APP_ERROR DataDealEngine::Process() { int iRet = APP_ERR_OK; //return APP_ERR_OK; while (!isStop_) { //获取主摄像头检测的状态 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr != pVoidData0) { std::shared_ptr pMoveData = std::static_pointer_cast(pVoidData0); // queuwMoveData_.push(*pMoveData); moveData_ = *pMoveData; LogDebug << "traindate:" << moveData_.strTrainDate << " trainname:" << moveData_.strTrainName << " MoveData frameid:" << moveData_.iFrameId << " IsEnd:" << moveData_.bIsEnd; } // LogDebug << "【帧号】" << (iDataNO_ * dataSourceConfig_.iSkipInterval); // if (queuwMoveData_.size() > 0 && (iDataNO_ * dataSourceConfig_.iSkipInterval) >= queuwMoveData_.front().iFrameId) // { // moveData_ = queuwMoveData_.front(); // queuwMoveData_.pop(); // LogDebug << "!!!--- moveDate 更新"; // } if (!moveData_.bHasTrain) { usleep(1000); //1ms continue; } //第一个数据,休眠1s,等待图片存入本地 if (iOrigDataNO_ == 1) { usleep(1000 * 1000); //1s } if (strDataDir_.empty()) { strDataDir_ = strResultPath_ + moveData_.strTrainDate + "/" + moveData_.strTrainName + "/"; strTrainDate_ = moveData_.strTrainDate; strTrainName_ = moveData_.strTrainName; } //如果设置了方向,则方向不对直接过滤,但结束帧不能过滤,需流转到后面Engine,保证后面处理正确。 if (iDirection_ == DIRECTION_UNKNOWN) { std::string strFilePath = strResultPath_ + strTrainDate_ + "/" + strTrainName_ + "/" + "direction.txt"; Json::Value jvDirectionInfo; if (MyUtils::getins()->ReadJsonInfo(jvDirectionInfo, strFilePath, 0)) { iDirection_ = jvDirectionInfo["direction"].asInt(); } } if (!moveData_.bIsEnd) { if (iDirection_ == DIRECTION_UNKNOWN || iDirection_ == iPushDirection_ || iPushDirection_ == DIRECTION_UNKNOWN) { MakeProcessData(); } else { LogDebug << "traindate:" << strTrainDate_ << " trainname:" << strTrainName_ << " iOrigDataNO_:" << iOrigDataNO_ << " continue."; bNotPushFlag_ = true; usleep(iIntervalTime_); //每组处理数据需间隔一定时间 continue; } } else { if (bNotPushFlag_) { iOrigDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; iDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; } if (iOrigDataNO_ * dataSourceConfig_.iSkipInterval > moveData_.iFrameId) { LogDebug << "dealFrameid:" << iOrigDataNO_ * dataSourceConfig_.iSkipInterval << " moveFrameid:" << moveData_.iFrameId; iOrigDataNO_ = moveData_.iFrameId / dataSourceConfig_.iSkipInterval; MakeProcessData(); } else { while (!isStop_ && iOrigDataNO_ * dataSourceConfig_.iSkipInterval <= moveData_.iFrameId) { //继续处理 MakeProcessData(); } } InitParam(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.h b/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.h index f192bea..e46f98d 100644 --- a/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.h +++ b/nvidia_ascend_engine/common_engine/DataDealEngine/DataDealEngine.h @@ -50,6 +50,7 @@ private: std::map> mapSourcePushPort_; MoveData moveData_; + std::queue queuwMoveData_; std::string strDataDir_; uint32_t iOrigDataNO_; //原过车数据个数 diff --git a/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.cpp b/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.cpp index 34f313e..dc11273 100644 --- a/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.cpp @@ -1 +1 @@ -#include "CameraEngine.h" #include "myutils.h" using namespace ai_matrix; namespace { const int LOW_THRESHOLD = 128; const int MAX_THRESHOLD = 4096; const uint16_t DELAY_TIME = 10000; } CameraEngine::CameraEngine() {} CameraEngine::~CameraEngine() {} APP_ERROR CameraEngine::Init() { bUseEngine_ = true; bHwDecode_ = MyYaml::GetIns()->GetBoolValue("gc_hardware_decode"); dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); //获取摄像机参数 if (MyYaml::GetIns()->GetStringValue("gc_data_source") != "camera" || !dataSourceConfig_.bUse) { bUseEngine_ = false; LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; nDelayTime = MyYaml::GetIns()->GetIntValue("gc_load_delay"); LogInfo << "engineId_:" << engineId_ << " CameraEngine Init ok"; return APP_ERR_OK; } APP_ERROR CameraEngine::DeInit() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } ResetCamera(); LogInfo << "engineId_:" << engineId_ << " CameraEngine DeInit ok"; return APP_ERR_OK; } void CameraEngine::ResetCamera() { if (pFormatCtx_ != nullptr) { // clear th cache of the queue avformat_close_input(&pFormatCtx_); pFormatCtx_ = nullptr; } } APP_ERROR CameraEngine::ConnectCamera() { pFormatCtx_ = CreateFormatContext(); // create context if (pFormatCtx_ == nullptr) { LogError << "engineId_:" << engineId_ << " pFormatCtx_ null!"; return APP_ERR_COMM_FAILURE; } //0-代表输入 av_dump_format(pFormatCtx_, 0, dataSourceConfig_.strUrl.c_str(), 0); // get stream infomation int iRet = APP_ERR_OK; iRet = GetStreamInfo(); if (iRet != APP_ERR_OK) { LogError << "engineId_:" << engineId_ << " Stream Info Check failed, iRet = " << iRet; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR CameraEngine::GetStreamInfo() { if (pFormatCtx_ != nullptr) { iVideoStream_ = -1; iAudioStream_ = -1; //frameInfo_.iFrameId = 0; //帧号从0开始 for (unsigned int i = 0; i < pFormatCtx_->nb_streams; i++) { AVStream *inStream = pFormatCtx_->streams[i]; if (inStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { iVideoStream_ = i; frameInfo_.iHeight = inStream->codecpar->height; frameInfo_.iWidth = inStream->codecpar->width; //获取帧率,帧率的打印都在流中的两个成员.且应取平均帧率为先,为{x,0}或者{0,1}则取实时帧率 if (inStream->avg_frame_rate.den == 0 || (inStream->avg_frame_rate.num == 0 && inStream->avg_frame_rate.den == 1)) { frameInfo_.iRate = inStream->r_frame_rate.num / inStream->r_frame_rate.den; } else { frameInfo_.iRate = inStream->avg_frame_rate.num / inStream->avg_frame_rate.den; } LogDebug << "engineId_:" << engineId_ << " width:" << frameInfo_.iWidth << " height:" << frameInfo_.iHeight << " rate:" << frameInfo_.iRate << " iVideoStream_:" << iVideoStream_; } else if (inStream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { iAudioStream_ = i; LogDebug << "engineId_:" << engineId_ << " iAudioStream_:" << iAudioStream_; } } if (iVideoStream_ == -1) { LogError << "engineId_:" << engineId_ << " Didn't find a video stream!"; return APP_ERR_COMM_FAILURE; } if (frameInfo_.iHeight < LOW_THRESHOLD || frameInfo_.iWidth < LOW_THRESHOLD || frameInfo_.iHeight > MAX_THRESHOLD || frameInfo_.iWidth > MAX_THRESHOLD) { LogError << "engineId_:" << engineId_ << " Size of frame is not supported in DVPP Video Decode!"; return APP_ERR_COMM_FAILURE; } AVCodecID codecId = pFormatCtx_->streams[iVideoStream_]->codecpar->codec_id; if (codecId == AV_CODEC_ID_H264) { int profile = pFormatCtx_->streams[iVideoStream_]->codecpar->profile; if (profile == FF_PROFILE_H264_BASELINE) { frameInfo_.format = H264_BASELINE_LEVEL; } else if (profile == FF_PROFILE_H264_MAIN) { frameInfo_.format = H264_MAIN_LEVEL; } else if (profile == FF_PROFILE_H264_HIGH) { frameInfo_.format = H264_HIGH_LEVEL; } else { LogError << "engineId_:" << engineId_ << " not support h264 profile"; return APP_ERR_COMM_FAILURE; } } else if (codecId == AV_CODEC_ID_H265) { int profile = pFormatCtx_->streams[iVideoStream_]->codecpar->profile; if (profile == FF_PROFILE_HEVC_MAIN) { frameInfo_.format = H265_MAIN_LEVEL; } else { LogError << "engineId_:" << engineId_ << " not support h265 profile"; return APP_ERR_COMM_FAILURE; } } else { LogError << "engineId_:" << engineId_ << " Error unsupported format" << codecId; return APP_ERR_COMM_FAILURE; } } return APP_ERR_OK; } AVFormatContext *CameraEngine::CreateFormatContext() { // create message for stream pull AVFormatContext *pFormatContext = nullptr; AVDictionary *pOptions = nullptr; // formatContext = avformat_alloc_context(); if (dataSourceConfig_.strUrl.find("rtsp:") != std::string::npos) // rtsp { av_dict_set(&pOptions, "rtsp_transport", "tcp", 0); // 指定其传输方式为TCP // av_dict_set(&pOptions, "stimeout", "3000000", 0); // 设置超时3秒 // av_dict_set(&pOptions, "rw_timeout", "3000", 0); //单位:ms av_dict_set(&pOptions, "timeout", "3000000", 0); //设置超时时间为3秒 } //av_register_all(); //注册所有支持的格式(这里一定注册这些,否则会因为协议解析问题报错!!!) //avcodec_register_all(); //注册编解码器 //avformat_network_init(); //注册网格格式,如果为本地文件则可以去掉该代码 int iRet = avformat_open_input(&pFormatContext, dataSourceConfig_.strUrl.c_str(), nullptr, &pOptions); if (nullptr != pOptions) { av_dict_free(&pOptions); } if (iRet != 0) { LogError << "engineId_:" << engineId_ << " Couldn't open input stream " << dataSourceConfig_.strUrl.c_str() << ", iRet=" << iRet; return nullptr; } // pFormatContext->flags |= AVFMT_FLAG_NONBLOCK; // pFormatContext->pb->flags |= AVIO_FLAG_NONBLOCK; // av_dict_set(&pFormatContext->interrupt_callback.callback, "timeout", "3000", 0); // iRet = avio_open2(&pFormatContext->pb, dataSourceConfig_.strUrl.c_str(), AVIO_FLAG_READ, NULL, NULL) < 0; // { // // 处理错误 // LogError << "engineId_:" << engineId_ << "avio_open2 iRet=" << iRet; // return nullptr; // } iRet = avformat_find_stream_info(pFormatContext, nullptr); if (iRet != 0) { LogError << "engineId_:" << engineId_ << " Couldn't find stream information, iRet = " << iRet; return nullptr; } return pFormatContext; } //av_read_frame的中断回调函数 // int CameraEngine::InterruptCallback(void *pData) // { // TimeoutContext* pTimeOutCtx = (TimeoutContext*)pData; // LogDebug << "InterruptCallback i64Timeout:" << pTimeOutCtx->i64Timeout; // return std::chrono::duration_cast( // std::chrono::system_clock::now().time_since_epoch()) // .count() >= pTimeOutCtx->i64Timeout // ? AVERROR_EXIT // : 0; // } APP_ERROR CameraEngine::Process() { int iRet = APP_ERR_OK; if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } if (bHwDecode_) { iRet = ConnectCamera(); if (iRet == APP_ERR_OK) { LogInfo << "engineId_:" << engineId_ << " Start the stream......"; bReconnectFlag_ = false; } else { ResetCamera(); bReconnectFlag_ = true; } // Pull data cyclically AVPacket pkt; while (!isStop_) { //重连相机 if (bReconnectFlag_) { iRet = ConnectCamera(); if (iRet == APP_ERR_OK) { LogInfo << "engineId_:" << engineId_ << " Start the stream......"; bReconnectFlag_ = false; } else { outputQueMap_[strPort1_]->push(std::static_pointer_cast(std::make_shared("摄像头连接失败!"))); ResetCamera(); std::this_thread::sleep_for(std::chrono::seconds(3)); //3秒后重连 continue; } } //设置av_read_frame中断函数 (中断函数中超过1s,则中断处理) // TimeoutContext timeoutCtx = { std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() + 1000 }; // pFormatCtx_->interrupt_callback.callback = &CameraEngine::InterruptCallback; // pFormatCtx_->interrupt_callback.opaque = &timeoutCtx; av_init_packet(&pkt); //init pkt iRet = av_read_frame(pFormatCtx_, &pkt); //需要一直读取,否则获取到的是历史数据 if (iRet != 0) { outputQueMap_[strPort1_]->push(std::static_pointer_cast(std::make_shared("图像读取失败!"))); LogError << "engineId_:" << engineId_ << " Read frame failed, reconnect iRet:" << iRet; av_packet_unref(&pkt); //重连相机 ResetCamera(); bReconnectFlag_ = true; continue; } else if (pkt.stream_index == iVideoStream_) //只解码视频流 { // LogDebug << "iRet:" << iRet << " pkt.size:" << pkt.size; if (pkt.size <= 0) { LogError << "engineId_:" << engineId_ << " Invalid pkt.size: " << pkt.size; av_packet_unref(&pkt); continue; } if (dataSourceConfig_.strUrl.find(".mp4") != std::string::npos) { const char szStartCode[4] = {0, 0, 0, 1}; if (bIsAvc_ || memcmp(szStartCode, pkt.data, 4) != 0) { // is avc1 code, have no start code of H264 int iLen = 0; uint8_t *p = pkt.data; bIsAvc_ = true; do { // add start_code for each NAL, one frame may have multi NALs. iLen = ntohl(*((long *)p)); memcpy(p, szStartCode, 4); p += 4; p += iLen; if (p >= pkt.data + pkt.size) { break; } } while (1); } } void* pH264Buffer = nullptr; pH264Buffer = new uint8_t[pkt.size]; memcpy(pH264Buffer, pkt.data, pkt.size); //组织数据 std::shared_ptr pProcessData = std::make_shared(); pProcessData->iWidth = frameInfo_.iWidth; pProcessData->iHeight = frameInfo_.iHeight; pProcessData->iRate = frameInfo_.iRate; pProcessData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis(); pProcessData->iDataSource = engineId_; pProcessData->iSize = pkt.size; pProcessData->pData.reset(pH264Buffer, [](void* data){if(data) {delete[] data; data = nullptr;}}); //智能指针管理内存 //push端口0,视频解码 iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "engineId_:" << engineId_ << "push the h264 frame data failed..."; } } else if (pkt.stream_index == iAudioStream_) { //音频流不处理。 } else { LogError << "engineId_:" << engineId_ << " stream err stream_index:" << pkt.stream_index; } av_packet_unref(&pkt); //unref if (dataSourceConfig_.strUrl.find("rtsp:") == std::string::npos) // 如果不是rtsp,定时发送 { usleep(DELAY_TIME); // delay 40ms } } } else { //从摄像头RTSP拉流 const std::string videoStreamAddress = std::string("rtspsrc location=") + dataSourceConfig_.strUrl.c_str() + " latency=10 ! \ rtph264depay ! h264parse ! nvv4l2decoder enable-max-performance=1 enable-frame-type-reporting=1 ! nvvidconv ! video/x-raw, format=(string)BGRx ! videoconvert ! appsink"; VideoCapture capture_video; while(!capture_video.open(videoStreamAddress)){ //, cv::CAP_FFMPEG LogInfo<<"Restart Opening video stream or file ..."< pBGRFrameData = std::make_shared(); std::shared_ptr pProcessData = std::make_shared(); if(!capture_video.read(frame)) { capture_video.release(); while(!capture_video.open(videoStreamAddress)){ //, cv::CAP_FFMPEG LogInfo<<"Restart Opening video stream or file ..."<iDataSource = engineId_; pBGRFrameData->iFrameId = nFrameid++; pBGRFrameData->iSize = resizepBGRBuffer_Size; pBGRFrameData->frameInfo.iWidth = IMAGE_WIDTH; pBGRFrameData->frameInfo.iHeight = IMAGE_HEIGHT; pBGRFrameData->frameInfo.iRate = frameRate; pProcessData->pVoidData = std::static_pointer_cast(pBGRFrameData); pProcessData->pData.reset(resizeBGRBufferobj, [](void* data){if(data) {delete[] data; data = nullptr;}}); if (nFrameid >= 0xFFFFFFFF) {nFrameid = 0;} pBGRFrameData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis(); pProcessData->iWidth = pBGRFrameData->frameInfo.iWidth; pProcessData->iHeight = pBGRFrameData->frameInfo.iHeight; pProcessData->iHeight = pBGRFrameData->frameInfo.iRate; iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); } } return APP_ERR_OK; } \ No newline at end of file +#include "CameraEngine.h" #include "myutils.h" using namespace ai_matrix; namespace { const int LOW_THRESHOLD = 128; const int MAX_THRESHOLD = 4096; const uint16_t DELAY_TIME = 20000; } CameraEngine::CameraEngine() {} CameraEngine::~CameraEngine() {} APP_ERROR CameraEngine::Init() { bUseEngine_ = true; bHwDecode_ = MyYaml::GetIns()->GetBoolValue("gc_hardware_decode"); dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); //获取摄像机参数 if (MyYaml::GetIns()->GetStringValue("gc_data_source") != "camera" || !dataSourceConfig_.bUse) { bUseEngine_ = false; LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; nDelayTime = MyYaml::GetIns()->GetIntValue("gc_load_delay"); LogInfo << "engineId_:" << engineId_ << " CameraEngine Init ok"; return APP_ERR_OK; } APP_ERROR CameraEngine::DeInit() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } ResetCamera(); LogInfo << "engineId_:" << engineId_ << " CameraEngine DeInit ok"; return APP_ERR_OK; } void CameraEngine::ResetCamera() { if (pFormatCtx_ != nullptr) { // clear th cache of the queue avformat_close_input(&pFormatCtx_); pFormatCtx_ = nullptr; } } APP_ERROR CameraEngine::ConnectCamera() { pFormatCtx_ = CreateFormatContext(); // create context if (pFormatCtx_ == nullptr) { LogError << "engineId_:" << engineId_ << " pFormatCtx_ null!"; return APP_ERR_COMM_FAILURE; } //0-代表输入 av_dump_format(pFormatCtx_, 0, dataSourceConfig_.strUrl.c_str(), 0); // get stream infomation int iRet = APP_ERR_OK; iRet = GetStreamInfo(); if (iRet != APP_ERR_OK) { LogError << "engineId_:" << engineId_ << " Stream Info Check failed, iRet = " << iRet; return APP_ERR_COMM_FAILURE; } return APP_ERR_OK; } APP_ERROR CameraEngine::GetStreamInfo() { if (pFormatCtx_ != nullptr) { iVideoStream_ = -1; iAudioStream_ = -1; //frameInfo_.iFrameId = 0; //帧号从0开始 for (unsigned int i = 0; i < pFormatCtx_->nb_streams; i++) { AVStream *inStream = pFormatCtx_->streams[i]; if (inStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { iVideoStream_ = i; frameInfo_.iHeight = inStream->codecpar->height; frameInfo_.iWidth = inStream->codecpar->width; //获取帧率,帧率的打印都在流中的两个成员.且应取平均帧率为先,为{x,0}或者{0,1}则取实时帧率 if (inStream->avg_frame_rate.den == 0 || (inStream->avg_frame_rate.num == 0 && inStream->avg_frame_rate.den == 1)) { frameInfo_.iRate = inStream->r_frame_rate.num / inStream->r_frame_rate.den; } else { frameInfo_.iRate = inStream->avg_frame_rate.num / inStream->avg_frame_rate.den; } LogDebug << "engineId_:" << engineId_ << " width:" << frameInfo_.iWidth << " height:" << frameInfo_.iHeight << " rate:" << frameInfo_.iRate << " iVideoStream_:" << iVideoStream_; } else if (inStream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { iAudioStream_ = i; LogDebug << "engineId_:" << engineId_ << " iAudioStream_:" << iAudioStream_; } } if (iVideoStream_ == -1) { LogError << "engineId_:" << engineId_ << " Didn't find a video stream!"; return APP_ERR_COMM_FAILURE; } if (frameInfo_.iHeight < LOW_THRESHOLD || frameInfo_.iWidth < LOW_THRESHOLD || frameInfo_.iHeight > MAX_THRESHOLD || frameInfo_.iWidth > MAX_THRESHOLD) { LogError << "engineId_:" << engineId_ << " Size of frame is not supported in DVPP Video Decode!"; return APP_ERR_COMM_FAILURE; } AVCodecID codecId = pFormatCtx_->streams[iVideoStream_]->codecpar->codec_id; if (codecId == AV_CODEC_ID_H264) { int profile = pFormatCtx_->streams[iVideoStream_]->codecpar->profile; if (profile == FF_PROFILE_H264_BASELINE) { frameInfo_.format = H264_BASELINE_LEVEL; } else if (profile == FF_PROFILE_H264_MAIN) { frameInfo_.format = H264_MAIN_LEVEL; } else if (profile == FF_PROFILE_H264_HIGH) { frameInfo_.format = H264_HIGH_LEVEL; } else { LogError << "engineId_:" << engineId_ << " not support h264 profile"; return APP_ERR_COMM_FAILURE; } } else if (codecId == AV_CODEC_ID_H265) { int profile = pFormatCtx_->streams[iVideoStream_]->codecpar->profile; if (profile == FF_PROFILE_HEVC_MAIN) { frameInfo_.format = H265_MAIN_LEVEL; } else { LogError << "engineId_:" << engineId_ << " not support h265 profile"; return APP_ERR_COMM_FAILURE; } } else { LogError << "engineId_:" << engineId_ << " Error unsupported format" << codecId; return APP_ERR_COMM_FAILURE; } } return APP_ERR_OK; } AVFormatContext *CameraEngine::CreateFormatContext() { // create message for stream pull AVFormatContext *pFormatContext = nullptr; AVDictionary *pOptions = nullptr; // formatContext = avformat_alloc_context(); if (dataSourceConfig_.strUrl.find("rtsp:") != std::string::npos) // rtsp { av_dict_set(&pOptions, "rtsp_transport", "tcp", 0); // 指定其传输方式为TCP // av_dict_set(&pOptions, "stimeout", "3000000", 0); // 设置超时3秒 // av_dict_set(&pOptions, "rw_timeout", "3000", 0); //单位:ms av_dict_set(&pOptions, "timeout", "3000000", 0); //设置超时时间为3秒 } //av_register_all(); //注册所有支持的格式(这里一定注册这些,否则会因为协议解析问题报错!!!) //avcodec_register_all(); //注册编解码器 //avformat_network_init(); //注册网格格式,如果为本地文件则可以去掉该代码 int iRet = avformat_open_input(&pFormatContext, dataSourceConfig_.strUrl.c_str(), nullptr, &pOptions); if (nullptr != pOptions) { av_dict_free(&pOptions); } if (iRet != 0) { LogError << "engineId_:" << engineId_ << " Couldn't open input stream " << dataSourceConfig_.strUrl.c_str() << ", iRet=" << iRet; return nullptr; } // pFormatContext->flags |= AVFMT_FLAG_NONBLOCK; // pFormatContext->pb->flags |= AVIO_FLAG_NONBLOCK; // av_dict_set(&pFormatContext->interrupt_callback.callback, "timeout", "3000", 0); // iRet = avio_open2(&pFormatContext->pb, dataSourceConfig_.strUrl.c_str(), AVIO_FLAG_READ, NULL, NULL) < 0; // { // // 处理错误 // LogError << "engineId_:" << engineId_ << "avio_open2 iRet=" << iRet; // return nullptr; // } iRet = avformat_find_stream_info(pFormatContext, nullptr); if (iRet != 0) { LogError << "engineId_:" << engineId_ << " Couldn't find stream information, iRet = " << iRet; return nullptr; } return pFormatContext; } //av_read_frame的中断回调函数 // int CameraEngine::InterruptCallback(void *pData) // { // TimeoutContext* pTimeOutCtx = (TimeoutContext*)pData; // LogDebug << "InterruptCallback i64Timeout:" << pTimeOutCtx->i64Timeout; // return std::chrono::duration_cast( // std::chrono::system_clock::now().time_since_epoch()) // .count() >= pTimeOutCtx->i64Timeout // ? AVERROR_EXIT // : 0; // } APP_ERROR CameraEngine::Process() { int iRet = APP_ERR_OK; if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } if (bHwDecode_) { iRet = ConnectCamera(); if (iRet == APP_ERR_OK) { LogInfo << "engineId_:" << engineId_ << " Start the stream......"; bReconnectFlag_ = false; } else { ResetCamera(); bReconnectFlag_ = true; } // Pull data cyclically AVPacket pkt; while (!isStop_) { //重连相机 if (bReconnectFlag_) { iRet = ConnectCamera(); if (iRet == APP_ERR_OK) { LogInfo << "engineId_:" << engineId_ << " Start the stream......"; bReconnectFlag_ = false; this->bCameraError_ = false; } else { if (!this->bCameraError_) { outputQueMap_[strPort1_]->push( std::static_pointer_cast( std::make_shared("摄像头连接失败!"))); this->bCameraError_ = true; } ResetCamera(); std::this_thread::sleep_for(std::chrono::seconds(3)); //3秒后重连 continue; } } //设置av_read_frame中断函数 (中断函数中超过1s,则中断处理) // TimeoutContext timeoutCtx = { std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() + 1000 }; // pFormatCtx_->interrupt_callback.callback = &CameraEngine::InterruptCallback; // pFormatCtx_->interrupt_callback.opaque = &timeoutCtx; av_init_packet(&pkt); //init pkt iRet = av_read_frame(pFormatCtx_, &pkt); //需要一直读取,否则获取到的是历史数据 if (iRet != 0) { outputQueMap_[strPort1_]->push(std::static_pointer_cast(std::make_shared("图像读取失败!"))); LogError << "engineId_:" << engineId_ << " Read frame failed, reconnect iRet:" << iRet; av_packet_unref(&pkt); //重连相机 ResetCamera(); bReconnectFlag_ = true; continue; } else if (pkt.stream_index == iVideoStream_) //只解码视频流 { // LogDebug << "iRet:" << iRet << " pkt.size:" << pkt.size; if (pkt.size <= 0) { LogError << "engineId_:" << engineId_ << " Invalid pkt.size: " << pkt.size; av_packet_unref(&pkt); continue; } if (dataSourceConfig_.strUrl.find(".mp4") != std::string::npos) { const char szStartCode[4] = {0, 0, 0, 1}; if (bIsAvc_ || memcmp(szStartCode, pkt.data, 4) != 0) { // is avc1 code, have no start code of H264 int iLen = 0; uint8_t *p = pkt.data; bIsAvc_ = true; do { // add start_code for each NAL, one frame may have multi NALs. iLen = ntohl(*((long *)p)); memcpy(p, szStartCode, 4); p += 4; p += iLen; if (p >= pkt.data + pkt.size) { break; } } while (1); } } void* pH264Buffer = nullptr; pH264Buffer = new uint8_t[pkt.size]; memcpy(pH264Buffer, pkt.data, pkt.size); //组织数据 std::shared_ptr pProcessData = std::make_shared(); pProcessData->iWidth = frameInfo_.iWidth; pProcessData->iHeight = frameInfo_.iHeight; pProcessData->iRate = frameInfo_.iRate; pProcessData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis(); pProcessData->iDataSource = engineId_; pProcessData->iSize = pkt.size; pProcessData->pData.reset(pH264Buffer, [](void* data){if(data) {delete[] data; data = nullptr;}}); //智能指针管理内存 //push端口0,视频解码 iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); if (iRet != APP_ERR_OK) { LogError << "engineId_:" << engineId_ << "push the h264 frame data failed..."; } } else if (pkt.stream_index == iAudioStream_) { //音频流不处理。 } else { LogError << "engineId_:" << engineId_ << " stream err stream_index:" << pkt.stream_index; } av_packet_unref(&pkt); //unref if (dataSourceConfig_.strUrl.find("rtsp:") == std::string::npos) // 如果不是rtsp,定时发送 { usleep(DELAY_TIME); // delay 40ms } } } else { //从摄像头RTSP拉流 const std::string videoStreamAddress = std::string("rtspsrc location=") + dataSourceConfig_.strUrl.c_str() + " latency=10 ! \ rtph264depay ! h264parse ! nvv4l2decoder enable-max-performance=1 enable-frame-type-reporting=1 ! nvvidconv ! video/x-raw, format=(string)BGRx ! videoconvert ! appsink"; VideoCapture capture_video; while(!capture_video.open(videoStreamAddress)){ //, cv::CAP_FFMPEG LogInfo<<"Restart Opening video stream or file ..."< pBGRFrameData = std::make_shared(); std::shared_ptr pProcessData = std::make_shared(); if(!capture_video.read(frame)) { capture_video.release(); while(!capture_video.open(videoStreamAddress)){ //, cv::CAP_FFMPEG LogInfo<<"Restart Opening video stream or file ..."<iDataSource = engineId_; pBGRFrameData->iFrameId = nFrameid++; pBGRFrameData->iSize = resizepBGRBuffer_Size; pBGRFrameData->frameInfo.iWidth = IMAGE_WIDTH; pBGRFrameData->frameInfo.iHeight = IMAGE_HEIGHT; pBGRFrameData->frameInfo.iRate = frameRate; pProcessData->pVoidData = std::static_pointer_cast(pBGRFrameData); pProcessData->pData.reset(resizeBGRBufferobj, [](void* data){if(data) {delete[] data; data = nullptr;}}); if (nFrameid >= 0xFFFFFFFF) {nFrameid = 0;} pBGRFrameData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis(); pProcessData->iWidth = pBGRFrameData->frameInfo.iWidth; pProcessData->iHeight = pBGRFrameData->frameInfo.iHeight; pProcessData->iHeight = pBGRFrameData->frameInfo.iRate; iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.h b/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.h index e37270c..d3a880f 100644 --- a/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.h +++ b/nvidia_ascend_engine/common_engine/DataSourceEngine/CameraEngine.h @@ -9,7 +9,7 @@ #include "AppCommon.h" - //编译器这部分代码按C语言(而不是C++)的方式进行编译 +//编译器这部分代码按C语言(而不是C++)的方式进行编译 #ifdef __cplusplus extern "C" { @@ -65,6 +65,8 @@ private: int nDelayTime; bool bIsAvc_ = false; int iAudioStream_ = -1; + + bool bCameraError_ = false; }; ENGINE_REGIST(CameraEngine) diff --git a/nvidia_ascend_engine/common_engine/DataSourceEngine/ReadImgEngine.cpp b/nvidia_ascend_engine/common_engine/DataSourceEngine/ReadImgEngine.cpp index 5f39bbd..65f9e3f 100644 --- a/nvidia_ascend_engine/common_engine/DataSourceEngine/ReadImgEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DataSourceEngine/ReadImgEngine.cpp @@ -105,7 +105,7 @@ APP_ERROR ReadImgEngine::Process() { std::string strFilePath = vecFiles_.at(iFileIndex); cv::Mat matBGR = cv::imread(strFilePath); - + //组织数据 std::shared_ptr pProcessData = std::make_shared(); pProcessData->iWidth = matBGR.cols; diff --git a/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp b/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp index 79ed3bc..698ae91 100644 --- a/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp @@ -1,269 +1 @@ -/* - * @Author: your name - * @Date: 2023-07-20 17:15:33 - * @LastEditors: your name - * @LastEditTime: 2023-07-23 20:09:39 - * @Description: file content - * @FilePath: /shigetai_lirs/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp - * - * Copyright © 2022 - */ -#include "DeviceStatusUpSerEngine.h" -#include "myutils.h" - - -DeviceStatusUpSerEngine::DeviceStatusUpSerEngine() {} -DeviceStatusUpSerEngine::~DeviceStatusUpSerEngine() {} - -APP_ERROR DeviceStatusUpSerEngine::Init() -{ - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - strGetTokenURL_ = MyYaml::GetIns()->GetStringValue("gc_gettoken_url"); - strURL_ = MyYaml::GetIns()->GetStringValue("gc_device_status_url"); - strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); - LogInfo << "DeviceStatusUpSerEngine Init ok"; - return APP_ERR_OK; -} - -APP_ERROR DeviceStatusUpSerEngine::DeInit() -{ - LogDebug << "curl_easy_cleanup"; - curl_easy_cleanup(pCurl_); - - /* 这个处理移动到main中, 防止多线程调用 - LogDebug << "内存清理"; - curl_global_cleanup(); - */ - LogInfo << "DeviceStatusUpSerEngine DeInit ok"; - return APP_ERR_OK; -} - -/** -* libcurl回调函数 -* inParam : void *pBuffer 回调内容地址 - : size_t size 回调单个数据大小 - : size_t nmemb 回调数据个数 -* outParam: std::string &strResp 返回内容 -* return : 回调数据大小 -*/ -size_t DeviceStatusUpSerEngine::WriteCallBack(void *pBuffer, size_t size, size_t nmemb, std::string &strResp) -{ - size_t sizes = size * nmemb; - std::string strTemp((char*)pBuffer, sizes); - strResp += strTemp; - return sizes; -} - -/** -* 调用http接口获取token -* inParam : -* outParam: std::string &strBladeAuth 返回的token信息 -* return : true:成功; false:失败 -*/ -bool DeviceStatusUpSerEngine::GetToken(std::string &strBladeAuth) -{ - //1. 获得curl操作符 - if (nullptr == pCurl_) - { - LogDebug<<"pCurl_ is null, invoke curl_easy_init"; - pCurl_ = curl_easy_init(); - if (nullptr == pCurl_) - { - LogError << "curl_easy_init failed !"; - return false; - } - } - - //2. 设置head, 和表单 - //设置head信息 - struct curl_slist *pHeaderList = nullptr; - pHeaderList = curl_slist_append(pHeaderList, "Authorization:Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0"); - - //设置表单信息 - curl_mime *pMultipart = curl_mime_init(pCurl_); - curl_mimepart *pPart = curl_mime_addpart(pMultipart); - curl_mime_name(pPart, "username"); - curl_mime_data(pPart, "guest_01", CURL_ZERO_TERMINATED); - pPart = curl_mime_addpart(pMultipart); - curl_mime_name(pPart, "password"); - curl_mime_data(pPart, "d55b0f642e817eea24725d2f2a31dd08", CURL_ZERO_TERMINATED); - pPart = curl_mime_addpart(pMultipart); - curl_mime_name(pPart, "tenantId"); - curl_mime_data(pPart, "000000", CURL_ZERO_TERMINATED); - pPart = curl_mime_addpart(pMultipart); - curl_mime_name(pPart, "grant_type"); - curl_mime_data(pPart, "password", CURL_ZERO_TERMINATED); - - curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) - curl_easy_setopt(pCurl_, CURLOPT_URL, strGetTokenURL_.c_str()); //设置url - curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 - curl_easy_setopt(pCurl_, CURLOPT_MIMEPOST, pMultipart); //设置表单 - //curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strBody.c_str()); //设置post内容 - //curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) - curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 - std::string strResponse; - curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 - - //3. 执行http请求 - CURLcode res = curl_easy_perform(pCurl_); - curl_slist_free_all(pHeaderList); //清除headerlist - curl_mime_free(pMultipart); //清除curl_mime - curl_easy_reset(pCurl_); //重置curl - if (res != CURLE_OK) - { - LogError << " curl_easy_perform fail:" << curl_easy_strerror(res); - return false; - } - - //4. 执行成功解析响应内容 - Json::CharReaderBuilder readerBuilder; - std::shared_ptr reader(readerBuilder.newCharReader()); - Json::Value jvResponse; - JSONCPP_STRING errs; - if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) - { - LogError << " response content fail " << strResponse; - return false; - } - LogDebug << "GetToken resp:" << strResponse; - - strBladeAuth += jvResponse["token_type"].asString(); - strBladeAuth += " "; - strBladeAuth += jvResponse["access_token"].asString(); - return true; -} - -/** -* 列车信息提交http接口 -* inParam : Json::Value &jvRequest 提交内容 -* outParam: -* return : true:提交成功; false:提交失败 -*/ -bool DeviceStatusUpSerEngine::ResultToHttpSrv(Json::Value &jvRequest) -{ - //获取token - std::string strBladeAuth("blade-auth:"); - if (!GetToken(strBladeAuth)) - { - LogError << " GetToken fail "; - return false; - } - LogDebug << "strBladeAuth:" << strBladeAuth; - - //1. 获得curl操作符 - if (nullptr == pCurl_) - { - LogDebug<<"pCurl_ is null, invoke curl_easy_init"; - pCurl_ = curl_easy_init(); - if (nullptr == pCurl_) - { - LogError << "curl_easy_init failed !"; - return false; - } - } - - //2. 设置http请求信息 - Json::StreamWriterBuilder jswBuilder; - std::string strRequest = Json::writeString(jswBuilder, jvRequest); - LogDebug << "to http:" << strRequest; - std::string strResponse; - struct curl_slist *pHeaderList = nullptr; - pHeaderList = curl_slist_append(pHeaderList, "Accept:application/json"); - pHeaderList = curl_slist_append(pHeaderList, "Content-Type:application/json"); - pHeaderList = curl_slist_append(pHeaderList, "charset:utf-8"); - pHeaderList = curl_slist_append(pHeaderList, strBladeAuth.c_str()); - curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) - curl_easy_setopt(pCurl_, CURLOPT_URL, strURL_.c_str()); //设置url - curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 - curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strRequest.c_str()); //设置post内容 - curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) - curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 - curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 - - //3. 执行http请求 - CURLcode res = curl_easy_perform(pCurl_); - curl_slist_free_all(pHeaderList); //清除headerlist - curl_easy_reset(pCurl_); //重置curl - if (res != CURLE_OK) - { - LogError << jvRequest.toStyledString() - << " curl_easy_perform fail:" << curl_easy_strerror(res); - return false; - } - - //4. 执行成功解析响应内容 - LogDebug << "设备异常上传结果:" << strResponse; - Json::CharReaderBuilder readerBuilder; - std::shared_ptr reader(readerBuilder.newCharReader()); - Json::Value jvResponse; - JSONCPP_STRING errs; - if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) - { - LogError << jvRequest.toStyledString() - << " response content fail " << strResponse; - return false; - } - - if (!jvResponse["success"].asBool()) - { - LogError << jvRequest.toStyledString() - << " response fail:" << strResponse; - return false; - } - - LogInfo << jvRequest.toStyledString() - << " post success"; - return true; -} - - -APP_ERROR DeviceStatusUpSerEngine::Process() -{ - int iRet = APP_ERR_OK; - if (0 == MyYaml::GetIns()->GetIntValue("gc_device_status_open")) - { - LogDebug << " gc_device_status_open value is 0"; - return APP_ERR_OK; - } - - while (!isStop_) - { - std::shared_ptr pVoidData0 = nullptr; - inputQueMap_[strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); //1ms - - //无数据大于1分钟 - iNoDataCnt_++; - if (iNoDataCnt_ > (60 * 1000)) - { - iNoDataCnt_ = 0; - } - continue; - } - iNoDataCnt_ = 0; - - std::shared_ptr pWarn = std::static_pointer_cast(pVoidData0); - - ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(0); //获取摄像机参数 - - //组装post信息 - Json::Value jvRequest; - jvRequest["tainsModule"] = "2"; // 传输模块:0=装车模块,1=超偏载模块,2=车号识别模块,3=web 模块 - jvRequest["networkStatus"] = "异常"; //网络状态: 正常/异常 - jvRequest["devName"] = "摄像头";// 设备名称 - jvRequest["devSn"] = strPoundNo_+"股道";// 设备编码 - jvRequest["cpuData"] = "";// CPU 情况 - jvRequest["memoryUsage"] = "";// 内存使用情况 - jvRequest["devRunningStatus"] = "异常";// 设备运行状态:正常/异常 - jvRequest["devCheckResult"] = *pWarn;// 检测结果 - jvRequest["devIp"] = dataSourceConfig.strUrl;// 设备 IP - jvRequest["devAccount"] = "";// 设备账号 - if (!ResultToHttpSrv(jvRequest)) - { - LogError << "摄像头异常状态上传服务器失败!"; - } - } - return APP_ERR_OK; -} +/* * @Author: your name * @Date: 2023-07-20 17:15:33 * @LastEditors: your name * @LastEditTime: 2023-07-23 20:09:39 * @Description: file content * @FilePath: /shigetai_lirs/nvidia_ascend_engine/common_engine/DataUploadEngine/DeviceStatusUpSerEngine.cpp * * Copyright © 2022 */ #include "DeviceStatusUpSerEngine.h" #include "myutils.h" DeviceStatusUpSerEngine::DeviceStatusUpSerEngine() {} DeviceStatusUpSerEngine::~DeviceStatusUpSerEngine() {} APP_ERROR DeviceStatusUpSerEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strGetTokenURL_ = MyYaml::GetIns()->GetStringValue("gc_gettoken_url"); strURL_ = MyYaml::GetIns()->GetStringValue("gc_device_status_url"); strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); LogInfo << "DeviceStatusUpSerEngine Init ok"; return APP_ERR_OK; } APP_ERROR DeviceStatusUpSerEngine::DeInit() { LogDebug << "curl_easy_cleanup"; curl_easy_cleanup(pCurl_); /* 这个处理移动到main中, 防止多线程调用 LogDebug << "内存清理"; curl_global_cleanup(); */ LogInfo << "DeviceStatusUpSerEngine DeInit ok"; return APP_ERR_OK; } /** * libcurl回调函数 * inParam : void *pBuffer 回调内容地址 : size_t size 回调单个数据大小 : size_t nmemb 回调数据个数 * outParam: std::string &strResp 返回内容 * return : 回调数据大小 */ size_t DeviceStatusUpSerEngine::WriteCallBack(void *pBuffer, size_t size, size_t nmemb, std::string &strResp) { size_t sizes = size * nmemb; std::string strTemp((char*)pBuffer, sizes); strResp += strTemp; return sizes; } /** * 调用http接口获取token * inParam : * outParam: std::string &strBladeAuth 返回的token信息 * return : true:成功; false:失败 */ bool DeviceStatusUpSerEngine::GetToken(std::string &strBladeAuth) { //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置head, 和表单 //设置head信息 struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Authorization:Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0"); //设置表单信息 curl_mime *pMultipart = curl_mime_init(pCurl_); curl_mimepart *pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "username"); curl_mime_data(pPart, "guest_01", CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "password"); curl_mime_data(pPart, "d55b0f642e817eea24725d2f2a31dd08", CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "tenantId"); curl_mime_data(pPart, "000000", CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "grant_type"); curl_mime_data(pPart, "password", CURL_ZERO_TERMINATED); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_URL, strGetTokenURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_MIMEPOST, pMultipart); //设置表单 //curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strBody.c_str()); //设置post内容 //curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 std::string strResponse; curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_mime_free(pMultipart); //清除curl_mime curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << " curl_easy_perform fail:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << " response content fail " << strResponse; return false; } LogDebug << "GetToken resp:" << strResponse; strBladeAuth += jvResponse["token_type"].asString(); strBladeAuth += " "; strBladeAuth += jvResponse["access_token"].asString(); return true; } /** * 列车信息提交http接口 * inParam : Json::Value &jvRequest 提交内容 * outParam: * return : true:提交成功; false:提交失败 */ bool DeviceStatusUpSerEngine::ResultToHttpSrv(Json::Value &jvRequest) { //获取token std::string strBladeAuth("blade-auth:"); if (!GetToken(strBladeAuth)) { LogError << " GetToken fail "; return false; } LogDebug << "strBladeAuth:" << strBladeAuth; //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置http请求信息 Json::StreamWriterBuilder jswBuilder; std::string strRequest = Json::writeString(jswBuilder, jvRequest); LogDebug << "to http:" << strRequest; std::string strResponse; struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Accept:application/json"); pHeaderList = curl_slist_append(pHeaderList, "Content-Type:application/json"); pHeaderList = curl_slist_append(pHeaderList, "charset:utf-8"); pHeaderList = curl_slist_append(pHeaderList, strBladeAuth.c_str()); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_URL, strURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strRequest.c_str()); //设置post内容 curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << jvRequest.toStyledString() << " curl_easy_perform fail:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 LogDebug << "设备异常上传结果:" << strResponse; Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << jvRequest.toStyledString() << " response content fail " << strResponse; return false; } if (!jvResponse["success"].asBool()) { LogError << jvRequest.toStyledString() << " response fail:" << strResponse; return false; } LogInfo << jvRequest.toStyledString() << " post success"; return true; } APP_ERROR DeviceStatusUpSerEngine::Process() { int iRet = APP_ERR_OK; if (0 == MyYaml::GetIns()->GetIntValue("gc_http_open")) { LogDebug << " gc_http_open value is 0"; return APP_ERR_OK; } while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms //无数据大于1分钟 iNoDataCnt_++; if (iNoDataCnt_ > (60 * 1000)) { iNoDataCnt_ = 0; } continue; } iNoDataCnt_ = 0; std::shared_ptr pWarn = std::static_pointer_cast(pVoidData0); ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(0); //获取摄像机参数 //组装post信息 Json::Value jvRequest; jvRequest["tainsModule"] = "2"; // 传输模块:0=装车模块,1=超偏载模块,2=车号识别模块,3=web 模块 jvRequest["networkStatus"] = "异常"; //网络状态: 正常/异常 jvRequest["devName"] = "摄像头";// 设备名称 jvRequest["devSn"] = strPoundNo_+"股道";// 设备编码 jvRequest["cpuData"] = "";// CPU 情况 jvRequest["memoryUsage"] = "";// 内存使用情况 jvRequest["devRunningStatus"] = "异常";// 设备运行状态:正常/异常 jvRequest["devCheckResult"] = *pWarn;// 检测结果 jvRequest["devIp"] = dataSourceConfig.strUrl;// 设备 IP jvRequest["devAccount"] = "";// 设备账号 if (!ResultToHttpSrv(jvRequest)) { LogError << "摄像头异常状态上传服务器失败!"; } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/DataUploadEngine/ResultToHttpSrvEngine.cpp b/nvidia_ascend_engine/common_engine/DataUploadEngine/ResultToHttpSrvEngine.cpp index 05b03cb..e1289fa 100644 --- a/nvidia_ascend_engine/common_engine/DataUploadEngine/ResultToHttpSrvEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DataUploadEngine/ResultToHttpSrvEngine.cpp @@ -1 +1 @@ -#include "ResultToHttpSrvEngine.h" #include "myutils.h" ResultToHttpSrvEngine::ResultToHttpSrvEngine() {} ResultToHttpSrvEngine::~ResultToHttpSrvEngine() {} APP_ERROR ResultToHttpSrvEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strUsername_ = MyYaml::GetIns()->GetStringValue("username"); strPassword_ = MyYaml::GetIns()->GetStringValue("password"); strURL_ = MyYaml::GetIns()->GetStringValue("gc_http_url"); strGetTokenURL_ = MyYaml::GetIns()->GetStringValue("gc_gettoken_url"); strImageSrv_ = MyYaml::GetIns()->GetPathValue("gc_image_srv"); strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); strFailSavePath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent.csv"; strFailSaveBakPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent_bak.csv"; LogInfo << "ResultToHttpSrvEngine Init ok"; return APP_ERR_OK; } APP_ERROR ResultToHttpSrvEngine::DeInit() { LogDebug << "curl_easy_cleanup"; curl_easy_cleanup(pCurl_); /* 这个处理移动到main中, 防止多线程调用 LogDebug << "内存清理"; curl_global_cleanup(); */ LogInfo << "ResultToHttpSrvEngine DeInit ok"; return APP_ERR_OK; } /** * libcurl回调函数 * inParam : void *pBuffer 回调内容地址 : size_t size 回调单个数据大小 : size_t nmemb 回调数据个数 * outParam: std::string &strResp 返回内容 * return : 回调数据大小 */ size_t ResultToHttpSrvEngine::WriteCallBack(void *pBuffer, size_t size, size_t nmemb, std::string &strResp) { size_t sizes = size * nmemb; std::string strTemp((char*)pBuffer, sizes); strResp += strTemp; return sizes; } /** * 调用http接口获取token * inParam : * outParam: std::string &strBladeAuth 返回的token信息 * return : true:成功; false:失败 */ bool ResultToHttpSrvEngine::GetToken(std::string &strBladeAuth) { //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置head, 和表单 //设置head信息 struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Authorization:Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0"); //设置表单信息 curl_mime *pMultipart = curl_mime_init(pCurl_); curl_mimepart *pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "username"); curl_mime_data(pPart, strUsername_.c_str(), CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "password"); curl_mime_data(pPart, strPassword_.c_str(), CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "tenantId"); curl_mime_data(pPart, "000000", CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "grant_type"); curl_mime_data(pPart, "password", CURL_ZERO_TERMINATED); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_URL, strGetTokenURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_MIMEPOST, pMultipart); //设置表单 //curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strBody.c_str()); //设置post内容 //curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 std::string strResponse; curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_mime_free(pMultipart); //清除curl_mime curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << " curl_easy_perform fail:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << " response content fail " << strResponse; return false; } LogDebug << "GetToken resp:" << strResponse; strBladeAuth += jvResponse["token_type"].asString(); strBladeAuth += " "; strBladeAuth += jvResponse["access_token"].asString(); return true; } /** * 列车信息提交http接口 * inParam : Json::Value &jvRequest 提交内容 * outParam: * return : true:提交成功; false:提交失败 */ bool ResultToHttpSrvEngine::ResultToHttpSrv(Json::Value &jvRequest) { //获取token std::string strBladeAuth("blade-auth:"); if (!GetToken(strBladeAuth)) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " GetToken fail "; return false; } LogDebug << "strBladeAuth:" << strBladeAuth; //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置http请求信息 Json::StreamWriterBuilder jswBuilder; std::string strRequest = Json::writeString(jswBuilder, jvRequest); LogDebug << "to http:" << strRequest; std::string strResponse; struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Accept:application/json"); pHeaderList = curl_slist_append(pHeaderList, "Content-Type:application/json"); pHeaderList = curl_slist_append(pHeaderList, "charset:utf-8"); pHeaderList = curl_slist_append(pHeaderList, strBladeAuth.c_str()); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_URL, strURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strRequest.c_str()); //设置post内容 curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " curl_easy_perform fail:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 LogInfo << "http resp:" << strResponse; Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " response content fail " << strResponse; return false; } if (!jvResponse["success"].asBool()) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " response fail"; return false; } LogInfo << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " post success"; return true; } /** * 处理上传失败的信息 * inParam : N/A * outParam: N/A * return : N/A */ void ResultToHttpSrvEngine::DealHttpFailInfo() { //队列有待处理数据,则先不处理异常数据。 if (inputQueMap_[strPort0_]->getSize() > 0) { LogDebug << "have new data to process"; return; } //文件不存在不处理 if (access(strFailSavePath_.c_str(), F_OK) == -1) { LogDebug << "no exit file:" << strFailSavePath_; return; } bool bAllSucc = true; std::ifstream inFile(strFailSavePath_.c_str(), std::ios::in); if (!inFile.is_open()) { LogError << strFailSavePath_ << " open fail"; return; } int iDealCnt = 0; std::string strLine; while (getline(inFile, strLine)) { Json::CharReaderBuilder jsrBuilder; std::shared_ptr reader(jsrBuilder.newCharReader()); Json::Value jvRequest; JSONCPP_STRING errs; if (!reader->parse(strLine.data(), strLine.data() + strLine.size(), &jvRequest, &errs)) { LogError << "json parse fail content:" << strLine; return; } /* 新数据到达后,异常数据还未开始处理,则直接关闭文件返回。先处理正常数据。 新数据到达后,异常数据处理中,则把异常未处理的数据全部当处理失败写入新文件中。先处理正常数据。 */ if (inputQueMap_[strPort0_]->getSize() > 0) { LogDebug << "Abnormal data processing, have new data to process"; if (0 == iDealCnt) { LogDebug << "Abnormal data processing not start"; inFile.close(); return; } SaveHttpFailInfo(jvRequest, strFailSaveBakPath_); bAllSucc = false; continue; } iDealCnt++; if (!ResultToHttpSrv(jvRequest)) { LogError << "re http post err:" << strLine; //SaveHttpFailInfo(jvRequest, strFailSaveBakPath_); // bAllSucc = false; continue; } } inFile.close(); if(bAllSucc) { //都处理成功,文件删除 remove(strFailSavePath_.c_str()); } else { //部分处理成功,重命名后再次被处理 rename(strFailSaveBakPath_.c_str(), strFailSavePath_.c_str()); } } /** * 保存http上传失败的信息 * inParam : Json::Value &jvRequest http失败信息 * : std::string &strFilePath 保存路径 * outParam: N/A * return : true(成功);false(失败) */ bool ResultToHttpSrvEngine::SaveHttpFailInfo(Json::Value &jvRequest, std::string &strFilePath) { std::ofstream outFile; outFile.open(strFilePath, std::ios::app); if (!outFile.is_open()) { LogError << strFilePath << " open fail"; return false; } Json::StreamWriterBuilder jswBuilder; jswBuilder["indentation"] = ""; std::string strRequest = Json::writeString(jswBuilder, jvRequest); outFile << strRequest << std::endl; outFile.close(); return true; } APP_ERROR ResultToHttpSrvEngine::Process() { int iRet = APP_ERR_OK; if (0 == MyYaml::GetIns()->GetIntValue("gc_http_open")) { LogDebug << " gc_http_open value is 0"; return APP_ERR_OK; } while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms //无数据大于1分钟 iNoDataCnt_++; if (iNoDataCnt_ > (60 * 1000)) { DealHttpFailInfo(); iNoDataCnt_ = 0; } continue; } iNoDataCnt_ = 0; std::shared_ptr pTrain = std::static_pointer_cast(pVoidData0); ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(pTrain->trainNum.iDataSource); //获取摄像机参数 char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->trainNum.iDataSource + 1); char szNumImgPath[64] = {0}; //车号最优图片路径 if (!pTrain->trainNum.strBestImg.empty()) { sprintf(szNumImgPath, "/%03d/%s", pTrain->trainNum.iDataSource + 1, pTrain->trainNum.strBestImg.c_str()); } char szProImgPath[64] = {0}; //属性最优图片路径 if (!pTrain->trainPro.strBestImg.empty()) { sprintf(szProImgPath, "/%03d/%s", pTrain->trainPro.iDataSource + 1, pTrain->trainPro.strBestImg.c_str()); } // char szChkDateImgPath[64] = {0}; //定检期最优图片路径 // if (!pTrain->chkDate.strBestImg.empty()) // { // sprintf(szChkDateImgPath, "%03d/%s", pTrain->chkDate.iDataSource + 1, pTrain->chkDate.strBestImg.c_str()); // } // char szContainer1ImgPath[64] = {0}; //集装箱1最优图片路径 // if (!pTrain->container1.strBestImg.empty()) // { // sprintf(szContainer1ImgPath, "%03d/%s", pTrain->container1.iDataSource + 1, pTrain->container1.strBestImg.c_str()); // } // char szContainer2ImgPath[64] = {0}; //集装箱2最优图片路径 // if (!pTrain->container2.strBestImg.empty()) // { // sprintf(szContainer2ImgPath, "%03d/%s", pTrain->container2.iDataSource + 1, pTrain->container2.strBestImg.c_str()); // } std::string strTime = pTrain->strTrainName; strTime = MyUtils::getins()->replace_all_distinct(strTime, std::string("-"), std::string(":")); int iCategory = 0; if (pTrain->trainNum.iTrainTypeId == 3) { iCategory = 0; } else if(pTrain->trainNum.iTrainTypeId == 2) { iCategory = 1; } else if (pTrain->trainNum.iTrainTypeId == 6) { iCategory = 2; } else if (pTrain->trainNum.iTrainTypeId == 0) { iCategory = 3; } //组装post信息 Json::Value jvRequest; Json::Value jvSubObj; jvSubObj["poundNo"] = strPoundNo_; // 股道号 jvRequest["trainParams"] = jvSubObj; jvRequest["carriageType"] = pTrain->trainNum.strTrainType; // 车型 jvRequest["carriageNumber"] = pTrain->trainNum.strTrainNum; // 车厢号 jvRequest["carriageOrder"] = pTrain->iCarXH; // 车节号 jvRequest["cameraNumber"] = szCameraNo; // 摄像头编号 jvRequest["carriageTareweight"] = pTrain->trainPro.strSelf; // 皮重 jvRequest["carriageLoad"] = pTrain->trainPro.strLoad; // 载重 jvRequest["carriageVolume"] = pTrain->trainPro.strVolume; // 容积 jvRequest["carriageChangelength"] = pTrain->trainPro.strChange; // 换长 jvRequest["proImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szProImgPath; // 属性图片 jvRequest["numImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szNumImgPath; // 车号图片 jvRequest["comeTime"] = pTrain->strTrainDate + " " + strTime; // 来车时间 jvRequest["carriageCategory"] = iCategory; // 车厢类别:0敞车,1:漏洞矿车,2:平车,3:车头 jvRequest["isTheLast"] = pTrain->bIsEnd ? 1 : 0; // 是否最后一节: 0:否,1:是 jvRequest["startFrame"] = pTrain->iStartFrameId; //车厢开始帧 jvRequest["endFrame"] = pTrain->iEndFrameId; //车厢结束帧 jvRequest["skipFrame"] = dataSourceConfig.iSkipInterval; jvRequest["collectTime"] = MyUtils::getins()->Stamp2Time(pTrain->i64EndTimeStamp, true);//车厢切分的时间 //跳帧 if (!ResultToHttpSrv(jvRequest)) { // SaveHttpFailInfo(jvRequest, strFailSavePath_); } //列车结束后再次处理失败的信息 if (pTrain->bIsEnd) { DealHttpFailInfo(); } } return APP_ERR_OK; } \ No newline at end of file +#include "ResultToHttpSrvEngine.h" #include "myutils.h" ResultToHttpSrvEngine::ResultToHttpSrvEngine() {} ResultToHttpSrvEngine::~ResultToHttpSrvEngine() {} APP_ERROR ResultToHttpSrvEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strUsername_ = MyYaml::GetIns()->GetStringValue("username"); strPassword_ = MyYaml::GetIns()->GetStringValue("password"); strURL_ = MyYaml::GetIns()->GetStringValue("gc_http_url"); strGetTokenURL_ = MyYaml::GetIns()->GetStringValue("gc_gettoken_url"); strImageSrv_ = MyYaml::GetIns()->GetPathValue("gc_image_srv"); strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); strFailSavePath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent.csv"; strFailSaveBakPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent_bak.csv"; LogInfo << "ResultToHttpSrvEngine Init ok"; return APP_ERR_OK; } APP_ERROR ResultToHttpSrvEngine::DeInit() { LogDebug << "curl_easy_cleanup"; curl_easy_cleanup(pCurl_); /* 这个处理移动到main中, 防止多线程调用 LogDebug << "内存清理"; curl_global_cleanup(); */ LogInfo << "ResultToHttpSrvEngine DeInit ok"; return APP_ERR_OK; } /** * libcurl回调函数 * inParam : void *pBuffer 回调内容地址 : size_t size 回调单个数据大小 : size_t nmemb 回调数据个数 * outParam: std::string &strResp 返回内容 * return : 回调数据大小 */ size_t ResultToHttpSrvEngine::WriteCallBack(void *pBuffer, size_t size, size_t nmemb, std::string &strResp) { size_t sizes = size * nmemb; std::string strTemp((char*)pBuffer, sizes); strResp += strTemp; return sizes; } /** * 调用http接口获取token * inParam : * outParam: std::string &strBladeAuth 返回的token信息 * return : true:成功; false:失败 */ bool ResultToHttpSrvEngine::GetToken(std::string &strBladeAuth) { //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置head, 和表单 //设置head信息 struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Authorization:Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0"); //设置表单信息 curl_mime *pMultipart = curl_mime_init(pCurl_); curl_mimepart *pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "username"); curl_mime_data(pPart, strUsername_.c_str(), CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "password"); curl_mime_data(pPart, strPassword_.c_str(), CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "tenantId"); curl_mime_data(pPart, "000000", CURL_ZERO_TERMINATED); pPart = curl_mime_addpart(pMultipart); curl_mime_name(pPart, "grant_type"); curl_mime_data(pPart, "password", CURL_ZERO_TERMINATED); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_URL, strGetTokenURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_MIMEPOST, pMultipart); //设置表单 //curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strBody.c_str()); //设置post内容 //curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 std::string strResponse; curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_mime_free(pMultipart); //清除curl_mime curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << " curl_easy_perform fail:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << " response content fail " << strResponse; return false; } LogDebug << "GetToken resp:" << strResponse; strBladeAuth += jvResponse["token_type"].asString(); strBladeAuth += " "; strBladeAuth += jvResponse["access_token"].asString(); return true; } /** * 列车信息提交http接口 * inParam : Json::Value &jvRequest 提交内容 * outParam: * return : true:提交成功; false:提交失败 */ bool ResultToHttpSrvEngine::ResultToHttpSrv(Json::Value &jvRequest) { //获取token std::string strBladeAuth("blade-auth:"); if (!GetToken(strBladeAuth)) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " GetToken fail "; return false; } LogDebug << "strBladeAuth:" << strBladeAuth; //1. 获得curl操作符 if (nullptr == pCurl_) { LogDebug<<"pCurl_ is null, invoke curl_easy_init"; pCurl_ = curl_easy_init(); if (nullptr == pCurl_) { LogError << "curl_easy_init failed !"; return false; } } //2. 设置http请求信息 Json::StreamWriterBuilder jswBuilder; std::string strRequest = Json::writeString(jswBuilder, jvRequest); LogDebug << "to http:" << strRequest; std::string strResponse; struct curl_slist *pHeaderList = nullptr; pHeaderList = curl_slist_append(pHeaderList, "Accept:application/json"); pHeaderList = curl_slist_append(pHeaderList, "Content-Type:application/json"); pHeaderList = curl_slist_append(pHeaderList, "charset:utf-8"); pHeaderList = curl_slist_append(pHeaderList, strBladeAuth.c_str()); curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时) curl_easy_setopt(pCurl_, CURLOPT_TIMEOUT, 1); // 设置超时时间为1秒 curl_easy_setopt(pCurl_, CURLOPT_URL, strURL_.c_str()); //设置url curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头 curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strRequest.c_str()); //设置post内容 curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post) curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数 curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数 //3. 执行http请求 CURLcode res = curl_easy_perform(pCurl_); curl_slist_free_all(pHeaderList); //清除headerlist curl_easy_reset(pCurl_); //重置curl if (res != CURLE_OK) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " 车节号:" << jvRequest["carriageOrder"].asInt() << " 识别结果上传失败:" << curl_easy_strerror(res); return false; } //4. 执行成功解析响应内容 LogInfo << "http resp:" << strResponse; Json::CharReaderBuilder readerBuilder; std::shared_ptr reader(readerBuilder.newCharReader()); Json::Value jvResponse; JSONCPP_STRING errs; if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs)) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " response content fail " << strResponse; return false; } if (!jvResponse["success"].asBool()) { LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " response fail"; return false; } LogInfo << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " post success"; return true; } /** * 处理上传失败的信息 * inParam : N/A * outParam: N/A * return : N/A */ void ResultToHttpSrvEngine::DealHttpFailInfo() { //队列有待处理数据,则先不处理异常数据。 if (inputQueMap_[strPort0_]->getSize() > 0) { LogDebug << "have new data to process"; return; } //文件不存在不处理 if (access(strFailSavePath_.c_str(), F_OK) == -1) { LogDebug << "no exit file:" << strFailSavePath_; return; } bool bAllSucc = true; std::ifstream inFile(strFailSavePath_.c_str(), std::ios::in); if (!inFile.is_open()) { LogError << strFailSavePath_ << " open fail"; return; } int iDealCnt = 0; std::string strLine; while (getline(inFile, strLine)) { Json::CharReaderBuilder jsrBuilder; std::shared_ptr reader(jsrBuilder.newCharReader()); Json::Value jvRequest; JSONCPP_STRING errs; if (!reader->parse(strLine.data(), strLine.data() + strLine.size(), &jvRequest, &errs)) { LogError << "json parse fail content:" << strLine; return; } /* 新数据到达后,异常数据还未开始处理,则直接关闭文件返回。先处理正常数据。 新数据到达后,异常数据处理中,则把异常未处理的数据全部当处理失败写入新文件中。先处理正常数据。 */ if (inputQueMap_[strPort0_]->getSize() > 0) { LogDebug << "Abnormal data processing, have new data to process"; if (0 == iDealCnt) { LogDebug << "Abnormal data processing not start"; inFile.close(); return; } SaveHttpFailInfo(jvRequest, strFailSaveBakPath_); bAllSucc = false; continue; } iDealCnt++; if (!ResultToHttpSrv(jvRequest)) { LogError << "re http post err:" << strLine; //SaveHttpFailInfo(jvRequest, strFailSaveBakPath_); // bAllSucc = false; continue; } } inFile.close(); if(bAllSucc) { //都处理成功,文件删除 remove(strFailSavePath_.c_str()); } else { //部分处理成功,重命名后再次被处理 rename(strFailSaveBakPath_.c_str(), strFailSavePath_.c_str()); } } /** * 保存http上传失败的信息 * inParam : Json::Value &jvRequest http失败信息 * : std::string &strFilePath 保存路径 * outParam: N/A * return : true(成功);false(失败) */ bool ResultToHttpSrvEngine::SaveHttpFailInfo(Json::Value &jvRequest, std::string &strFilePath) { std::ofstream outFile; outFile.open(strFilePath, std::ios::app); if (!outFile.is_open()) { LogError << strFilePath << " open fail"; return false; } Json::StreamWriterBuilder jswBuilder; jswBuilder["indentation"] = ""; std::string strRequest = Json::writeString(jswBuilder, jvRequest); outFile << strRequest << std::endl; outFile.close(); return true; } APP_ERROR ResultToHttpSrvEngine::Process() { int iRet = APP_ERR_OK; if (0 == MyYaml::GetIns()->GetIntValue("gc_http_open")) { LogDebug << " gc_http_open value is 0"; return APP_ERR_OK; } while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms //无数据大于1分钟 iNoDataCnt_++; if (iNoDataCnt_ > (60 * 1000)) { DealHttpFailInfo(); iNoDataCnt_ = 0; } continue; } iNoDataCnt_ = 0; std::shared_ptr pTrain = std::static_pointer_cast(pVoidData0); ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(pTrain->trainNum.iDataSource); //获取摄像机参数 char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->trainNum.iDataSource + 1); char szNumImgPath[64] = {0}; //车号最优图片路径 if (!pTrain->trainNum.strBestImg.empty()) { sprintf(szNumImgPath, "/%03d/%s", pTrain->trainNum.iDataSource + 1, pTrain->trainNum.strBestImg.c_str()); } char szProImgPath[64] = {0}; //属性最优图片路径 if (!pTrain->trainPro.strBestImg.empty()) { sprintf(szProImgPath, "/%03d/%s", pTrain->trainPro.iDataSource + 1, pTrain->trainPro.strBestImg.c_str()); } // char szChkDateImgPath[64] = {0}; //定检期最优图片路径 // if (!pTrain->chkDate.strBestImg.empty()) // { // sprintf(szChkDateImgPath, "%03d/%s", pTrain->chkDate.iDataSource + 1, pTrain->chkDate.strBestImg.c_str()); // } // char szContainer1ImgPath[64] = {0}; //集装箱1最优图片路径 // if (!pTrain->container1.strBestImg.empty()) // { // sprintf(szContainer1ImgPath, "%03d/%s", pTrain->container1.iDataSource + 1, pTrain->container1.strBestImg.c_str()); // } // char szContainer2ImgPath[64] = {0}; //集装箱2最优图片路径 // if (!pTrain->container2.strBestImg.empty()) // { // sprintf(szContainer2ImgPath, "%03d/%s", pTrain->container2.iDataSource + 1, pTrain->container2.strBestImg.c_str()); // } std::string strTime = pTrain->strTrainName; strTime = MyUtils::getins()->replace_all_distinct(strTime, std::string("-"), std::string(":")); int iCategory = 0; if (pTrain->trainNum.iTrainTypeId == 3) { iCategory = 0; } else if(pTrain->trainNum.iTrainTypeId == 2) { iCategory = 1; } else if (pTrain->trainNum.iTrainTypeId == 6) { iCategory = 2; } else if (pTrain->trainNum.iTrainTypeId == 0) { iCategory = 3; } //组装post信息 Json::Value jvRequest; Json::Value jvSubObj; jvSubObj["poundNo"] = strPoundNo_; // 股道号 jvRequest["trainParams"] = jvSubObj; jvRequest["carriageType"] = pTrain->trainNum.strTrainType; // 车型 jvRequest["carriageNumber"] = pTrain->trainNum.strTrainNum; // 车厢号 jvRequest["carriageOrder"] = pTrain->iCarXH; // 车节号 jvRequest["cameraNumber"] = szCameraNo; // 摄像头编号 jvRequest["carriageTareweight"] = pTrain->trainPro.strSelf; // 皮重 jvRequest["carriageLoad"] = pTrain->trainPro.strLoad; // 载重 jvRequest["carriageVolume"] = pTrain->trainPro.strVolume; // 容积 jvRequest["carriageChangelength"] = pTrain->trainPro.strChange; // 换长 jvRequest["proImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szProImgPath; // 属性图片 jvRequest["numImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szNumImgPath; // 车号图片 jvRequest["comeTime"] = pTrain->strTrainDate + " " + strTime; // 来车时间 jvRequest["carriageCategory"] = iCategory; // 车厢类别:0敞车,1:漏洞矿车,2:平车,3:车头 jvRequest["isTheLast"] = pTrain->bIsEnd ? 1 : 0; // 是否最后一节: 0:否,1:是 jvRequest["startFrame"] = pTrain->iStartFrameId; //车厢开始帧 jvRequest["endFrame"] = pTrain->iEndFrameId; //车厢结束帧 jvRequest["skipFrame"] = dataSourceConfig.iSkipInterval; jvRequest["collectTime"] = MyUtils::getins()->Stamp2Time(pTrain->i64EndTimeStamp, true);//车厢切分的时间 //跳帧 if (!ResultToHttpSrv(jvRequest)) { // SaveHttpFailInfo(jvRequest, strFailSavePath_); } //列车结束后再次处理失败的信息 if (pTrain->bIsEnd) { DealHttpFailInfo(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.cpp b/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.cpp index 88c4083..7fe8970 100644 --- a/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.cpp +++ b/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.cpp @@ -1 +1 @@ -#include "DeleteExpiredFolderEngine.h" using namespace ai_matrix; DeleteExpiredFolderEngine::DeleteExpiredFolderEngine() {} DeleteExpiredFolderEngine::~DeleteExpiredFolderEngine() {} APP_ERROR DeleteExpiredFolderEngine::Init() { iDaysNumber_ = MyYaml::GetIns()->GetIntValue("gc_days_for_result_expire_folder"); strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); LogInfo << "DeleteExpiredFolderEngine Init ok"; return APP_ERR_OK; } APP_ERROR DeleteExpiredFolderEngine::DeInit() { LogInfo << "DeleteExpiredFolderEngine DeInit ok"; return APP_ERR_OK; } APP_ERROR DeleteExpiredFolderEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::string strTrainDate_temp = MyUtils::getins()->GetDate(); DeletePreviousFolder(strResultPath_, strTrainDate_temp, iDaysNumber_); usleep(1000*1000*3600*24); //每二十四小时执行一次 } return APP_ERR_OK; } void DeleteExpiredFolderEngine::DeletePreviousFolder(std::string path, const std::string &date, int n_days) { // 1 computer date std::string previous_date = getDateBeforeNDays(date, n_days); if (!previous_date.empty()) std::cout << "Date before " << n_days << " days from " << date << " is: " << previous_date << std::endl; // 2 std::vector subfolders; GetSubfolderNames(path, subfolders); // for (const auto &it : subfolders) // std::cout << it.year << "." << it.month << "." << it.day << std::endl; // 3 delete if (path.back() != '/') path += "/"; Date reference_date = StrToDate(previous_date); // 给定的参考日期 DeleteEarlierDatesFolder(path, subfolders, reference_date); } // 获取某月有多少天 int DeleteExpiredFolderEngine::DaysInMonth(int year, int month) { int max_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { max_days[2] = 29; // 闰年2月有29天 } return max_days[month]; } // 解析字符串为日期结构体 Date DeleteExpiredFolderEngine::StrToDate(const std::string &date_str) { std::istringstream iss(date_str); int year, month, day; char dash; if (!(iss >> year >> dash && dash == '-' && iss >> month >> dash && dash == '-' && iss >> day)) { LogError << ("Invalid date format") << ":" << date_str; } return {year, month, day}; } // 减去指定天数 void DeleteExpiredFolderEngine::SubtractDays(Date &date, int n_days) { while (n_days > 0) { date.day--; n_days--; if (date.day == 0) { if (--date.month == 0) { --date.year; date.month = 12; } int max_days = DaysInMonth(date.year, date.month); date.day = max_days; } } } // 格式化日期结构体为字符串 std::string DeleteExpiredFolderEngine::DateToStr(const Date &date) { std::ostringstream oss; oss << date.year << "-" << std::setfill('0') << std::setw(2) << date.month << "-" << std::setw(2) << date.day; return oss.str(); } // 主要功能函数,接收一个日期字符串和一个整数n,返回n天前的日期字符串 std::string DeleteExpiredFolderEngine::getDateBeforeNDays(const std::string &input_date, int n_days) { try { Date date = StrToDate(input_date); SubtractDays(date, n_days); return DateToStr(date); } catch (const std::exception &e) { LogError << "Error: " << e.what(); return ""; } } void DeleteExpiredFolderEngine::GetSubfolderNames(std::string &directory, std::vector &folder_names) { if (directory.back() != '/') directory += "/"; DIR *dir; struct dirent *ent; if ((dir = opendir(directory.c_str())) != nullptr) { while ((ent = readdir(dir)) != nullptr) { // 排除"."和".." if (ent->d_type == DT_DIR && ent->d_name[0] != '.' && ent->d_name == "best") { folder_names.push_back(StrToDate(ent->d_name)); } } closedir(dir); } else { LogError << "Unable to open directory: " << directory; } } void DeleteExpiredFolderEngine::DeleteFolder(const std::string directory) { std::string command = "rm -rf " + directory; int result = system(command.c_str()); if (result != 0) std::cout << "Failed to remove directory recursively: " << directory << std::endl; else std::cout << "delete folder successfully : " << directory << std::endl; } // 删除向量中小于指定日期的所有元素 void DeleteExpiredFolderEngine::DeleteEarlierDatesFolder(std::string &path, std::vector &subfolders, const Date &reference_date) { if (path.back() != '/') path += "/"; for (const Date &cur : subfolders) { // bool flag = false; if (cur.year < reference_date.year) { DeleteFolder(path + DateToStr(cur)); } else if (cur.year == reference_date.year && cur.month < reference_date.month) { DeleteFolder(path + DateToStr(cur)); } else if (cur.year == reference_date.year && cur.month == reference_date.month && cur.day < reference_date.day) { DeleteFolder(path + DateToStr(cur)); } } } \ No newline at end of file +#include "DeleteExpiredFolderEngine.h" using namespace ai_matrix; DeleteExpiredFolderEngine::DeleteExpiredFolderEngine() {} DeleteExpiredFolderEngine::~DeleteExpiredFolderEngine() {} APP_ERROR DeleteExpiredFolderEngine::Init() { iDaysNumber_ = MyYaml::GetIns()->GetIntValue("gc_days_for_result_expire_folder"); strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); strLogBakPath_ = MyYaml::GetIns()->GetPathValue("gc_log_logfile_bakpath"); LogInfo << "DeleteExpiredFolderEngine Init ok"; return APP_ERR_OK; } APP_ERROR DeleteExpiredFolderEngine::DeInit() { LogInfo << "DeleteExpiredFolderEngine DeInit ok"; return APP_ERR_OK; } APP_ERROR DeleteExpiredFolderEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::string strTrainDate_temp = MyUtils::getins()->GetDate(); DeletePreviousFolder(strResultPath_, strTrainDate_temp, iDaysNumber_); // DeletePreviousFolder(strLogBakPath_, strTrainDate_temp, iDaysNumber_); usleep(1000*1000*10); //每10秒执行一次 } return APP_ERR_OK; } void DeleteExpiredFolderEngine::DeletePreviousFolder(std::string path, const std::string &date, int n_days) { // 1 computer date std::string previous_date = getDateBeforeNDays(date, n_days); if (!previous_date.empty()) std::cout << "Date before " << n_days << " days from " << date << " is: " << previous_date << std::endl; // 2 std::vector subfolders; GetSubfolderNames(path, subfolders); // for (const auto &it : subfolders) // std::cout << it.year << "." << it.month << "." << it.day << std::endl; // 3 delete if (path.back() != '/') path += "/"; Date reference_date = StrToDate(previous_date); // 给定的参考日期 DeleteEarlierDatesFolder(path, subfolders, reference_date); } // 获取某月有多少天 int DeleteExpiredFolderEngine::DaysInMonth(int year, int month) { int max_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { max_days[2] = 29; // 闰年2月有29天 } return max_days[month]; } // 解析字符串为日期结构体 Date DeleteExpiredFolderEngine::StrToDate(const std::string &date_str) { std::istringstream iss(date_str); int year, month, day; char dash; if (!(iss >> year >> dash && dash == '-' && iss >> month >> dash && dash == '-' && iss >> day)) { LogError << ("Invalid date format") << ":" << date_str; } return {year, month, day}; } // 减去指定天数 void DeleteExpiredFolderEngine::SubtractDays(Date &date, int n_days) { while (n_days > 0) { date.day--; n_days--; if (date.day == 0) { if (--date.month == 0) { --date.year; date.month = 12; } int max_days = DaysInMonth(date.year, date.month); date.day = max_days; } } } // 格式化日期结构体为字符串 std::string DeleteExpiredFolderEngine::DateToStr(const Date &date) { std::ostringstream oss; oss << date.year << "-" << std::setfill('0') << std::setw(2) << date.month << "-" << std::setw(2) << date.day; return oss.str(); } // 主要功能函数,接收一个日期字符串和一个整数n,返回n天前的日期字符串 std::string DeleteExpiredFolderEngine::getDateBeforeNDays(const std::string &input_date, int n_days) { try { Date date = StrToDate(input_date); SubtractDays(date, n_days); return DateToStr(date); } catch (const std::exception &e) { LogError << "Error: " << e.what(); return ""; } } void DeleteExpiredFolderEngine::GetSubfolderNames(std::string &directory, std::vector &folder_names) { if (directory.back() != '/') directory += "/"; DIR *dir; struct dirent *ent; if ((dir = opendir(directory.c_str())) != nullptr) { while ((ent = readdir(dir)) != nullptr) { // 排除"."和".." if (ent->d_type == DT_DIR && ent->d_name[0] != '.' && ent->d_name != "best") { folder_names.push_back(StrToDate(ent->d_name)); } } closedir(dir); } else { LogError << "Unable to open directory: " << directory; } } void DeleteExpiredFolderEngine::DeleteFolder(const std::string directory) { std::string command = "rm -rf " + directory; int result = system(command.c_str()); if (result != 0) std::cout << "Failed to remove directory recursively: " << directory << std::endl; else std::cout << "delete folder successfully : " << directory << std::endl; } // 删除向量中小于指定日期的所有元素 void DeleteExpiredFolderEngine::DeleteEarlierDatesFolder(std::string &path, std::vector &subfolders, const Date &reference_date) { if (path.back() != '/') path += "/"; for (const Date &cur : subfolders) { // bool flag = false; if (cur.year < reference_date.year) { DeleteFolder(path + DateToStr(cur)); } else if (cur.year == reference_date.year && cur.month < reference_date.month) { DeleteFolder(path + DateToStr(cur)); } else if (cur.year == reference_date.year && cur.month == reference_date.month && cur.day < reference_date.day) { DeleteFolder(path + DateToStr(cur)); } } } // void DeleteExpiredFolderEngine::PushData(const std::string &strPort, const std::shared_ptr &pSaveImgData) // { // while (true) // { // int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pSaveImgData)); // if (iRet != 0) // { // LogDebug << "sourceid:" << pSaveImgData->iDataSource << " frameid:" << pSaveImgData->iFrameId << " push fail iRet:" << iRet; // if (iRet == 2) // { // usleep(10000); // 10ms // continue; // } // } // break; // } // } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.h b/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.h index 8c808e0..fa4597c 100644 --- a/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.h +++ b/nvidia_ascend_engine/common_engine/DeleteExpiredFolderEngine/DeleteExpiredFolderEngine.h @@ -48,6 +48,7 @@ private: private: std::string strResultPath_; + std::string strLogBakPath_; int iDaysNumber_; }; diff --git a/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.cpp b/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.cpp index a3fe3a0..f480688 100644 --- a/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.cpp +++ b/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.cpp @@ -1 +1 @@ -#include "FilterTrainStepOneEngine.h" #include "myutils.h" using namespace ai_matrix; namespace { //按照x坐标排列 bool CompareX(const PostSubData &a, const PostSubData &b) { return a.step1Location.fLTX < b.step1Location.fLTX; } } extern std::atomic_uint64_t g_i64ReRunTimeStamp; extern std::atomic_uint32_t g_iReRunOrigFrameId; extern std::atomic_uint32_t g_iReRunFrameId; extern std::atomic_uint32_t g_iReRunOrigChkDateFid; extern std::atomic_uint32_t g_iReRunOrigContainerFid; FilterTrainStepOneEngine::FilterTrainStepOneEngine() {} FilterTrainStepOneEngine::~FilterTrainStepOneEngine() {} APP_ERROR FilterTrainStepOneEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); iChkStopPX_ = MyYaml::GetIns()->GetIntValue("gc_chkstop_px"); iChkStopCount_ = MyYaml::GetIns()->GetIntValue("gc_chkstop_count"); iPartitionFrameNum_ = MyYaml::GetIns()->GetIntValue("partition_frame_span"); iPlitFrameSpanPX_ = MyYaml::GetIns()->GetIntValue("gc_split_frame_span_px"); iPushDirection_ = MyYaml::GetIns()->GetIntValue("gc_push_direction"); //获取主摄像头信息 mainCfg_ = MyYaml::GetIns()->GetDataSourceConfigById(0); std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { this->rightFirst_ = iter->second.iRightFirst; this->leftFirst_ = iter->second.iLeftFirst; if (iter->second.strTarget.find("NUM") != std::string::npos) { LogDebug << "DataSource:" << iter->first << " deal NUM"; mapHeadContinueCnt_[iter->first] = 0; mapProContinueCnt_[iter->first] = 0; mapNumContinueCnt_[iter->first] = 0; mapSpaceContinueCnt_[iter->first] = 0; mapTrainSpaceContinueCnt_[iter->first] = 0; mapDataSourceIsEnd_[iter->first] = false; PostData postDataTemp; mapPostDataFrist_[iter->first] = postDataTemp; std::map> mapStep1InfoTemp; //[key-目标框id, 目标框坐标集合] mapMapStep1Info_[iter->first] = mapStep1InfoTemp; } } mapTargetStr_.insert(std::make_pair(NUM, "NUM")); mapTargetStr_.insert(std::make_pair(PRO, "PRO")); mapTargetStr_.insert(std::make_pair(HEAD, "HEAD")); mapTargetStr_.insert(std::make_pair(SPACE, "SPACE"));//SPACE mapTargetStr_.insert(std::make_pair(TRAINSPACE, "SPACE"));//SPACE InitParam(); LogInfo << "FilterTrainStepOneEngine Init ok"; return APP_ERR_OK; } APP_ERROR FilterTrainStepOneEngine::DeInit() { LogInfo << "FilterTrainStepOneEngine DeInit ok"; return APP_ERR_OK; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::InitParam() { mapProcessDataPre_.clear(); for (auto iter = mapHeadContinueCnt_.begin(); iter != mapHeadContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapProContinueCnt_.begin(); iter != mapProContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapNumContinueCnt_.begin(); iter != mapNumContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapSpaceContinueCnt_.begin(); iter != mapSpaceContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapTrainSpaceContinueCnt_.begin(); iter != mapTrainSpaceContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { iter->second = false; } for (auto iter = mapPostDataFrist_.begin(); iter != mapPostDataFrist_.end(); iter++) { iter->second.vecPostSubData.clear(); } for (auto iter = mapMapStep1Info_.begin(); iter != mapMapStep1Info_.end(); iter++) { iter->second.clear(); } iDirection_ = DIRECTION_UNKNOWN; iNotChgCount_ = 0; while (!stackBackInfo_.empty()) { stackBackInfo_.pop(); } while (!quePostData_.empty()) { quePostData_.pop(); } iTrainStatus_ = TRAINSTATUS_RUN; mapCalDirection_.clear(); } /** * push数据到队列,队列满时则休眠一段时间再push * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } void FilterTrainStepOneEngine::AddBackInfo(std::shared_ptr pProcessData) { std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); std::string strAllClassType; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { if (strAllClassType.find(mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]) != std::string::npos) { continue; } strAllClassType += mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]; } if (strAllClassType.empty()) { return; } LogDebug << "frameId:" << pProcessData->iFrameId << " addbackinfo strAllClassType:" << strAllClassType; TrainBackInfo trainBackInfo; trainBackInfo.processData = pProcessData; trainBackInfo.strAllClassType = strAllClassType; if (stackBackInfo_.empty()) { stackBackInfo_.push(trainBackInfo); LogDebug << "frameId:" << pProcessData->iFrameId << " push strAllClassType:" << strAllClassType << " stacksize:" << stackBackInfo_.size(); } else { TrainBackInfo trainBackInfoTop = stackBackInfo_.top(); // 2024年3月27日修改前 // if (trainBackInfoTop.strAllClassType != trainBackInfo.strAllClassType) // { // stackBackInfo_.push(trainBackInfo); // LogDebug << "frameId:" << pProcessData->iFrameId << " push strAllClassType:" << strAllClassType // << " stacksize:" << stackBackInfo_.size(); // } if (trainBackInfoTop.strAllClassType != trainBackInfo.strAllClassType) { if (iDirection_ == DIRECTION_RIGHT && trainBackInfo.strAllClassType == "SPACE" && (trainBackInfoTop.strAllClassType == "PROSPACE" || trainBackInfoTop.strAllClassType == "SPACEPRO")) { return; } if (iDirection_ == DIRECTION_RIGHT && trainBackInfo.strAllClassType == "SPACE" && (trainBackInfoTop.strAllClassType == "NUMSPACE" || trainBackInfoTop.strAllClassType == "SPACENUM")) { return; } if (iDirection_ == DIRECTION_LEFT && trainBackInfo.strAllClassType == "SPACE" && (trainBackInfoTop.strAllClassType == "NUMSPACE" || trainBackInfoTop.strAllClassType == "SPACENUM")) { return; } stackBackInfo_.push(trainBackInfo); LogDebug << "frameId:" << pProcessData->iFrameId << " push strAllClassType:" << strAllClassType << " stacksize:" << stackBackInfo_.size(); } } } bool FilterTrainStepOneEngine::IsEndDealBackInfo(std::shared_ptr pProcessData) { if (stackBackInfo_.empty()) { return true; } bool bPopFlag = false; std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); if (pPostData->vecPostSubData.size() == 0) return false; /* 处理倒车数据时,数据需设置为倒车,主要是保证这样的数据后面Engine不处理,防止切分车厢出错。 类型不相等时,就pop,当pop后,还剩一个数据时,则表示已经回到了刚开始倒车的地方。(只剩一个数据的逻辑在上方) 处理最后一个时,不能只判断下类型相同就弹出。需要控制下位置。(要么类型相同位置合适,要么类型不相同) 正向为向左行驶,则当前数据的位置尽量小于等于栈中最后一个元素的位置。 正向为向右行驶,则当前数据的位置尽量大于等于栈中最后一个元素的位置。 */ std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); std::string strAllClassType; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { if (strAllClassType.find(mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]) != std::string::npos) { continue; } strAllClassType += mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]; } if (strAllClassType.empty()) { return false; } if (stackBackInfo_.size() == 1) { TrainBackInfo trainBackInfoLast = stackBackInfo_.top(); std::shared_ptr pPostDataBack = std::static_pointer_cast(trainBackInfoLast.processData->pVoidData); std::sort(pPostDataBack->vecPostSubData.begin(), pPostDataBack->vecPostSubData.end(), CompareX); for (size_t i = 0; i < pPostDataBack->vecPostSubData.size(); i++) { int bFlag = -1; for (size_t j = 0; j < pPostData->vecPostSubData.size(); j++) { if (pPostDataBack->vecPostSubData[i].iBigClassId == pPostData->vecPostSubData[j].iBigClassId) { if (pPostData->vecPostSubData[j].step1Location.fLTX < 1 || pPostDataBack->vecPostSubData[i].step1Location.fLTX < 1) { LogDebug << "大框X坐标小于1,判定为异常大框。过滤!!"; break; } bFlag = (pPostDataBack->vecPostSubData[i].step1Location.fLTX <= pPostData->vecPostSubData[j].step1Location.fLTX) ? 1 : 0; LogDebug << "帧:" << pProcessData->iFrameId << " 倒车前帧:" << pPostDataBack->iFrameId << " 恢复到原位:" << bFlag << " 当前框位置:" << pPostData->vecPostSubData[i].step1Location.fLTX << " 倒车前位置:" << pPostDataBack->vecPostSubData[i].step1Location.fLTX << "方向:" << iDirection_; } } if ((iDirection_ == DIRECTION_LEFT && bFlag == 0) || (iDirection_ == DIRECTION_RIGHT && bFlag == 1)) { bPopFlag = true; break; } } if (bPopFlag) { LogDebug << "frameId:" << pProcessData->iFrameId << " 恢复倒车前的位置:" << bPopFlag; stackBackInfo_.pop(); } } else { TrainBackInfo trainBackInfoTop_bak = stackBackInfo_.top(); stackBackInfo_.pop(); TrainBackInfo trainBackInfoTop = stackBackInfo_.top(); if (trainBackInfoTop.strAllClassType != strAllClassType) { stackBackInfo_.push(trainBackInfoTop_bak); LogDebug << "帧:" << pProcessData->iFrameId << " 倒车信息:" << stackBackInfo_.size() << " 顶部倒车信息:" << trainBackInfoTop.strAllClassType << " 本次识别信息:" << strAllClassType; } else { // bPopFlag = true; LogDebug << "帧:" << pProcessData->iFrameId << " 倒车信息:" << stackBackInfo_.size() << " 顶部倒车信息:" << trainBackInfoTop.strAllClassType << " 本次识别信息:" << strAllClassType << " 删除倒车信息:" << trainBackInfoTop_bak.strAllClassType; } // if(bPopFlag) // { // stackBackInfo_.pop(); // bPopFlag = false; // } } return stackBackInfo_.empty() ? true : false; } /** * 校验火车是否停止 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : true:停止; false:非停止 1(正常行驶) 2(停车) 3(倒车) */ int FilterTrainStepOneEngine::GetTrainStatus(std::shared_ptr pProcessData) { if (iDirection_ == DIRECTION_UNKNOWN) { LogDebug << " frameId:" << pProcessData->iFrameId << " 未判断出行车方向,暂定认为火车正常行驶中"; return TRAINSTATUS_RUN; } std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); pPostData->iFrameId = pProcessData->iFrameId; // 1. 无框时,返回之前的列车状态 if (pPostData->vecPostSubData.size() == 0) { return iTrainStatus_; } quePostData_.push(*pPostData.get()); if (quePostData_.size() < 3) { return TRAINSTATUS_RUN; } PostData postDataFront = quePostData_.front(); //iNotChgCount_大于0表示有可能停车,此时pop队列数据要多留存几个。用最开始的数据来判断是否真正停车,如果每次只用上上帧判断当列车超级慢时可能判断为停车。 int iSizeTemp = iNotChgCount_ > 0 ? 10 : 2; while (quePostData_.size() > iSizeTemp) { quePostData_.pop(); } LogDebug << "frameId:" << pProcessData->iFrameId << " 判断运动状态队列 第一帧:" << postDataFront.iFrameId << " 队列size:" << quePostData_.size() << " iSizeTemp:" << iSizeTemp; bool bSameFlag = false; int iDiffValue = iChkStopPX_; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubDataBack = pPostData->vecPostSubData[i]; for (size_t j = 0; j < postDataFront.vecPostSubData.size(); j++) { PostSubData postSubDataFront = postDataFront.vecPostSubData[j]; /* 使用iBigClassId,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致类别不一样 使用iTargetType,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致像素差判断不准。 */ if (postSubDataFront.iTargetType != postSubDataBack.iTargetType) { LogDebug << "判断前后帧识别的是否一致 上一个:" << postSubDataFront.iTargetType << " 当前:" << postSubDataBack.iTargetType; continue; } // if (postSubDataFront.iTargetType == SPACE && postSubDataFront.iBigClassId != postSubDataBack.iBigClassId) // { // iDiffValue = 50; // } bSameFlag = true; int iCenterBack = postSubDataBack.step1Location.fLTX + (postSubDataBack.step1Location.fRBX - postSubDataBack.step1Location.fLTX) / 2; int iCenterFront = postSubDataFront.step1Location.fLTX + (postSubDataFront.step1Location.fRBX - postSubDataFront.step1Location.fLTX) / 2; //位置比较大于10个像素,则表示有移动。再判断时正向移动,还是倒车 LogDebug << "frameId:" << pProcessData->iFrameId << " " << iCenterBack << "-" << iCenterFront << "=" << abs(iCenterBack - iCenterFront) << " 预期判定移动的差值为iDiffValue:" << iDiffValue; if (abs(iCenterBack - iCenterFront) > iDiffValue) { iNotChgCount_ = 0; /* iCenterBack > iCenterFront 表示向右行驶,且原方向为向左行驶 iCenterBack < iCenterFront 表示向左行驶,且原方向为向右行驶 以上2种表示倒车。 */ if ((iCenterBack > iCenterFront && iDirection_ == DIRECTION_LEFT) || (iCenterBack < iCenterFront && iDirection_ == DIRECTION_RIGHT)) { if (this->iPartitionFrameNum_ < (pProcessData->iFrameId - postDataFront.iFrameId) && this->iPlitFrameSpanPX_ < abs(iCenterBack - iCenterFront)) { return TRAINSTATUS_RUN; } LogDebug << "frameId:" << pProcessData->iFrameId << " 检测到火车倒车"; return TRAINSTATUS_BACK; } else { LogDebug << "frameId:" << pProcessData->iFrameId << " 正常行驶"; return TRAINSTATUS_RUN; } } /* 小于10个像素表示可能停车,累计未变化次数。 累计变化次数超过10次,返回停车 累计变化次数未超过10次,返回之前行驶状态 */ else { iNotChgCount_++; LogDebug << " frameId:" << pProcessData->iFrameId << " 大框移动范围小 判断停车计数:" << iNotChgCount_ << "/" << iChkStopCount_; if (iNotChgCount_ > iChkStopCount_) { LogDebug << "frameId:" << pProcessData->iFrameId << " 检测到火车停车"; return TRAINSTATUS_STOP; } else { // LogDebug << "frameId:" << pProcessData->iFrameId << " iTrainStatus_:" << iTrainStatus_; return iTrainStatus_; } } } } /* 未找到相同的框,说明是老框消失掉了,新框出现了。 按新框出现的位置判断是向左行驶,还是向右行驶。 */ LogDebug << "frameId:" << pProcessData->iFrameId << " bSameFlag:" << bSameFlag; if (!bSameFlag) { std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); Step1Location step1Location = pPostData->vecPostSubData.front().step1Location; if (iDirection_ == DIRECTION_LEFT) { step1Location = pPostData->vecPostSubData.back().step1Location; } LogDebug << "frameId:" << pProcessData->iFrameId << " fLTX:" << step1Location.fLTX << " fRBX:" << step1Location.fRBX; iNotChgCount_ = 0; int iCenter = step1Location.fLTX + (step1Location.fRBX - step1Location.fLTX) / 2; int iValue = pProcessData->iWidth / 2; if ((iCenter > iValue && iDirection_ == DIRECTION_RIGHT) || (iCenter < iValue && iDirection_ == DIRECTION_LEFT)) { /* 针对有效帧较少时,和上上帧比较没有同类型大框,且当前帧已行驶到画面中心导致误判的情况, 增加和上帧同类型大框的比较处理。 */ PostData postDataMiddle = quePostData_.front(); for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubDataBack = pPostData->vecPostSubData[i]; for (size_t j = 0; j < postDataMiddle.vecPostSubData.size(); j++) { PostSubData postSubDataMiddle = postDataMiddle.vecPostSubData[j]; if (postSubDataMiddle.iTargetType != postSubDataBack.iTargetType) { continue; } int iCenterBack = postSubDataBack.step1Location.fLTX + (postSubDataBack.step1Location.fRBX - postSubDataBack.step1Location.fLTX) / 2; int iCenterMiddle = postSubDataMiddle.step1Location.fLTX + (postSubDataMiddle.step1Location.fRBX - postSubDataMiddle.step1Location.fLTX) / 2; // 位置比较大于10个像素,则表示有移动。再判断时正向移动,还是倒车 LogDebug << "frameId:" << pProcessData->iFrameId << " " << iCenterBack << "-" << iCenterMiddle << "=" << abs(iCenterBack - iCenterMiddle) << " middle cmp iDiffValue:" << iDiffValue; if (abs(iCenterBack - iCenterMiddle) > iDiffValue) { if ((iCenterBack > iCenterMiddle && iDirection_ == DIRECTION_LEFT) || (iCenterBack < iCenterMiddle && iDirection_ == DIRECTION_RIGHT)) { LogDebug << "frameId:" << pProcessData->iFrameId << " back2 back2"; return TRAINSTATUS_BACK; } else { LogDebug << "frameId:" << pProcessData->iFrameId << " run"; return TRAINSTATUS_RUN; } } } } // LogDebug << "frameId:" << pProcessData->iFrameId << " back2"; return iTrainStatus_; } } LogDebug << "frameId:" << pProcessData->iFrameId << " iNotChgCount_:" << iNotChgCount_ << " run run"; return TRAINSTATUS_RUN; } /** * 设置行车方向 * inParam : std::vector &vecLocation :大框坐标集合 : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::SetDirection(std::vector &vecLocation, std::shared_ptr pProcessData) { if (vecLocation.size() < 1) { return; } Step1Location slFront = vecLocation.front(); Step1Location slBack = vecLocation.back(); /* 移动距离小于50个像素,则判断最后一个框的出现的位置 */ LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " slFront:" << slFront.fLTX << " slBack:" << slBack.fLTX; if (fabs(slBack.fLTX - slFront.fLTX) < 50) { float fTempX1 = pProcessData->iWidth / 5; //5分之1的X坐标 float fTempX2 = pProcessData->iWidth / 5 * 4; //5分之4的X坐标 if (slBack.fLTX < fTempX1) { iDirection_ = DIRECTION_LEFT; } else if (slBack.fRBX > fTempX2) { iDirection_ = DIRECTION_RIGHT; } } else { //行驶方向 左 if ((slBack.fLTX - slFront.fLTX) < 0) { iDirection_ = DIRECTION_LEFT; } //行驶方向 右 else if ((slBack.fLTX - slFront.fLTX) > 0) { iDirection_ = DIRECTION_RIGHT; } } //未判断出移动方向,清除数后重新计算。 if (iDirection_ == DIRECTION_UNKNOWN) { auto iterMapStep1Info = mapMapStep1Info_.find(pProcessData->iDataSource); iterMapStep1Info->second.clear(); } else { if (MyYaml::GetIns()->GetDataSourceConfigById(pProcessData->iDataSource).iLeftFirst != mainCfg_.iLeftFirst) { LogDebug << "before sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; iDirection_ = (iDirection_ == DIRECTION_LEFT) ? DIRECTION_RIGHT : DIRECTION_LEFT; LogDebug << "after sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; } } } /** * 计算行车方向新 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::CalculateDirectionNew(std::shared_ptr pProcessData) { /* 连续3帧同目标识别框信息 判断位置差异是否超过10px(判停车参数),且两两之间都是线性。如果符合则计算方向。 上述条件不符合则剔除第一个元素,再次累计连续3帧处理。 */ auto iterMap = mapCalDirection_.find(pProcessData->iDataSource); if (iterMap == mapCalDirection_.end()) { std::map> mapTemp; mapCalDirection_.insert(std::make_pair(pProcessData->iDataSource, mapTemp)); iterMap = mapCalDirection_.find(pProcessData->iDataSource); } std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); for (auto iter = pPostData->vecPostSubData.begin(); iter != pPostData->vecPostSubData.end(); iter++) { CalculateInfo calInfo; calInfo.iFrameId = pProcessData->iFrameId; calInfo.iBigClassId = iter->iCarXH; calInfo.fCenterX = iter->step1Location.fLTX + (iter->step1Location.fRBX - iter->step1Location.fLTX) / 2; auto iterSubMap = iterMap->second.find(iter->iBigClassId); if (iterSubMap == iterMap->second.end()) { std::vector vecTemp; iterMap->second.insert(std::make_pair(iter->iBigClassId, vecTemp)); iterSubMap = iterMap->second.find(iter->iBigClassId); } iterSubMap->second.emplace_back(calInfo); if (iterSubMap->second.size() > 2) { LogDebug << "souceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " last:" << iterSubMap->second.at(2).iFrameId << " " << iterSubMap->second.at(2).fCenterX << " mid:" << iterSubMap->second.at(1).iFrameId << " " << iterSubMap->second.at(1).fCenterX << " pre:" << iterSubMap->second.at(0).iFrameId << " " << iterSubMap->second.at(0).fCenterX; //如果帧号连续,且移动位置大于15px,则计算方向 if (iterSubMap->second.at(2).iFrameId - iterSubMap->second.at(1).iFrameId != mainCfg_.iSkipInterval || iterSubMap->second.at(1).iFrameId - iterSubMap->second.at(0).iFrameId != mainCfg_.iSkipInterval) { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } int iLast = iterSubMap->second.at(2).fCenterX; int iMid = iterSubMap->second.at(1).fCenterX; int iPre = iterSubMap->second.at(0).fCenterX; if (abs(iPre - iLast) <= iChkStopPX_) { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } if (iPre <= iMid && iMid <= iLast) { iDirection_ = DIRECTION_RIGHT; } else if (iPre >= iMid && iMid >= iLast) { iDirection_ = DIRECTION_LEFT; } else { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } LogDebug << "souceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " iDirection_:" << iDirection_; } } //主相机的对侧相机需反向设置方向 if (iDirection_ != DIRECTION_UNKNOWN && MyYaml::GetIns()->GetDataSourceConfigById(pProcessData->iDataSource).iLeftFirst != mainCfg_.iLeftFirst) { LogDebug << "before sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; iDirection_ = (iDirection_ == DIRECTION_LEFT) ? DIRECTION_RIGHT : DIRECTION_LEFT; LogDebug << "after sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; } } /** * 计算行车方向 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::CalculateDirection(std::shared_ptr pProcessData) { auto iterPostDataFrist = mapPostDataFrist_.find(pProcessData->iDataSource); auto iterMapStep1Info = mapMapStep1Info_.find(pProcessData->iDataSource); /* 1帧暂时最多识别3个大框。[(车头、间隔、车号); (车号、间隔、属性)] 因间隔大框不是很准确,暂时把间隔大框剔除后,计算方向。 剔除间隔后,大框的可能情况为(车头; 车号; 属性; 车头&车号; 车号&属性) */ std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); PostData postDataTemp = *pPostData; for (auto iter = postDataTemp.vecPostSubData.begin(); iter != postDataTemp.vecPostSubData.end();) { if (iter->iTargetType == SPACE) { iter = postDataTemp.vecPostSubData.erase(iter); continue; } auto iterMap = iterMapStep1Info->second.find(iter->iTargetType); if (iterMap != iterMapStep1Info->second.end()) { iterMap->second.emplace_back(iter->step1Location); } else { std::vector vecTemp; vecTemp.emplace_back(iter->step1Location); iterMapStep1Info->second.insert(std::pair>(iter->iTargetType, vecTemp)); } iter++; } //记录第一次识别到大框的信息 if (iterPostDataFrist->second.vecPostSubData.size() == 0) { iterPostDataFrist->second = postDataTemp; LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " size:" << iterPostDataFrist->second.vecPostSubData.size(); } //无框时,不计算方向 if (iterPostDataFrist->second.vecPostSubData.size() == 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " no find data"; return; } //框的个数和类型没有变化时,不计算方向 if (iterPostDataFrist->second.vecPostSubData.size() - postDataTemp.vecPostSubData.size() == 0) { std::sort(iterPostDataFrist->second.vecPostSubData.begin(), iterPostDataFrist->second.vecPostSubData.end(), CompareX); std::sort(postDataTemp.vecPostSubData.begin(), postDataTemp.vecPostSubData.end(), CompareX); bool bFlag = true; for (int i = 0; i < iterPostDataFrist->second.vecPostSubData.size(); i++) { if (iterPostDataFrist->second.vecPostSubData[i].iTargetType != postDataTemp.vecPostSubData[i].iTargetType) { bFlag = false; break; } } if (bFlag) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " datasize and datatype equal"; return; } } auto iter = iterMapStep1Info->second.begin(); int iMaxSize = iter->second.size(); int iMaxSizeKey = iter->first; int iMinSize = iter->second.size(); int iMinSizeKey = iter->first; while (iter != iterMapStep1Info->second.end()) { if (iter->second.size() > iMaxSize) { iMaxSize = iter->second.size(); iMaxSizeKey = iter->first; } if (iter->second.size() < iMinSize) { iMinSize = iter->second.size(); iMinSizeKey = iter->first; } iter++; } LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " iMaxSize:" << iMaxSize << " iMaxSizeKey:" << iMaxSizeKey << " iMinSize:" << iMinSize << " iMinSizeKey:" << iMinSizeKey; /* 第一次识别为1个框,后续变化为无框或2个框,使用框个数多的数据计算方向 第一次识别为2个框,后续变化为1个框,使用个数多的数据计算方向。 后续变化为0个框,使用个数少的数据计算方向。 */ if (iterPostDataFrist->second.vecPostSubData.size() == 1) { SetDirection(iterMapStep1Info->second[iMaxSizeKey], pProcessData); } else if (iterPostDataFrist->second.vecPostSubData.size() == 2) { if (postDataTemp.vecPostSubData.size() == 1) { SetDirection(iterMapStep1Info->second[iMinSizeKey], pProcessData); } else if (postDataTemp.vecPostSubData.size() == 0) { SetDirection(iterMapStep1Info->second[iMaxSizeKey], pProcessData); } } LogDebug<< "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " 行车方向:" << iDirection_; } void FilterTrainStepOneEngine::sendComeTrain(const std::string strTrainDate, const std::string strTrainName, const int iDirection) { std::string message = "{\"cometime\":\"" + strTrainDate + " " + strTrainName + "\",\"type\":\"1\",\"direction\":" + to_string(iDirection == iPushDirection_ ? 1:-1) + "}"; LogWarn << message; outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_1"]->push(std::static_pointer_cast(std::make_shared(message))); } /** * 根据当前帧数据,处理上一帧数据 * inParam : std::shared_ptr pProcessData :当前帧数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::DealProcessDataPre(std::shared_ptr pProcessData) { /* 目标框是否是连续识别,只识别到一帧的目标框认为误识别,过滤掉。 判断上一帧,当前帧 是否有框 上一帧有框,当前帧有框,说明连续识别,正常处理。 上一帧有框,当前帧无框,则非连续识别,过滤大框 上一帧无框,当前帧有框,则连续识别个数置零。 上一帧无框,当前帧无框,则连续识别个数置零。 */ auto iterProcessData = mapProcessDataPre_.find(pProcessData->iDataSource); if (iterProcessData == mapProcessDataPre_.end() || nullptr == iterProcessData->second) { return; } auto iterHeadContinueCnt = mapHeadContinueCnt_.find(pProcessData->iDataSource); auto iterProContinueCnt = mapProContinueCnt_.find(pProcessData->iDataSource); auto iterNumContinueCnt = mapNumContinueCnt_.find(pProcessData->iDataSource); auto iterSpaceContinueCnt = mapSpaceContinueCnt_.find(pProcessData->iDataSource); auto iterTranSpaceContinueCnt = mapTrainSpaceContinueCnt_.find(pProcessData->iDataSource); //获取当前帧识别情况 std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); for (int i = 0; i < pPostData->vecPostSubData.size(); i++) { if (pPostData->vecPostSubData[i].iTargetType == HEAD) { iterHeadContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == PRO) { iterProContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == NUM) { iterNumContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == SPACE) { iterSpaceContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == TRAINSPACE) { iterTranSpaceContinueCnt->second++; } } //LogDebug << "engineId:" << engineId_ << " frameId:" << pProcessData->iFrameId << " " << iProContinueCnt_ << " " << iNumContinueCnt_; //获取上一帧识别情况 std::shared_ptr pPostDataPre = std::static_pointer_cast(iterProcessData->second->pVoidData); bool bPreHaveHead = false; bool bPreHavePro = false; bool bPreHaveNum = false; bool bPreHaveSpace = false; bool bPreHaveTrainSpace = false; for (int iPre = 0; iPre < pPostDataPre->vecPostSubData.size(); iPre++) { if (pPostDataPre->vecPostSubData[iPre].iTargetType == HEAD) { iterHeadContinueCnt->second++; bPreHaveHead = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == PRO) { iterProContinueCnt->second++; bPreHavePro = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == NUM) { iterNumContinueCnt->second++; bPreHaveNum = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == SPACE) { iterSpaceContinueCnt->second++; bPreHaveSpace = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == TRAINSPACE) { iterTranSpaceContinueCnt->second++; bPreHaveTrainSpace = true; } } //前一帧无大框连续识别次数置零 iterHeadContinueCnt->second = bPreHaveHead ? iterHeadContinueCnt->second : 0; iterProContinueCnt->second = bPreHavePro ? iterProContinueCnt->second : 0; iterNumContinueCnt->second = bPreHaveNum ? iterNumContinueCnt->second : 0; iterSpaceContinueCnt->second = bPreHaveSpace ? iterSpaceContinueCnt->second : 0; iterTranSpaceContinueCnt->second = bPreHaveTrainSpace ? iterTranSpaceContinueCnt->second : 0; //非连续识别的情况,认为误识别,剔除误识别的大框信息 for (std::vector::iterator it = pPostDataPre->vecPostSubData.begin(); it != pPostDataPre->vecPostSubData.end();) { if (iterHeadContinueCnt->second < 2 && it->iTargetType == HEAD) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " Head 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterProContinueCnt->second < 2 && it->iTargetType == PRO) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " PRO 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterNumContinueCnt->second < 2 && it->iTargetType == NUM) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " NUM 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterSpaceContinueCnt->second < 2 && it->iTargetType == SPACE) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " SPACE 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterTranSpaceContinueCnt->second < 2 && it->iTargetType == TRAINSPACE) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " TRAINSPACE 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } it++; } //判定行驶方向, 记录Direction文件信息 if (iDirection_ == DIRECTION_UNKNOWN) { iDirection_ = iterProcessData->second->iDirection; LogInfo << "方向:" << (iDirection_ == DIRECTION_LEFT ? "左" : (iDirection_ == DIRECTION_RIGHT ? "右" : "未判断出来")); if (iDirection_ == DIRECTION_UNKNOWN) { //CalculateDirection(iterProcessData->second); CalculateDirectionNew(iterProcessData->second); if (iDirection_ != DIRECTION_UNKNOWN) this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_); } if (iDirection_ != DIRECTION_UNKNOWN) { auto iterPostDataFrist = mapPostDataFrist_.find(pProcessData->iDataSource); Json::Value jvDirectionInfo; jvDirectionInfo["direction"] = iDirection_; jvDirectionInfo["firstStep1Cnt"] = iterPostDataFrist->second.vecPostSubData.size(); jvDirectionInfo["frameid"] = iterProcessData->second->iFrameId; jvDirectionInfo["sourceid"] = iterProcessData->second->iDataSource; std::string strFilePath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/" + "direction.txt"; MyUtils::getins()->WriteJsonInfo(jvDirectionInfo, strFilePath); } } //主摄像头校验是否停车 int iTrainStatusTemp = iTrainStatus_; if (iterProcessData->second->iDataSource == 0) { iTrainStatus_ = GetTrainStatus(iterProcessData->second); iTrainStatusTemp = iTrainStatus_; if (iTrainStatus_ == TRAINSTATUS_STOP) { //停车 } else if (iTrainStatus_ == TRAINSTATUS_BACK) { //倒车 AddBackInfo(iterProcessData->second); iTrainStatusTemp = TRAINSTATUS_STOP; } else if(iTrainStatus_ == TRAINSTATUS_RUN) { /* 正向行驶需先把倒车产生的倒车数据处理完毕,即使车辆回到原倒车点,再开始识别行驶数据 */ if(!IsEndDealBackInfo(iterProcessData->second)) { iTrainStatusTemp = TRAINSTATUS_STOP; } } } LogDebug << "数据源:" << iterProcessData->second->iDataSource << " 帧:" << iterProcessData->second->iFrameId << " 火车实时运行状态:" << iTrainStatus_ << "(0无车,1运行,2停车,3倒车) iTrainStatusTemp:" << iTrainStatusTemp; iterProcessData->second->iStatus = iTrainStatusTemp; // this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_); //上一帧,push端口0 PushData(strPort0_, iterProcessData->second); } APP_ERROR FilterTrainStepOneEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); // //停止后再次行驶,把队列中多余的数据丢弃。 // if (iReRunOrigFrameId_ != 0 && pProcessData->iOrigFrameId > iReRunOrigFrameId_ && !pProcessData->bIsEnd) // { // LogDebug << "reRunOrigFrameId:" << iReRunOrigFrameId_ << " origFrameId:" << pProcessData->iOrigFrameId; // continue; // } if (pProcessData->bIsEnd) { mapDataSourceIsEnd_[pProcessData->iDataSource] = pProcessData->bIsEnd; } //1帧暂时最多识别4个大框。[(车头、车厢间隔、间隔、车号); (车号、车厢间隔、间隔、属性)] if (pPostData->vecPostSubData.size() > 4) { LogError << "sourceid:" << pProcessData->iDataSource << " frameId:" << pProcessData->iFrameId << " vecpostsubdata size:" << pPostData->vecPostSubData.size(); pPostData->vecPostSubData.clear(); } //按指定识别区域过滤误识别信息--过滤逻辑迁移至TrainStepOneEngine中。 //根据当前帧数据,处理上一帧数据 DealProcessDataPre(pProcessData); mapProcessDataPre_[pProcessData->iDataSource] = pProcessData; if (pProcessData->bIsEnd) { //结束帧,push端口0 LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " isEnd:" << pProcessData->bIsEnd; PushData(strPort0_, pProcessData); } //3. 全部结束,初始化相关参数 bool bAllEnd = true; for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { bAllEnd = bAllEnd && iter->second; } if (bAllEnd) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " bAllEnd"; InitParam(); } } return APP_ERR_OK; } \ No newline at end of file +#include "FilterTrainStepOneEngine.h" #include "myutils.h" #include using namespace ai_matrix; namespace { //按照x坐标排列 bool CompareX(const PostSubData &a, const PostSubData &b) { return a.step1Location.fLTX < b.step1Location.fLTX; } } extern std::atomic_uint64_t g_i64ReRunTimeStamp; extern std::atomic_uint32_t g_iReRunOrigFrameId; extern std::atomic_uint32_t g_iReRunFrameId; extern std::atomic_uint32_t g_iReRunOrigChkDateFid; extern std::atomic_uint32_t g_iReRunOrigContainerFid; FilterTrainStepOneEngine::FilterTrainStepOneEngine() {} FilterTrainStepOneEngine::~FilterTrainStepOneEngine() {} APP_ERROR FilterTrainStepOneEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); iChkStopPX_ = MyYaml::GetIns()->GetIntValue("gc_chkstop_px"); iChkStopCount_ = MyYaml::GetIns()->GetIntValue("gc_chkstop_count"); iPartitionFrameNum_ = MyYaml::GetIns()->GetIntValue("partition_frame_span"); iPlitFrameSpanPX_ = MyYaml::GetIns()->GetIntValue("gc_split_frame_span_px"); iPushDirection_ = MyYaml::GetIns()->GetIntValue("gc_push_direction"); //获取主摄像头信息 mainCfg_ = MyYaml::GetIns()->GetDataSourceConfigById(0); std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { this->rightFirst_ = iter->second.iRightFirst; this->leftFirst_ = iter->second.iLeftFirst; if (iter->second.strTarget.find("NUM") != std::string::npos) { LogDebug << "DataSource:" << iter->first << " deal NUM"; mapHeadContinueCnt_[iter->first] = 0; mapProContinueCnt_[iter->first] = 0; mapNumContinueCnt_[iter->first] = 0; mapSpaceContinueCnt_[iter->first] = 0; mapTrainSpaceContinueCnt_[iter->first] = 0; mapDataSourceIsEnd_[iter->first] = false; PostData postDataTemp; mapPostDataFrist_[iter->first] = postDataTemp; std::map> mapStep1InfoTemp; //[key-目标框id, 目标框坐标集合] mapMapStep1Info_[iter->first] = mapStep1InfoTemp; } } mapTargetStr_.insert(std::make_pair(NUM, "NUM")); mapTargetStr_.insert(std::make_pair(PRO, "PRO")); mapTargetStr_.insert(std::make_pair(HEAD, "HEAD")); mapTargetStr_.insert(std::make_pair(SPACE, "SPACE"));//SPACE mapTargetStr_.insert(std::make_pair(TRAINSPACE, "SPACE"));//SPACE InitParam(); LogInfo << "FilterTrainStepOneEngine Init ok"; return APP_ERR_OK; } APP_ERROR FilterTrainStepOneEngine::DeInit() { LogInfo << "FilterTrainStepOneEngine DeInit ok"; return APP_ERR_OK; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::InitParam() { mapProcessDataPre_.clear(); for (auto iter = mapHeadContinueCnt_.begin(); iter != mapHeadContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapProContinueCnt_.begin(); iter != mapProContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapNumContinueCnt_.begin(); iter != mapNumContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapSpaceContinueCnt_.begin(); iter != mapSpaceContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapTrainSpaceContinueCnt_.begin(); iter != mapTrainSpaceContinueCnt_.end(); iter++) { iter->second = 0; } for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { iter->second = false; } for (auto iter = mapPostDataFrist_.begin(); iter != mapPostDataFrist_.end(); iter++) { iter->second.vecPostSubData.clear(); } for (auto iter = mapMapStep1Info_.begin(); iter != mapMapStep1Info_.end(); iter++) { iter->second.clear(); } iDirection_ = DIRECTION_UNKNOWN; iNotChgCount_ = 0; while (!stackBackInfo_.empty()) { stackBackInfo_.pop(); } while (!quePostData_.empty()) { quePostData_.pop(); } iTrainStatus_ = TRAINSTATUS_RUN; mapCalDirection_.clear(); } /** * push数据到队列,队列满时则休眠一段时间再push * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } void FilterTrainStepOneEngine::AddBackInfo(std::shared_ptr pProcessData) { std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); std::string strAllClassType; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { if (strAllClassType.find(mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]) != std::string::npos) { continue; } strAllClassType += mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]; } if (strAllClassType.empty()) { return; } LogDebug << "frameId:" << pProcessData->iFrameId << " addbackinfo strAllClassType:" << strAllClassType; TrainBackInfo trainBackInfo; trainBackInfo.processData = pProcessData; trainBackInfo.strAllClassType = strAllClassType; if (stackBackInfo_.empty()) { stackBackInfo_.push(trainBackInfo); LogDebug << "frameId:" << pProcessData->iFrameId << " push strAllClassType:" << strAllClassType << " stacksize:" << stackBackInfo_.size(); } else { TrainBackInfo trainBackInfoTop = stackBackInfo_.top(); if (trainBackInfoTop.strAllClassType != trainBackInfo.strAllClassType) { if (((iDirection_ == DIRECTION_RIGHT && this->rightFirst_ == RIGHT_RUN_AND_PRO_FIRST) || (iDirection_ == DIRECTION_LEFT && this->leftFirst_ == LEFT_RUN_AND_PRO_FIRST)) && ((trainBackInfo.strAllClassType == "SPACE" && (trainBackInfoTop.strAllClassType == "PROSPACE" || trainBackInfoTop.strAllClassType == "SPACEPRO")) || (trainBackInfo.strAllClassType == "NUM" && (trainBackInfoTop.strAllClassType == "NUMSPACE" || trainBackInfoTop.strAllClassType == "SPACENUM")) || ((trainBackInfo.strAllClassType == "PROSPACE" || trainBackInfo.strAllClassType == "SPACEPRO") && trainBackInfoTop.strAllClassType == "PRO"))) { return; } if (((iDirection_ == DIRECTION_RIGHT && this->rightFirst_ == RIGHT_RUN_AND_NUM_FIRST) || (iDirection_ == DIRECTION_LEFT && this->leftFirst_ == LEFT_RUN_AND_NUM_FIRST)) && ((trainBackInfo.strAllClassType == "SPACE" && (trainBackInfoTop.strAllClassType == "NUMSPACE" || trainBackInfoTop.strAllClassType == "SPACENUM")) || (trainBackInfo.strAllClassType == "PRO" && (trainBackInfoTop.strAllClassType == "PROSPACE" || trainBackInfoTop.strAllClassType == "SPACEPRO")) || ((trainBackInfo.strAllClassType == "NUMSPACE" || trainBackInfo.strAllClassType == "SPACENUM") && trainBackInfoTop.strAllClassType == "NUM"))) { return; } stackBackInfo_.push(trainBackInfo); LogDebug << "frameId:" << pProcessData->iFrameId << " push strAllClassType:" << strAllClassType << " stacksize:" << stackBackInfo_.size(); } } } bool FilterTrainStepOneEngine::IsEndDealBackInfo(std::shared_ptr pProcessData) { if (stackBackInfo_.empty()) { return true; } bool bPopFlag = false; std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); if (pPostData->vecPostSubData.size() == 0) return false; /* 处理倒车数据时,数据需设置为倒车,主要是保证这样的数据后面Engine不处理,防止切分车厢出错。 类型不相等时,就pop,当pop后,还剩一个数据时,则表示已经回到了刚开始倒车的地方。(只剩一个数据的逻辑在上方) 处理最后一个时,不能只判断下类型相同就弹出。需要控制下位置。(要么类型相同位置合适,要么类型不相同) 正向为向左行驶,则当前数据的位置尽量小于等于栈中最后一个元素的位置。 正向为向右行驶,则当前数据的位置尽量大于等于栈中最后一个元素的位置。 */ std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); std::string strAllClassType; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { if (strAllClassType.find(mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]) != std::string::npos) { continue; } strAllClassType += mapTargetStr_[pPostData->vecPostSubData[i].iTargetType]; } if (strAllClassType.empty()) { return false; } if (stackBackInfo_.size() == 1) { TrainBackInfo trainBackInfoLast = stackBackInfo_.top(); std::shared_ptr pPostDataBack = std::static_pointer_cast(trainBackInfoLast.processData->pVoidData); std::sort(pPostDataBack->vecPostSubData.begin(), pPostDataBack->vecPostSubData.end(), CompareX); for (size_t i = 0; i < pPostDataBack->vecPostSubData.size(); i++) { int bFlag = -1; for (size_t j = 0; j < pPostData->vecPostSubData.size(); j++) { if (pPostDataBack->vecPostSubData[i].iBigClassId == pPostData->vecPostSubData[j].iBigClassId) { if (pPostData->vecPostSubData[j].step1Location.fLTX < 1 || pPostDataBack->vecPostSubData[i].step1Location.fLTX < 1) { LogDebug << "大框X坐标小于1,判定为异常大框。过滤!!"; break; } bFlag = (pPostDataBack->vecPostSubData[i].step1Location.fLTX <= pPostData->vecPostSubData[j].step1Location.fLTX) ? 1 : 0; LogDebug << "帧:" << pProcessData->iFrameId << " 倒车前帧:" << pPostDataBack->iFrameId << " 恢复到原位:" << bFlag << " 当前框位置:" << pPostData->vecPostSubData[i].step1Location.fLTX << " 倒车前位置:" << pPostDataBack->vecPostSubData[i].step1Location.fLTX << "方向:" << iDirection_; } } if ((iDirection_ == DIRECTION_LEFT && bFlag == 0) || (iDirection_ == DIRECTION_RIGHT && bFlag == 1)) { bPopFlag = true; break; } } if (bPopFlag) { LogDebug << "frameId:" << pProcessData->iFrameId << " 恢复倒车前的位置:" << bPopFlag; stackBackInfo_.pop(); } } else { TrainBackInfo trainBackInfoTop_bak = stackBackInfo_.top(); stackBackInfo_.pop(); TrainBackInfo trainBackInfoTop = stackBackInfo_.top(); if (trainBackInfoTop.strAllClassType != strAllClassType) { stackBackInfo_.push(trainBackInfoTop_bak); LogDebug << "帧:" << pProcessData->iFrameId << " 倒车信息:" << stackBackInfo_.size() << " 顶部倒车信息:" << trainBackInfoTop.strAllClassType << " 本次识别信息:" << strAllClassType; } else { // bPopFlag = true; LogDebug << "帧:" << pProcessData->iFrameId << " 倒车信息:" << stackBackInfo_.size() << " 顶部倒车信息:" << trainBackInfoTop.strAllClassType << " 本次识别信息:" << strAllClassType << " 删除倒车信息:" << trainBackInfoTop_bak.strAllClassType; } // if(bPopFlag) // { // stackBackInfo_.pop(); // bPopFlag = false; // } } return stackBackInfo_.empty() ? true : false; } /** * 校验火车是否停止 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : true:停止; false:非停止 1(正常行驶) 2(停车) 3(倒车) */ int FilterTrainStepOneEngine::GetTrainStatus(std::shared_ptr pProcessData) { if (iDirection_ == DIRECTION_UNKNOWN) { LogDebug << " frameId:" << pProcessData->iFrameId << " 未判断出行车方向,暂定认为火车正常行驶中"; return TRAINSTATUS_RUN; } std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); pPostData->iFrameId = pProcessData->iFrameId; // 1. 无框时,返回之前的列车状态 if (pPostData->vecPostSubData.size() == 0) { return iTrainStatus_; } quePostData_.push(*pPostData.get()); if (quePostData_.size() < 3) { return TRAINSTATUS_RUN; } PostData postDataFront = quePostData_.front(); //iNotChgCount_大于0表示有可能停车,此时pop队列数据要多留存几个。用最开始的数据来判断是否真正停车,如果每次只用上上帧判断当列车超级慢时可能判断为停车。 int iSizeTemp = iNotChgCount_ > 0 ? 10 : 2; while (quePostData_.size() > iSizeTemp) { quePostData_.pop(); } // LogDebug << "frameId:" << pProcessData->iFrameId << " 判断运动状态队列 第一帧:" << postDataFront.iFrameId << " 队列size:" << quePostData_.size() << " iSizeTemp:" << iSizeTemp; bool bSameFlag = false; int iDiffValue = iChkStopPX_; for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubDataBack = pPostData->vecPostSubData[i]; for (size_t j = 0; j < postDataFront.vecPostSubData.size(); j++) { PostSubData postSubDataFront = postDataFront.vecPostSubData[j]; /* 使用iBigClassId,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致类别不一样 使用iTargetType,可能出现平车只有间隔大框,且间隔大框可以一会是平车间隔,一会是通用间隔。导致像素差判断不准。 */ if (postSubDataFront.iTargetType != postSubDataBack.iTargetType) { LogDebug << "判断前后帧识别的是否一致 上一个:" << postSubDataFront.iTargetType << " 当前:" << postSubDataBack.iTargetType; continue; } // if (postSubDataFront.iTargetType == SPACE && postSubDataFront.iBigClassId != postSubDataBack.iBigClassId) // { // iDiffValue = 50; // } bSameFlag = true; int iCenterBack = postSubDataBack.step1Location.fLTX + (postSubDataBack.step1Location.fRBX - postSubDataBack.step1Location.fLTX) / 2; int iCenterFront = postSubDataFront.step1Location.fLTX + (postSubDataFront.step1Location.fRBX - postSubDataFront.step1Location.fLTX) / 2; //位置比较大于10个像素,则表示有移动。再判断时正向移动,还是倒车 // LogDebug << "frameId:" << pProcessData->iFrameId << " " << iCenterBack << "-" << iCenterFront // << "=" << abs(iCenterBack - iCenterFront) << " 预期判定移动的差值为iDiffValue:" << iDiffValue; if (abs(iCenterBack - iCenterFront) > iDiffValue) { iNotChgCount_ = 0; /* iCenterBack > iCenterFront 表示向右行驶,且原方向为向左行驶 iCenterBack < iCenterFront 表示向左行驶,且原方向为向右行驶 以上2种表示倒车。 */ if ((iCenterBack > iCenterFront && iDirection_ == DIRECTION_LEFT) || (iCenterBack < iCenterFront && iDirection_ == DIRECTION_RIGHT)) { if (this->iPartitionFrameNum_ < (pProcessData->iFrameId - postDataFront.iFrameId) && this->iPlitFrameSpanPX_ < abs(iCenterBack - iCenterFront)) { return TRAINSTATUS_RUN; } LogDebug << "frameId:" << pProcessData->iFrameId << " 检测到火车倒车"; return TRAINSTATUS_BACK; } else { LogDebug << "frameId:" << pProcessData->iFrameId << " 正常行驶"; return TRAINSTATUS_RUN; } } /* 小于10个像素表示可能停车,累计未变化次数。 累计变化次数超过10次,返回停车 累计变化次数未超过10次,返回之前行驶状态 */ else { iNotChgCount_++; LogDebug << " frameId:" << pProcessData->iFrameId << " 大框移动范围小(" << abs(iCenterBack - iCenterFront) << ") 判断停车计数:" << iNotChgCount_ << "/" << iChkStopCount_; if (iNotChgCount_ > iChkStopCount_) { LogDebug << "frameId:" << pProcessData->iFrameId << " 检测到火车停车"; return TRAINSTATUS_STOP; } else { // LogDebug << "frameId:" << pProcessData->iFrameId << " iTrainStatus_:" << iTrainStatus_; return iTrainStatus_; } } } } /* 未找到相同的框,说明是老框消失掉了,新框出现了。 按新框出现的位置判断是向左行驶,还是向右行驶。 */ LogDebug << "frameId:" << pProcessData->iFrameId << " bSameFlag:" << bSameFlag; if (!bSameFlag) { std::sort(pPostData->vecPostSubData.begin(), pPostData->vecPostSubData.end(), CompareX); Step1Location step1Location = pPostData->vecPostSubData.front().step1Location; if (iDirection_ == DIRECTION_LEFT) { step1Location = pPostData->vecPostSubData.back().step1Location; } LogDebug << "frameId:" << pProcessData->iFrameId << " fLTX:" << step1Location.fLTX << " fRBX:" << step1Location.fRBX; iNotChgCount_ = 0; int iCenter = step1Location.fLTX + (step1Location.fRBX - step1Location.fLTX) / 2; int iValue = pProcessData->iWidth / 2; if ((iCenter > iValue && iDirection_ == DIRECTION_RIGHT) || (iCenter < iValue && iDirection_ == DIRECTION_LEFT)) { /* 针对有效帧较少时,和上上帧比较没有同类型大框,且当前帧已行驶到画面中心导致误判的情况, 增加和上帧同类型大框的比较处理。 */ PostData postDataMiddle = quePostData_.front(); for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubDataBack = pPostData->vecPostSubData[i]; for (size_t j = 0; j < postDataMiddle.vecPostSubData.size(); j++) { PostSubData postSubDataMiddle = postDataMiddle.vecPostSubData[j]; if (postSubDataMiddle.iTargetType != postSubDataBack.iTargetType) { continue; } int iCenterBack = postSubDataBack.step1Location.fLTX + (postSubDataBack.step1Location.fRBX - postSubDataBack.step1Location.fLTX) / 2; int iCenterMiddle = postSubDataMiddle.step1Location.fLTX + (postSubDataMiddle.step1Location.fRBX - postSubDataMiddle.step1Location.fLTX) / 2; // 位置比较大于10个像素,则表示有移动。再判断时正向移动,还是倒车 LogDebug << "frameId:" << pProcessData->iFrameId << " " << iCenterBack << "-" << iCenterMiddle << "=" << abs(iCenterBack - iCenterMiddle) << " 移动差值 iDiffValue:" << iDiffValue; if (abs(iCenterBack - iCenterMiddle) > iDiffValue) { if ((iCenterBack > iCenterMiddle && iDirection_ == DIRECTION_LEFT) || (iCenterBack < iCenterMiddle && iDirection_ == DIRECTION_RIGHT)) { LogDebug << "frameId:" << pProcessData->iFrameId << " 检测到火车倒车"; return TRAINSTATUS_BACK; } else { LogDebug << "frameId:" << pProcessData->iFrameId << " 正常行驶"; return TRAINSTATUS_RUN; } } } } // LogDebug << "frameId:" << pProcessData->iFrameId << " back2"; return iTrainStatus_; } } // LogDebug << "frameId:" << pProcessData->iFrameId << " iNotChgCount_:" << iNotChgCount_ << " run run"; return TRAINSTATUS_RUN; } /** * 设置行车方向 * inParam : std::vector &vecLocation :大框坐标集合 : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::SetDirection(std::vector &vecLocation, std::shared_ptr pProcessData) { if (vecLocation.size() < 1) { return; } Step1Location slFront = vecLocation.front(); Step1Location slBack = vecLocation.back(); /* 移动距离小于50个像素,则判断最后一个框的出现的位置 */ LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " slFront:" << slFront.fLTX << " slBack:" << slBack.fLTX; if (fabs(slBack.fLTX - slFront.fLTX) < 50) { float fTempX1 = pProcessData->iWidth / 5; //5分之1的X坐标 float fTempX2 = pProcessData->iWidth / 5 * 4; //5分之4的X坐标 if (slBack.fLTX < fTempX1) { iDirection_ = DIRECTION_LEFT; } else if (slBack.fRBX > fTempX2) { iDirection_ = DIRECTION_RIGHT; } } else { //行驶方向 左 if ((slBack.fLTX - slFront.fLTX) < 0) { iDirection_ = DIRECTION_LEFT; } //行驶方向 右 else if ((slBack.fLTX - slFront.fLTX) > 0) { iDirection_ = DIRECTION_RIGHT; } } //未判断出移动方向,清除数后重新计算。 if (iDirection_ == DIRECTION_UNKNOWN) { auto iterMapStep1Info = mapMapStep1Info_.find(pProcessData->iDataSource); iterMapStep1Info->second.clear(); } else { if (MyYaml::GetIns()->GetDataSourceConfigById(pProcessData->iDataSource).iLeftFirst != mainCfg_.iLeftFirst) { LogDebug << "before sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; iDirection_ = (iDirection_ == DIRECTION_LEFT) ? DIRECTION_RIGHT : DIRECTION_LEFT; LogDebug << "after sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; } } } /** * 计算行车方向新 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::CalculateDirectionNew(std::shared_ptr pProcessData) { /* 连续3帧同目标识别框信息 判断位置差异是否超过10px(判停车参数),且两两之间都是线性。如果符合则计算方向。 上述条件不符合则剔除第一个元素,再次累计连续3帧处理。 */ auto iterMap = mapCalDirection_.find(pProcessData->iDataSource); if (iterMap == mapCalDirection_.end()) { std::map> mapTemp; mapCalDirection_.insert(std::make_pair(pProcessData->iDataSource, mapTemp)); iterMap = mapCalDirection_.find(pProcessData->iDataSource); } std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); for (auto iter = pPostData->vecPostSubData.begin(); iter != pPostData->vecPostSubData.end(); iter++) { CalculateInfo calInfo; calInfo.iFrameId = pProcessData->iFrameId; calInfo.iBigClassId = iter->iBigClassId; calInfo.fCenterX = iter->step1Location.fLTX + (iter->step1Location.fRBX - iter->step1Location.fLTX) / 2; calInfo.fTargetWidth = iter->step1Location.fRBX - iter->step1Location.fLTX; auto iterSubMap = iterMap->second.find(iter->iBigClassId); if (iterSubMap == iterMap->second.end()) { std::vector vecTemp; iterMap->second.insert(std::make_pair(iter->iBigClassId, vecTemp)); iterSubMap = iterMap->second.find(iter->iBigClassId); } iterSubMap->second.emplace_back(calInfo); if (iterSubMap->second.size() > 2) { LogDebug << "souceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " last:" << iterSubMap->second.at(2).iFrameId << " " << iterSubMap->second.at(2).fCenterX << " mid:" << iterSubMap->second.at(1).iFrameId << " " << iterSubMap->second.at(1).fCenterX << " pre:" << iterSubMap->second.at(0).iFrameId << " " << iterSubMap->second.at(0).fCenterX; //如果帧号连续,且移动位置大于15px,则计算方向 if (iterSubMap->second.at(2).iFrameId - iterSubMap->second.at(1).iFrameId != mainCfg_.iSkipInterval || iterSubMap->second.at(1).iFrameId - iterSubMap->second.at(0).iFrameId != mainCfg_.iSkipInterval) { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } if (abs(iterSubMap->second.at(0).fTargetWidth - iterSubMap->second.at(2).fTargetWidth) >= 1.5*iChkStopPX_) { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } int iLast = iterSubMap->second.at(2).fCenterX; int iMid = iterSubMap->second.at(1).fCenterX; int iPre = iterSubMap->second.at(0).fCenterX; if (abs(iPre - iLast) <= iChkStopPX_) { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } if (iPre <= iMid && iMid <= iLast) { iDirection_ = DIRECTION_RIGHT; } else if (iPre >= iMid && iMid >= iLast) { iDirection_ = DIRECTION_LEFT; } else { iterSubMap->second.erase(iterSubMap->second.begin()); continue; } LogDebug << "souceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " iDirection_:" << iDirection_; } } //主相机的对侧相机需反向设置方向 if (iDirection_ != DIRECTION_UNKNOWN && MyYaml::GetIns()->GetDataSourceConfigById(pProcessData->iDataSource).iLeftFirst != mainCfg_.iLeftFirst) { LogDebug << "before sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; iDirection_ = (iDirection_ == DIRECTION_LEFT) ? DIRECTION_RIGHT : DIRECTION_LEFT; LogDebug << "after sourceid:" << pProcessData->iDataSource << "frameid:" << pProcessData->iFrameId << " direction:" << iDirection_; } } /** * 计算行车方向 * inParam : std::shared_ptr pProcessData :待处理数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::CalculateDirection(std::shared_ptr pProcessData) { auto iterPostDataFrist = mapPostDataFrist_.find(pProcessData->iDataSource); auto iterMapStep1Info = mapMapStep1Info_.find(pProcessData->iDataSource); /* 1帧暂时最多识别3个大框。[(车头、间隔、车号); (车号、间隔、属性)] 因间隔大框不是很准确,暂时把间隔大框剔除后,计算方向。 剔除间隔后,大框的可能情况为(车头; 车号; 属性; 车头&车号; 车号&属性) */ std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); PostData postDataTemp = *pPostData; for (auto iter = postDataTemp.vecPostSubData.begin(); iter != postDataTemp.vecPostSubData.end();) { if (iter->iTargetType == SPACE) { iter = postDataTemp.vecPostSubData.erase(iter); continue; } auto iterMap = iterMapStep1Info->second.find(iter->iTargetType); if (iterMap != iterMapStep1Info->second.end()) { iterMap->second.emplace_back(iter->step1Location); } else { std::vector vecTemp; vecTemp.emplace_back(iter->step1Location); iterMapStep1Info->second.insert(std::pair>(iter->iTargetType, vecTemp)); } iter++; } //记录第一次识别到大框的信息 if (iterPostDataFrist->second.vecPostSubData.size() == 0) { iterPostDataFrist->second = postDataTemp; LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " size:" << iterPostDataFrist->second.vecPostSubData.size(); } //无框时,不计算方向 if (iterPostDataFrist->second.vecPostSubData.size() == 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " no find data"; return; } //框的个数和类型没有变化时,不计算方向 if (iterPostDataFrist->second.vecPostSubData.size() - postDataTemp.vecPostSubData.size() == 0) { std::sort(iterPostDataFrist->second.vecPostSubData.begin(), iterPostDataFrist->second.vecPostSubData.end(), CompareX); std::sort(postDataTemp.vecPostSubData.begin(), postDataTemp.vecPostSubData.end(), CompareX); bool bFlag = true; for (int i = 0; i < iterPostDataFrist->second.vecPostSubData.size(); i++) { if (iterPostDataFrist->second.vecPostSubData[i].iTargetType != postDataTemp.vecPostSubData[i].iTargetType) { bFlag = false; break; } } if (bFlag) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " datasize and datatype equal"; return; } } auto iter = iterMapStep1Info->second.begin(); int iMaxSize = iter->second.size(); int iMaxSizeKey = iter->first; int iMinSize = iter->second.size(); int iMinSizeKey = iter->first; while (iter != iterMapStep1Info->second.end()) { if (iter->second.size() > iMaxSize) { iMaxSize = iter->second.size(); iMaxSizeKey = iter->first; } if (iter->second.size() < iMinSize) { iMinSize = iter->second.size(); iMinSizeKey = iter->first; } iter++; } LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " iMaxSize:" << iMaxSize << " iMaxSizeKey:" << iMaxSizeKey << " iMinSize:" << iMinSize << " iMinSizeKey:" << iMinSizeKey; /* 第一次识别为1个框,后续变化为无框或2个框,使用框个数多的数据计算方向 第一次识别为2个框,后续变化为1个框,使用个数多的数据计算方向。 后续变化为0个框,使用个数少的数据计算方向。 */ if (iterPostDataFrist->second.vecPostSubData.size() == 1) { SetDirection(iterMapStep1Info->second[iMaxSizeKey], pProcessData); } else if (iterPostDataFrist->second.vecPostSubData.size() == 2) { if (postDataTemp.vecPostSubData.size() == 1) { SetDirection(iterMapStep1Info->second[iMinSizeKey], pProcessData); } else if (postDataTemp.vecPostSubData.size() == 0) { SetDirection(iterMapStep1Info->second[iMaxSizeKey], pProcessData); } } LogDebug<< "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " 行车方向:" << iDirection_; } void FilterTrainStepOneEngine::sendComeTrain(const std::string strTrainDate, const std::string strTrainName, const int iDirection) { std::string message = "{\"cometime\":\"" + strTrainDate + " " + strTrainName + "\",\"type\":\"1\",\"direction\":" + to_string(iDirection == iPushDirection_ ? 1:-1) + "}"; LogWarn << message; outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_1"]->push(std::static_pointer_cast(std::make_shared(message))); } /** * 根据当前帧数据,处理上一帧数据 * inParam : std::shared_ptr pProcessData :当前帧数据 * outParam: N/A * return : N/A */ void FilterTrainStepOneEngine::DealProcessDataPre(std::shared_ptr pProcessData) { /* 目标框是否是连续识别,只识别到一帧的目标框认为误识别,过滤掉。 判断上一帧,当前帧 是否有框 上一帧有框,当前帧有框,说明连续识别,正常处理。 上一帧有框,当前帧无框,则非连续识别,过滤大框 上一帧无框,当前帧有框,则连续识别个数置零。 上一帧无框,当前帧无框,则连续识别个数置零。 */ auto iterProcessData = mapProcessDataPre_.find(pProcessData->iDataSource); if (iterProcessData == mapProcessDataPre_.end() || nullptr == iterProcessData->second) { return; } auto iterHeadContinueCnt = mapHeadContinueCnt_.find(pProcessData->iDataSource); auto iterProContinueCnt = mapProContinueCnt_.find(pProcessData->iDataSource); auto iterNumContinueCnt = mapNumContinueCnt_.find(pProcessData->iDataSource); auto iterSpaceContinueCnt = mapSpaceContinueCnt_.find(pProcessData->iDataSource); auto iterTranSpaceContinueCnt = mapTrainSpaceContinueCnt_.find(pProcessData->iDataSource); //获取当前帧识别情况 std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); for (int i = 0; i < pPostData->vecPostSubData.size(); i++) { if (pPostData->vecPostSubData[i].iTargetType == HEAD) { iterHeadContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == PRO) { iterProContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == NUM) { iterNumContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == SPACE) { iterSpaceContinueCnt->second++; } else if (pPostData->vecPostSubData[i].iTargetType == TRAINSPACE) { iterTranSpaceContinueCnt->second++; } } //LogDebug << "engineId:" << engineId_ << " frameId:" << pProcessData->iFrameId << " " << iProContinueCnt_ << " " << iNumContinueCnt_; //获取上一帧识别情况 std::shared_ptr pPostDataPre = std::static_pointer_cast(iterProcessData->second->pVoidData); bool bPreHaveHead = false; bool bPreHavePro = false; bool bPreHaveNum = false; bool bPreHaveSpace = false; bool bPreHaveTrainSpace = false; for (int iPre = 0; iPre < pPostDataPre->vecPostSubData.size(); iPre++) { if (pPostDataPre->vecPostSubData[iPre].iTargetType == HEAD) { iterHeadContinueCnt->second++; bPreHaveHead = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == PRO) { iterProContinueCnt->second++; bPreHavePro = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == NUM) { iterNumContinueCnt->second++; bPreHaveNum = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == SPACE) { iterSpaceContinueCnt->second++; bPreHaveSpace = true; } else if (pPostDataPre->vecPostSubData[iPre].iTargetType == TRAINSPACE) { iterTranSpaceContinueCnt->second++; bPreHaveTrainSpace = true; } } //前一帧无大框连续识别次数置零 iterHeadContinueCnt->second = bPreHaveHead ? iterHeadContinueCnt->second : 0; iterProContinueCnt->second = bPreHavePro ? iterProContinueCnt->second : 0; iterNumContinueCnt->second = bPreHaveNum ? iterNumContinueCnt->second : 0; iterSpaceContinueCnt->second = bPreHaveSpace ? iterSpaceContinueCnt->second : 0; iterTranSpaceContinueCnt->second = bPreHaveTrainSpace ? iterTranSpaceContinueCnt->second : 0; //非连续识别的情况,认为误识别,剔除误识别的大框信息 for (std::vector::iterator it = pPostDataPre->vecPostSubData.begin(); it != pPostDataPre->vecPostSubData.end();) { if (iterHeadContinueCnt->second < 2 && it->iTargetType == HEAD) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " Head 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterProContinueCnt->second < 2 && it->iTargetType == PRO) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " PRO 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterNumContinueCnt->second < 2 && it->iTargetType == NUM) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " NUM 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterSpaceContinueCnt->second < 2 && it->iTargetType == SPACE) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " SPACE 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } if (iterTranSpaceContinueCnt->second < 2 && it->iTargetType == TRAINSPACE) { LogDebug << " frameId:" << iterProcessData->second->iFrameId << " TRAINSPACE 框因非连续识别而过滤"; it = pPostDataPre->vecPostSubData.erase(it); continue; } it++; } //判定行驶方向, 记录Direction文件信息 if (iDirection_ == DIRECTION_UNKNOWN) { iDirection_ = iterProcessData->second->iDirection; LogInfo << "方向:" << (iDirection_ == DIRECTION_LEFT ? "左" : (iDirection_ == DIRECTION_RIGHT ? "右" : "未判断出来")); if (iDirection_ == DIRECTION_UNKNOWN) { //CalculateDirection(iterProcessData->second); CalculateDirectionNew(iterProcessData->second); if (iDirection_ != DIRECTION_UNKNOWN) this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_); } if (iDirection_ != DIRECTION_UNKNOWN) { auto iterPostDataFrist = mapPostDataFrist_.find(pProcessData->iDataSource); Json::Value jvDirectionInfo; jvDirectionInfo["direction"] = iDirection_; jvDirectionInfo["firstStep1Cnt"] = iterPostDataFrist->second.vecPostSubData.size(); jvDirectionInfo["frameid"] = iterProcessData->second->iFrameId; jvDirectionInfo["sourceid"] = iterProcessData->second->iDataSource; std::string strFilePath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/" + "direction.txt"; MyUtils::getins()->WriteJsonInfo(jvDirectionInfo, strFilePath); } } //主摄像头校验是否停车 int iTrainStatusTemp = iTrainStatus_; if (iterProcessData->second->iDataSource == 0) { iTrainStatus_ = GetTrainStatus(iterProcessData->second); iTrainStatusTemp = iTrainStatus_; if (iTrainStatus_ == TRAINSTATUS_STOP) { //停车 } else if (iTrainStatus_ == TRAINSTATUS_BACK) { //倒车 AddBackInfo(iterProcessData->second); iTrainStatusTemp = TRAINSTATUS_STOP; } else if(iTrainStatus_ == TRAINSTATUS_RUN) { /* 正向行驶需先把倒车产生的倒车数据处理完毕,即使车辆回到原倒车点,再开始识别行驶数据 */ if(!IsEndDealBackInfo(iterProcessData->second)) { iTrainStatusTemp = TRAINSTATUS_STOP; } } } LogDebug << "数据源:" << iterProcessData->second->iDataSource << " 帧:" << iterProcessData->second->iFrameId << " 火车实时运行状态:" << iTrainStatus_ << "(0无车,1运行,2停车,3倒车) iTrainStatusTemp:" << iTrainStatusTemp; iterProcessData->second->iStatus = iTrainStatusTemp; // this->sendComeTrain(pProcessData->strTrainDate, pProcessData->strTrainName, iDirection_); //上一帧,push端口0 PushData(strPort0_, iterProcessData->second); } APP_ERROR FilterTrainStepOneEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); // //停止后再次行驶,把队列中多余的数据丢弃。 // if (iReRunOrigFrameId_ != 0 && pProcessData->iOrigFrameId > iReRunOrigFrameId_ && !pProcessData->bIsEnd) // { // LogDebug << "reRunOrigFrameId:" << iReRunOrigFrameId_ << " origFrameId:" << pProcessData->iOrigFrameId; // continue; // } if (pProcessData->bIsEnd) { mapDataSourceIsEnd_[pProcessData->iDataSource] = pProcessData->bIsEnd; } //1帧暂时最多识别4个大框。[(车头、车厢间隔、间隔、车号); (车号、车厢间隔、间隔、属性)] if (pPostData->vecPostSubData.size() > 4) { LogError << "sourceid:" << pProcessData->iDataSource << " frameId:" << pProcessData->iFrameId << " vecpostsubdata size:" << pPostData->vecPostSubData.size(); pPostData->vecPostSubData.clear(); } //按指定识别区域过滤误识别信息--过滤逻辑迁移至TrainStepOneEngine中。 //根据当前帧数据,处理上一帧数据 DealProcessDataPre(pProcessData); mapProcessDataPre_[pProcessData->iDataSource] = pProcessData; if (pProcessData->bIsEnd) { //结束帧,push端口0 LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " isEnd:" << pProcessData->bIsEnd; PushData(strPort0_, pProcessData); } //3. 全部结束,初始化相关参数 bool bAllEnd = true; for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { bAllEnd = bAllEnd && iter->second; } if (bAllEnd) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " bAllEnd"; InitParam(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.h b/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.h index a95f9c2..432b8b3 100644 --- a/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.h +++ b/nvidia_ascend_engine/common_engine/FilterEngine/FilterTrainStepOneEngine.h @@ -58,11 +58,11 @@ private: int iChkStopPX_; int iChkStopCount_; int iDirection_; //方向 - int iPushDirection_; //需要识别的方向 + int iPushDirection_; //需要识别的方向 int rightFirst_; // 向右行驶的在前大框类型 int leftFirst_; // 向左行驶的在前大框类型 int iPartitionFrameNum_; //满足跨车厢的帧间隔 - int iPlitFrameSpanPX_; //相连帧 同种大框的跨度最大值 + int iPlitFrameSpanPX_; //相连帧 同种大框的跨度最大值 std::map mapPostDataFrist_; //[key-数据源id, value-第一步识别信息] std::map>> mapMapStep1Info_; //[key-数据源id, value-[key-识别目标, value-识别框集合]] diff --git a/nvidia_ascend_engine/common_engine/MergerEngine/MergerAllEngine.cpp b/nvidia_ascend_engine/common_engine/MergerEngine/MergerAllEngine.cpp index 9ec9201..79a9fec 100644 --- a/nvidia_ascend_engine/common_engine/MergerEngine/MergerAllEngine.cpp +++ b/nvidia_ascend_engine/common_engine/MergerEngine/MergerAllEngine.cpp @@ -2,6 +2,22 @@ using namespace ai_matrix; +namespace +{ + std::map mapLoad = { + {"C62", "60"}, + {"C62B", "61"}, + {"C63", "61"}, + {"C64", "61"}, + {"C65", "60"}, + {"C70", "70"}, + {"C80", "80"}, + {"KM70", "70"}, + {"KM81", "81"}, + {"KM98", "98"} + }; +} + MergerAllEngine::MergerAllEngine() {} MergerAllEngine::~MergerAllEngine() {} @@ -133,7 +149,7 @@ void MergerAllEngine::PushData(std::shared_ptr pTrain) pTrain->bMergerFlag = true; std::shared_ptr pTrainToCsv = std::make_shared(); *pTrainToCsv = *pTrain; - + if (bUploadFlag_) { queTrain_.push(pTrain); @@ -251,7 +267,7 @@ APP_ERROR MergerAllEngine::Process() } int iHaveDataCnt = QueueHaveDataCount(); - //识别目标信息个数和获取信息个数相等,则合并信息推送web + //识别目标信息个数和获取信息个数相等,则合并信息推送web if (iHaveDataCnt == iPopPortCnt_) { std::shared_ptr pTrain = nullptr; @@ -299,7 +315,7 @@ APP_ERROR MergerAllEngine::Process() pTrain->container1 = pTrainContainer->container1; pTrain->container2 = pTrainContainer->container2; } - + //车头在前为第0节; 车头在后为最后一节+1 if(pTrain->trainNum.iTrainTypeId == 0 && iTrainIndex_ == 1) { @@ -312,12 +328,28 @@ APP_ERROR MergerAllEngine::Process() 特殊处理:针对车头在后的且当前为最后一节,且未识别到车型,则默认设置为车头。 防止车尾间隔误识别,多切分车型,且web端无法过滤的问题。 */ - if (!bHeadFrontFlag_ && pTrain->bIsEnd && pTrain->trainNum.iTrainTypeId == -1) + if (!bHeadFrontFlag_ + && pTrain->bIsEnd + && pTrain->trainNum.iTrainTypeId == -1) { LogDebug << "cometime:" << pTrain->strTrainDate << " " << pTrain->strTrainName << " iCarXH:" << pTrain->iCarXH << " num:" << pTrain->trainNum.strTrainNum; pTrain->trainNum.iTrainTypeId = 0; } + + // 修正载重 + for (std::map::iterator it = + mapLoad.begin(); + it != mapLoad.end(); ++it) { + + if (pTrain->trainNum.strTrainType.find(it->first) != + std::string::npos) { + pTrain->trainPro.strLoad = it->second; + } + } + + // if (pTrain->trainPro.strLoad.size() > 2 && pTrain->trainPro.strLoad[0] != '1') pTrain->trainPro.strLoad = ""; + PushData(pTrain); //最后一节处理后,初始化参数 diff --git a/nvidia_ascend_engine/common_engine/SaveEngine/SaveCsvEngine.cpp b/nvidia_ascend_engine/common_engine/SaveEngine/SaveCsvEngine.cpp index 232abfd..8e64d87 100644 --- a/nvidia_ascend_engine/common_engine/SaveEngine/SaveCsvEngine.cpp +++ b/nvidia_ascend_engine/common_engine/SaveEngine/SaveCsvEngine.cpp @@ -1 +1 @@ -#include "SaveCsvEngine.h" using namespace ai_matrix; SaveCsvEngine::SaveCsvEngine() {} SaveCsvEngine::~SaveCsvEngine() {} APP_ERROR SaveCsvEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); LogInfo << "SaveCsvEngine Init ok"; return APP_ERR_OK; } APP_ERROR SaveCsvEngine::DeInit() { LogInfo << "SaveCsvEngine DeInit ok"; return APP_ERR_OK; } /** * 保存合并后车厢的最优结果到CSV中 (该文件支持其web导入) * inParam : std::shared_ptr pTrain :列车信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveMergerCsv(std::shared_ptr pTrain) { //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/) std::string strTrainPath = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + "/"; if (!MyUtils::getins()->CreateDirPath(strTrainPath)) { LogError << "iCarXH:" << pTrain->iCarXH << " train savecsv err"; return false; } //2. 保存csv std::string strCsvName = pTrain->strTrainDate + pTrain->strTrainName + std::string(".csv"); strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strTrainPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); // 打开模式可省略 if (!bIsExsit) { outFile << "poundno" << ',' << "year" << ',' << "time" << ',' << "direction" << ',' << "speed" << ',' << "camerano" << ',' << "skipInterval" << ',' << "carxh" << ',' << "type" << ',' << "num" << ',' << "load" << ',' << "self" << ',' << "volume" << ',' << "volumesurface" << ',' << "change" << ',' << "numImgPath" << ',' << "proImgPath" << ',' << "videoStart" << ',' << "videoEnd" << ',' << "containerNo1" << ',' << "containerNo2" << ',' << "inspection" << ',' << "inspectionImg" << ',' << "containerImg_1" << ',' << "containerImg_2" << ',' << "startTime" << ',' << "endTime" << std::endl; } std::string strTime = pTrain->strTrainName; strTime = MyUtils::getins()->replace_all_distinct(strTime, std::string("-"), std::string(":")); ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(pTrain->trainNum.iDataSource); //获取摄像机参数 char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->trainNum.iDataSource + 1); char szNumImgPath[64] = {0}; //车号最优图片路径 if (!pTrain->trainNum.strBestImg.empty()) { sprintf(szNumImgPath, "%03d/%s", pTrain->trainNum.iDataSource + 1, pTrain->trainNum.strBestImg.c_str()); } char szProImgPath[64] = {0}; //属性最优图片路径 if (!pTrain->trainPro.strBestImg.empty()) { sprintf(szProImgPath, "%03d/%s", pTrain->trainPro.iDataSource + 1, pTrain->trainPro.strBestImg.c_str()); } char szChkDateImgPath[64] = {0}; //定检期最优图片路径 if (!pTrain->chkDate.strBestImg.empty()) { sprintf(szChkDateImgPath, "%03d/%s", pTrain->chkDate.iDataSource + 1, pTrain->chkDate.strBestImg.c_str()); } char szContainer1ImgPath[64] = {0}; //集装箱1最优图片路径 if (!pTrain->container1.strBestImg.empty()) { sprintf(szContainer1ImgPath, "%03d/%s", pTrain->container1.iDataSource + 1, pTrain->container1.strBestImg.c_str()); } char szContainer2ImgPath[64] = {0}; //集装箱2最优图片路径 if (!pTrain->container2.strBestImg.empty()) { sprintf(szContainer2ImgPath, "%03d/%s", pTrain->container2.iDataSource + 1, pTrain->container2.strBestImg.c_str()); } outFile << strPoundNo_ << ',' << pTrain->strTrainDate << ',' << strTime << ',' << pTrain->iDirection << ',' << 0.0 << ',' << szCameraNo << ',' << dataSourceConfig.iSkipInterval << ',' << pTrain->iCarXH << ',' << pTrain->trainNum.strTrainType << ',' << pTrain->trainNum.strTrainNum << ',' << pTrain->trainPro.strLoad << ',' << pTrain->trainPro.strSelf << ',' << pTrain->trainPro.strVolume << ',' << pTrain->trainPro.strVolumeSurface << ',' //容量记表 << pTrain->trainPro.strChange << ',' << szNumImgPath << ',' << szProImgPath << ',' << pTrain->iStartFrameId << ',' << pTrain->iEndFrameId << ',' << pTrain->container1.strContainerNo << ',' << pTrain->container2.strContainerNo << ',' << pTrain->chkDate.strChkDate1DeadLine << ',' << szChkDateImgPath << ',' << szContainer1ImgPath << ',' << szContainer2ImgPath << ',' << MyUtils::getins()->Stamp2Time(pTrain->i64StartTimeStamp, true) << ',' << MyUtils::getins()->Stamp2Time(pTrain->i64EndTimeStamp, true) << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " train savecsv fail!"; return false; } return true; } /** * 保存车厢的最优结果到CSV中 * inParam : std::shared_ptr pTrain :列车信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveTrainCsv(std::shared_ptr pTrain) { char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->iDataSource + 1); std::string strTrainPath = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + "/" + szCameraNo + "/"; //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) if (!MyUtils::getins()->CreateDirPath(strTrainPath)) { LogError << "iCarXH:" << pTrain->iCarXH << " train savecsv err"; return false; } //2. 保存csv std::string strCsvName = pTrain->strTrainDate + pTrain->strTrainName + "_" + szCameraNo + "_train.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strTrainPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); if (!bIsExsit) { outFile << "car_xh" << ',' << "train_num_name" << ',' << "train_pro_name" << ',' << "t_type" << ',' << "t_num" << ',' << "load" << ',' << "self" << ',' << "volume" << ',' << "change" << ',' << "volumesurface" << ',' << "num_ltx" << ',' << "num_lty" << ',' << "num_rbx" << ',' << "num_rby" << ',' << "pro_ltx" << ',' << "pro_lty" << ',' << "pro_rbx" << ',' << "pro_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "start_timestamp" << ',' //记录车厢开始,结束帧时间戳,用于比对集装箱合并 << "timestamp" << ',' << "end_timestamp" << ',' << "start_num" << ',' << "num_timestamp" << ',' //记录车号,属性时间戳,用于比对定检期合并 << "end_num" << ',' << "start_pro" << ',' << "pro_timestamp" << ',' << "end_pro" << std::endl; } outFile << pTrain->iCarXH << ',' << pTrain->trainNum.strBestImg << ',' << pTrain->trainPro.strBestImg << ',' << pTrain->trainNum.strTrainType << ',' << pTrain->trainNum.strTrainNum << ',' << pTrain->trainPro.strLoad << ',' << pTrain->trainPro.strSelf << ',' << pTrain->trainPro.strVolume << ',' << pTrain->trainPro.strChange << ',' << pTrain->trainPro.strVolumeSurface << ',' << pTrain->trainNum.step1Location.fLTX << ',' << pTrain->trainNum.step1Location.fLTY << ',' << pTrain->trainNum.step1Location.fRBX << ',' << pTrain->trainNum.step1Location.fRBY << ',' << pTrain->trainPro.step1Location.fLTX << ',' << pTrain->trainPro.step1Location.fLTY << ',' << pTrain->trainPro.step1Location.fRBX << ',' << pTrain->trainPro.step1Location.fRBY << ',' << pTrain->iStartFrameId << ',' << pTrain->iEndFrameId << ',' << pTrain->i64StartTimeStamp << ',' << pTrain->i64TimeStamp << ',' << pTrain->i64EndTimeStamp << ',' << pTrain->trainNum.i64StartTimeStamp << ',' << pTrain->trainNum.i64TimeStamp << ',' << pTrain->trainNum.i64EndTimeStamp << ',' << pTrain->trainPro.i64StartTimeStamp << ',' << pTrain->trainPro.i64TimeStamp << ',' << pTrain->trainPro.i64EndTimeStamp << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " train savecsv fail!"; return false; } return true; } /** * 保存定检期的最优结果到CSV中 * inParam : std::shared_ptr pChkDate :定检期信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveChkDateCsv(std::shared_ptr pChkDate) { if (pChkDate->strBestImg.empty()) { LogDebug << "datetime:" << pChkDate->strTrainDate << " " << pChkDate->strTrainName << " carxh:" << pChkDate->iCarXH << " chkdate empty"; return true; } //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pChkDate->iDataSource + 1); std::string strChkDatePath = strResultPath_ + pChkDate->strTrainDate + "/" + pChkDate->strTrainName + "/" + szCameraNo + "/"; if (!MyUtils::getins()->CreateDirPath(strChkDatePath)) { LogError << "iCarXH:" << pChkDate->iCarXH << "chkdate savecsv err"; return false; } //2. 保存csv std::string strCsvName = pChkDate->strTrainDate + pChkDate->strTrainName + "_" + szCameraNo + "_chkdate.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strChkDatePath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); // 打开模式可省略 if (!bIsExsit) { outFile << "car_xh" << ',' << "chkdate_name" << ',' << "chkdate1" << ',' << "chkdate2" << ',' << "chkdate_ltx" << ',' << "chkdate_lty" << ',' << "chkdate_rbx" << ',' << "chkdate_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "start_timestamp" << ',' << "end_timestamp" << ',' << "timestamp" << ',' << "chkdate1deadline" << std::endl; } outFile << pChkDate->iCarXH << ',' << pChkDate->strBestImg << ',' << pChkDate->strChkDate1 << ',' << pChkDate->strChkDate2 << ',' << pChkDate->step1Location.fLTX << ',' << pChkDate->step1Location.fLTY << ',' << pChkDate->step1Location.fRBX << ',' << pChkDate->step1Location.fRBY << ',' << pChkDate->iStartFrameId << ',' << pChkDate->iEndFrameId << ',' << pChkDate->i64StartTimeStamp << ',' << pChkDate->i64EndTimeStamp << ',' << pChkDate->i64TimeStamp << ',' << pChkDate->strChkDate1DeadLine << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " chkdate savecsv fail!"; return false; } return true; } /** * 保存集装箱的最优结果到CSV中 * inParam : std::shared_ptr pTrainContainer :集装箱信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveContainerCsv(std::shared_ptr pTrainContainer) { std::vector vecContainer; vecContainer.emplace_back(pTrainContainer->container1); vecContainer.emplace_back(pTrainContainer->container2); for (auto iter = vecContainer.begin(); iter != vecContainer.end(); iter++) { if (iter->strContainerNo.empty()) { continue; } // 1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", iter->iDataSource + 1); std::string strContainerPath = strResultPath_ + iter->strTrainDate + "/" + iter->strTrainName + "/" + szCameraNo + "/"; if (!MyUtils::getins()->CreateDirPath(strContainerPath)) { LogError << "ContainerNo:" << iter->strContainerNo << " container savecsv err"; continue; } // 2. 保存csv std::string strCsvName = iter->strTrainDate + iter->strTrainName + "_" + szCameraNo + "_container.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strContainerPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); if (!bIsExsit) { outFile << "datasource" << ',' << "container_name" << ',' << "containerNo" << ',' << "container_ltx" << ',' << "container_lty" << ',' << "container_rbx" << ',' << "container_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "timestamp" << std::endl; } outFile << iter->iDataSource << ',' << iter->strBestImg << ',' << iter->strContainerNo << ',' << iter->step1Location.fLTX << ',' << iter->step1Location.fLTY << ',' << iter->step1Location.fRBX << ',' << iter->step1Location.fRBY << ',' << iter->iStartFrameId << ',' << iter->iEndFrameId << ',' << iter->i64TimeStamp << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " container savecsv fail!"; continue; } } return true; } APP_ERROR SaveCsvEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { bool bPopFlag = false; //pop端口0 车厢信息 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr != pVoidData0) { std::shared_ptr pTrain = std::static_pointer_cast(pVoidData0); if (pTrain->bMergerFlag) { SaveMergerCsv(pTrain); } else { SaveTrainCsv(pTrain); } bPopFlag = true; } //pop端口1 定检期信息 if (inputQueMap_.count(strPort1_) > 0) { std::shared_ptr pVoidData1 = nullptr; inputQueMap_[strPort1_]->pop(pVoidData1); if (nullptr != pVoidData1) { std::shared_ptr pChkDate = std::static_pointer_cast(pVoidData1); SaveChkDateCsv(pChkDate); bPopFlag = true; } } //pop端口2 集装箱信息 if (inputQueMap_.count(strPort2_) > 0) { std::shared_ptr pVoidData2 = nullptr; inputQueMap_[strPort2_]->pop(pVoidData2); if (nullptr != pVoidData2) { std::shared_ptr pTrainContainer = std::static_pointer_cast(pVoidData2); SaveContainerCsv(pTrainContainer); bPopFlag = true; } } if (!bPopFlag) { usleep(1000); continue; } } return APP_ERR_OK; } \ No newline at end of file +#include "SaveCsvEngine.h" using namespace ai_matrix; SaveCsvEngine::SaveCsvEngine() {} SaveCsvEngine::~SaveCsvEngine() {} APP_ERROR SaveCsvEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno"); LogInfo << "SaveCsvEngine Init ok"; return APP_ERR_OK; } APP_ERROR SaveCsvEngine::DeInit() { LogInfo << "SaveCsvEngine DeInit ok"; return APP_ERR_OK; } /** * 保存合并后车厢的最优结果到CSV中 (该文件支持其web导入) * inParam : std::shared_ptr pTrain :列车信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveMergerCsv(std::shared_ptr pTrain) { //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/) std::string strTrainPath = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + "/"; if (!MyUtils::getins()->CreateDirPath(strTrainPath)) { LogError << "iCarXH:" << pTrain->iCarXH << " train savecsv err"; return false; } //2. 保存csv std::string strCsvName = pTrain->strTrainDate + pTrain->strTrainName + std::string(".csv"); strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strTrainPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); // 打开模式可省略 if (!bIsExsit) { outFile << "poundno" << ',' << "year" << ',' << "time" << ',' << "direction" << ',' << "speed" << ',' << "typeId" << ',' << "skipInterval" << ',' << "carxh" << ',' << "type" << ',' << "num" << ',' << "load" << ',' << "self" << ',' << "volume" << ',' << "volumesurface" << ',' << "change" << ',' << "numImgPath" << ',' << "proImgPath" << ',' << "videoStart" << ',' << "videoEnd" << ',' << "containerNo1" << ',' << "containerNo2" << ',' << "inspection" << ',' << "inspectionImg" << ',' << "containerImg_1" << ',' << "containerImg_2" << ',' << "startTime" << ',' << "endTime" << std::endl; } std::string strTime = pTrain->strTrainName; strTime = MyUtils::getins()->replace_all_distinct(strTime, std::string("-"), std::string(":")); ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(pTrain->trainNum.iDataSource); //获取摄像机参数 char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->trainNum.iDataSource + 1); char szNumImgPath[64] = {0}; //车号最优图片路径 if (!pTrain->trainNum.strBestImg.empty()) { sprintf(szNumImgPath, "%03d/%s", pTrain->trainNum.iDataSource + 1, pTrain->trainNum.strBestImg.c_str()); } char szProImgPath[64] = {0}; //属性最优图片路径 if (!pTrain->trainPro.strBestImg.empty()) { sprintf(szProImgPath, "%03d/%s", pTrain->trainPro.iDataSource + 1, pTrain->trainPro.strBestImg.c_str()); } char szChkDateImgPath[64] = {0}; //定检期最优图片路径 if (!pTrain->chkDate.strBestImg.empty()) { sprintf(szChkDateImgPath, "%03d/%s", pTrain->chkDate.iDataSource + 1, pTrain->chkDate.strBestImg.c_str()); } char szContainer1ImgPath[64] = {0}; //集装箱1最优图片路径 if (!pTrain->container1.strBestImg.empty()) { sprintf(szContainer1ImgPath, "%03d/%s", pTrain->container1.iDataSource + 1, pTrain->container1.strBestImg.c_str()); } char szContainer2ImgPath[64] = {0}; //集装箱2最优图片路径 if (!pTrain->container2.strBestImg.empty()) { sprintf(szContainer2ImgPath, "%03d/%s", pTrain->container2.iDataSource + 1, pTrain->container2.strBestImg.c_str()); } outFile << strPoundNo_ << ',' << pTrain->strTrainDate << ',' << strTime << ',' << pTrain->iDirection << ',' << 0.0 << ',' << pTrain->trainNum.iTrainTypeId << ',' << dataSourceConfig.iSkipInterval << ',' << pTrain->iCarXH << ',' << pTrain->trainNum.strTrainType << ',' << pTrain->trainNum.strTrainNum << ',' << pTrain->trainPro.strLoad << ',' << pTrain->trainPro.strSelf << ',' << pTrain->trainPro.strVolume << ',' << pTrain->trainPro.strVolumeSurface << ',' //容量记表 << pTrain->trainPro.strChange << ',' << szNumImgPath << ',' << szProImgPath << ',' << pTrain->iStartFrameId << ',' << pTrain->iEndFrameId << ',' << pTrain->container1.strContainerNo << ',' << pTrain->container2.strContainerNo << ',' << pTrain->chkDate.strChkDate1DeadLine << ',' << szChkDateImgPath << ',' << szContainer1ImgPath << ',' << szContainer2ImgPath << ',' << MyUtils::getins()->Stamp2Time(pTrain->i64StartTimeStamp, true) << ',' << MyUtils::getins()->Stamp2Time(pTrain->i64EndTimeStamp, true) << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " train savecsv fail!"; return false; } return true; } /** * 保存车厢的最优结果到CSV中 * inParam : std::shared_ptr pTrain :列车信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveTrainCsv(std::shared_ptr pTrain) { char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pTrain->iDataSource + 1); std::string strTrainPath = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + "/" + szCameraNo + "/"; //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) if (!MyUtils::getins()->CreateDirPath(strTrainPath)) { LogError << "iCarXH:" << pTrain->iCarXH << " train savecsv err"; return false; } //2. 保存csv std::string strCsvName = pTrain->strTrainDate + pTrain->strTrainName + "_" + szCameraNo + "_train.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strTrainPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); if (!bIsExsit) { outFile << "car_xh" << ',' << "train_num_name" << ',' << "train_pro_name" << ',' << "t_type" << ',' << "t_num" << ',' << "load" << ',' << "self" << ',' << "volume" << ',' << "change" << ',' << "volumesurface" << ',' << "num_ltx" << ',' << "num_lty" << ',' << "num_rbx" << ',' << "num_rby" << ',' << "pro_ltx" << ',' << "pro_lty" << ',' << "pro_rbx" << ',' << "pro_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "start_timestamp" << ',' //记录车厢开始,结束帧时间戳,用于比对集装箱合并 << "timestamp" << ',' << "end_timestamp" << ',' << "start_num" << ',' << "num_timestamp" << ',' //记录车号,属性时间戳,用于比对定检期合并 << "end_num" << ',' << "start_pro" << ',' << "pro_timestamp" << ',' << "end_pro" << std::endl; } outFile << pTrain->iCarXH << ',' << pTrain->trainNum.strBestImg << ',' << pTrain->trainPro.strBestImg << ',' << pTrain->trainNum.strTrainType << ',' << pTrain->trainNum.strTrainNum << ',' << pTrain->trainPro.strLoad << ',' << pTrain->trainPro.strSelf << ',' << pTrain->trainPro.strVolume << ',' << pTrain->trainPro.strChange << ',' << pTrain->trainPro.strVolumeSurface << ',' << pTrain->trainNum.step1Location.fLTX << ',' << pTrain->trainNum.step1Location.fLTY << ',' << pTrain->trainNum.step1Location.fRBX << ',' << pTrain->trainNum.step1Location.fRBY << ',' << pTrain->trainPro.step1Location.fLTX << ',' << pTrain->trainPro.step1Location.fLTY << ',' << pTrain->trainPro.step1Location.fRBX << ',' << pTrain->trainPro.step1Location.fRBY << ',' << pTrain->iStartFrameId << ',' << pTrain->iEndFrameId << ',' << pTrain->i64StartTimeStamp << ',' << pTrain->i64TimeStamp << ',' << pTrain->i64EndTimeStamp << ',' << pTrain->trainNum.i64StartTimeStamp << ',' << pTrain->trainNum.i64TimeStamp << ',' << pTrain->trainNum.i64EndTimeStamp << ',' << pTrain->trainPro.i64StartTimeStamp << ',' << pTrain->trainPro.i64TimeStamp << ',' << pTrain->trainPro.i64EndTimeStamp << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " train savecsv fail!"; return false; } return true; } /** * 保存定检期的最优结果到CSV中 * inParam : std::shared_ptr pChkDate :定检期信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveChkDateCsv(std::shared_ptr pChkDate) { if (pChkDate->strBestImg.empty()) { LogDebug << "datetime:" << pChkDate->strTrainDate << " " << pChkDate->strTrainName << " carxh:" << pChkDate->iCarXH << " chkdate empty"; return true; } //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", pChkDate->iDataSource + 1); std::string strChkDatePath = strResultPath_ + pChkDate->strTrainDate + "/" + pChkDate->strTrainName + "/" + szCameraNo + "/"; if (!MyUtils::getins()->CreateDirPath(strChkDatePath)) { LogError << "iCarXH:" << pChkDate->iCarXH << "chkdate savecsv err"; return false; } //2. 保存csv std::string strCsvName = pChkDate->strTrainDate + pChkDate->strTrainName + "_" + szCameraNo + "_chkdate.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strChkDatePath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); // 打开模式可省略 if (!bIsExsit) { outFile << "car_xh" << ',' << "chkdate_name" << ',' << "chkdate1" << ',' << "chkdate2" << ',' << "chkdate_ltx" << ',' << "chkdate_lty" << ',' << "chkdate_rbx" << ',' << "chkdate_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "start_timestamp" << ',' << "end_timestamp" << ',' << "timestamp" << ',' << "chkdate1deadline" << std::endl; } outFile << pChkDate->iCarXH << ',' << pChkDate->strBestImg << ',' << pChkDate->strChkDate1 << ',' << pChkDate->strChkDate2 << ',' << pChkDate->step1Location.fLTX << ',' << pChkDate->step1Location.fLTY << ',' << pChkDate->step1Location.fRBX << ',' << pChkDate->step1Location.fRBY << ',' << pChkDate->iStartFrameId << ',' << pChkDate->iEndFrameId << ',' << pChkDate->i64StartTimeStamp << ',' << pChkDate->i64EndTimeStamp << ',' << pChkDate->i64TimeStamp << ',' << pChkDate->strChkDate1DeadLine << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " chkdate savecsv fail!"; return false; } return true; } /** * 保存集装箱的最优结果到CSV中 * inParam : std::shared_ptr pTrainContainer :集装箱信息 * outParam: * return : true/false */ bool SaveCsvEngine::SaveContainerCsv(std::shared_ptr pTrainContainer) { std::vector vecContainer; vecContainer.emplace_back(pTrainContainer->container1); vecContainer.emplace_back(pTrainContainer->container2); for (auto iter = vecContainer.begin(); iter != vecContainer.end(); iter++) { if (iter->strContainerNo.empty()) { continue; } // 1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/) char szCameraNo[4] = {0}; sprintf(szCameraNo, "%03d", iter->iDataSource + 1); std::string strContainerPath = strResultPath_ + iter->strTrainDate + "/" + iter->strTrainName + "/" + szCameraNo + "/"; if (!MyUtils::getins()->CreateDirPath(strContainerPath)) { LogError << "ContainerNo:" << iter->strContainerNo << " container savecsv err"; continue; } // 2. 保存csv std::string strCsvName = iter->strTrainDate + iter->strTrainName + "_" + szCameraNo + "_container.csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); std::string strCsvPath = strContainerPath + strCsvName; bool bIsExsit = false; if (access(strCsvPath.c_str(), F_OK) != -1) { bIsExsit = true; } try { // 写文件 std::ofstream outFile; outFile.open(strCsvPath, std::ios::app); if (!bIsExsit) { outFile << "datasource" << ',' << "container_name" << ',' << "containerNo" << ',' << "container_ltx" << ',' << "container_lty" << ',' << "container_rbx" << ',' << "container_rby" << ',' << "start_frameId" << ',' << "end_frameId" << ',' << "timestamp" << std::endl; } outFile << iter->iDataSource << ',' << iter->strBestImg << ',' << iter->strContainerNo << ',' << iter->step1Location.fLTX << ',' << iter->step1Location.fLTY << ',' << iter->step1Location.fRBX << ',' << iter->step1Location.fRBY << ',' << iter->iStartFrameId << ',' << iter->iEndFrameId << ',' << iter->i64TimeStamp << std::endl; outFile.close(); } catch (const std::exception &) { LogError << "strCsvPath:" << strCsvPath << " container savecsv fail!"; continue; } } return true; } APP_ERROR SaveCsvEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { bool bPopFlag = false; //pop端口0 车厢信息 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr != pVoidData0) { std::shared_ptr pTrain = std::static_pointer_cast(pVoidData0); if (pTrain->bMergerFlag) { SaveMergerCsv(pTrain); } else { SaveTrainCsv(pTrain); } bPopFlag = true; } //pop端口1 定检期信息 if (inputQueMap_.count(strPort1_) > 0) { std::shared_ptr pVoidData1 = nullptr; inputQueMap_[strPort1_]->pop(pVoidData1); if (nullptr != pVoidData1) { std::shared_ptr pChkDate = std::static_pointer_cast(pVoidData1); SaveChkDateCsv(pChkDate); bPopFlag = true; } } //pop端口2 集装箱信息 if (inputQueMap_.count(strPort2_) > 0) { std::shared_ptr pVoidData2 = nullptr; inputQueMap_[strPort2_]->pop(pVoidData2); if (nullptr != pVoidData2) { std::shared_ptr pTrainContainer = std::static_pointer_cast(pVoidData2); SaveContainerCsv(pTrainContainer); bPopFlag = true; } } if (!bPopFlag) { usleep(1000); continue; } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/SaveEngine/SaveImgEngine.cpp b/nvidia_ascend_engine/common_engine/SaveEngine/SaveImgEngine.cpp index 3569b64..887f1d2 100644 --- a/nvidia_ascend_engine/common_engine/SaveEngine/SaveImgEngine.cpp +++ b/nvidia_ascend_engine/common_engine/SaveEngine/SaveImgEngine.cpp @@ -45,10 +45,10 @@ APP_ERROR SaveImgEngine::Process() LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } - + vector compression_params; - compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg - compression_params.push_back(iPicQuality); //图片质量 + compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg + compression_params.push_back(iPicQuality); //图片质量 iDirection_ = DIRECTION_UNKNOWN; int iRet = APP_ERR_OK; @@ -61,7 +61,7 @@ APP_ERROR SaveImgEngine::Process() usleep(1000); continue; } - + std::shared_ptr pSaveImgData = std::static_pointer_cast(pvoidd); //如果设置了方向,则方向不对直接过滤,但结束帧不能过滤,需流转到后面Engine,保证后面处理正确。 @@ -113,13 +113,13 @@ APP_ERROR SaveImgEngine::Process() } // 3.保存图片 - + if (pSaveImgData->pData != nullptr && pSaveImgData->iSize != 0) { cv::Mat matBGR(pSaveImgData->iHeight, pSaveImgData->iWidth, CV_8UC3, static_cast(pSaveImgData->pData.get())); //RGB iWidth = pSaveImgData->iWidth; iHeight = pSaveImgData->iHeight; - + // cv::Mat mtOutImage; // cv::cvtColor(cvimg, mtOutImage, cv::COLOR_RGB2BGR); diff --git a/nvidia_ascend_engine/common_engine/SaveEngine/SaveStepOneResultEngine.cpp b/nvidia_ascend_engine/common_engine/SaveEngine/SaveStepOneResultEngine.cpp index 4c98c1b..c7dcff9 100644 --- a/nvidia_ascend_engine/common_engine/SaveEngine/SaveStepOneResultEngine.cpp +++ b/nvidia_ascend_engine/common_engine/SaveEngine/SaveStepOneResultEngine.cpp @@ -1,705 +1 @@ -#include "SaveStepOneResultEngine.h" - - -using namespace ai_matrix; - -SaveStepOneResultEngine::SaveStepOneResultEngine() {} - -SaveStepOneResultEngine::~SaveStepOneResultEngine() {} - -APP_ERROR SaveStepOneResultEngine::Init() -{ - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; - strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); - iSplitSpan_ = MyYaml::GetIns()->GetIntValue("partition_frame_span"); - iSplitSpanPX_ = MyYaml::GetIns()->GetIntValue("gc_split_frame_span_px"); - - dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); - - std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); - std::string delimiter(","); - for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) - { - int iCnt = 0; - std::vector vecSplit = MyUtils::getins()->split(iter->second.strTarget, delimiter); - for (auto iter = vecSplit.begin(); iter != vecSplit.end(); iter++) - { - if (*iter == "NUM") - { - iCnt++; - } - else if (*iter == "CHKDATE") - { - iCnt++; - } - else if (*iter == "CONTAINER" || *iter == "CONTAINER_T") - { - iCnt++; - } - } - mapInvokeModelCnt_[iter->first] = iCnt; - } - - InitParam(); - LogInfo << "SaveStepOneResultEngine Init ok"; - return APP_ERR_OK; -} - -APP_ERROR SaveStepOneResultEngine::DeInit() -{ - LogInfo << "SaveStepOneResultEngine DeInit ok"; - return APP_ERR_OK; -} - -/** -* 初始化参数信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SaveStepOneResultEngine::InitParam() -{ - iPushSpaceFrameId_ = 0; - i64TimeStampFirst_ = 0; - iDirection_ = DIRECTION_UNKNOWN; - bPushIsEnd_ = false; - vecParationInfo_.clear(); - std::vector().swap(vecParationInfo_); - bDealCenterFlag_ = false; - parationInfoLast_.i64EndTimeStamp = 0; - parationInfoLast_.modelSpaceFrame = 0; - parationInfoLast_.iRate = 0; - parationInfoLast_.bmodelconfirmed = false; - parationInfoLast_.fLTX = 0.0; - parationInfoLast_.fRBX = 0.0; - parationInfoLast_.strTrainDate = ""; - parationInfoLast_.strTrainName = ""; - parationInfoLast_.bIsEnd = false; - parationInfoLast_.nStatus = 0; - mapNumCenterInfo_.clear(); - mapProCenterInfo_.clear(); - bHaveHeadFlag_ = false; - headInfo_.iFrameId = 0; - headInfo_.fCenterX = 0; -} - -/** -* 构造车厢间隔信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SaveStepOneResultEngine::MakeParationInfo(PartionInfo ¶tionInfo, std::shared_ptr pProcessData, Json::Value &jvStep1Space) -{ - parationInfo.i64EndTimeStamp = pProcessData->i64TimeStamp; - parationInfo.modelSpaceFrame = pProcessData->iFrameId; - parationInfo.iRate = pProcessData->iRate; - parationInfo.bmodelconfirmed = true; - parationInfo.fLTX = jvStep1Space[0]["ltx"].asFloat(); - parationInfo.fRBX = jvStep1Space[0]["rbx"].asFloat(); - parationInfo.strTrainDate = pProcessData->strTrainDate; - parationInfo.strTrainName = pProcessData->strTrainName; - parationInfo.bIsEnd = pProcessData->bIsEnd; - parationInfo.nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); - parationInfoLast_ = parationInfo; -} - -/** -* 处理中心间隔信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SaveStepOneResultEngine::DealCenterSpace(std::vector &vecParationInfo, - std::shared_ptr pProcessData) -{ - int iVecSize = vecParationInfo.size(); - if (iVecSize < 0) - { - return; - } - LogDebug << "积累的车厢切分信息数:" << iVecSize << " 帧:" << pProcessData->iFrameId - << " 第一个车厢切分信息帧:" << vecParationInfo.at(0).modelSpaceFrame - << " 最后一个车厢切分信息帧:" << vecParationInfo.at(iVecSize - 1).modelSpaceFrame - << " 最后一个车厢切分信息是否为结束:" << vecParationInfo.at(iVecSize - 1).bIsEnd; - - /* - 因停车后再行驶未能及时判断出为行驶状态,导致更新间隔信息,出现漏切分车厢(具体原因分析见正通2023-02-28的问题分析记录) - 漏切分时vecParationInfo中保存的是两辆车的间隔信息,因此针对vecParationInfo做特殊处理,从此处切分出遗漏的车厢。 - */ - std::vector vecSpacePos; - for (int i = 1; i < iVecSize; i++) - { - int iCenterXPre = vecParationInfo[i - 1].fLTX + (vecParationInfo[i - 1].fRBX - vecParationInfo[i - 1].fLTX) / 2; - int iCenterX = vecParationInfo[i].fLTX + (vecParationInfo[i].fRBX - vecParationInfo[i].fLTX) / 2; - bool bIntervalFlag = ((int)(vecParationInfo[i].modelSpaceFrame - vecParationInfo[i - 1].modelSpaceFrame)) > iSplitSpan_; - LogDebug << "上一帧ID:" << vecParationInfo[i - 1].modelSpaceFrame << " 上一帧间隔X轴中线:" << iCenterXPre - << " 本帧ID:" << vecParationInfo[i].modelSpaceFrame << " 本帧间隔X轴中线:" << iCenterX - << " 满足帧间隔:" << bIntervalFlag << " i:" << i; - if (iDirection_ == DIRECTION_LEFT && (iCenterXPre < iCenterX - iSplitSpanPX_) && bIntervalFlag) - { - vecSpacePos.push_back(i - 1); - } - if (iDirection_ == DIRECTION_RIGHT && (iCenterXPre - iSplitSpanPX_ > iCenterX) && bIntervalFlag) - { - vecSpacePos.push_back(i - 1); - } - } - LogDebug << "vecSpacePos size:" << vecSpacePos.size(); - vecSpacePos.push_back(iVecSize - 1); - - /* - 如果集合中最后为列车结束帧,则表示停车在车厢间隔。这时用最后一个作为车厢划分帧。 - 其他场景使用靠近中心的间隔帧作为车厢划分帧 - */ - for (int iSpacePos = 0; iSpacePos < vecSpacePos.size(); iSpacePos++) - { - LogDebug << "index:" << vecSpacePos.at(iSpacePos) << " frameid:" << vecParationInfo[vecSpacePos.at(iSpacePos)].modelSpaceFrame; - std::shared_ptr pPartionInfo = std::make_shared(); - if (iSpacePos == vecSpacePos.size() - 1 && vecParationInfo[vecSpacePos.at(iSpacePos)].bIsEnd) - { - *pPartionInfo = vecParationInfo[vecSpacePos.at(iSpacePos)]; - } - else - { - int iPos = 0; - int iImageCenter = pProcessData->iWidth / 2; - int iToCenterXMin = iImageCenter; - int iBegin = (iSpacePos == 0 ? 0 : vecSpacePos.at(iSpacePos - 1) + 1); - for (int i = iBegin; i <= vecSpacePos.at(iSpacePos); i++) - { - int iCenterX = vecParationInfo[i].fLTX + (vecParationInfo[i].fRBX - vecParationInfo[i].fLTX) / 2; - if (iToCenterXMin > abs(iCenterX - iImageCenter)) - { - iToCenterXMin = abs(iCenterX - iImageCenter); - iPos = i; - } - } - *pPartionInfo = vecParationInfo[iPos]; - } - - //此处切分时,依据车号,属性判断是否有漏的车厢,如果有则依靠车号属性切分。 - SplitTrainByNumPro(pPartionInfo, pProcessData); - - pPartionInfo->fLTX = pPartionInfo->fLTX / (pProcessData->iWidth / METHOD_BASE_WIDTH); - pPartionInfo->fRBX = pPartionInfo->fRBX / (pProcessData->iWidth / METHOD_BASE_WIDTH); - if (iPushSpaceFrameId_ == 0) - { - pPartionInfo->i64StartTimeStamp = i64TimeStampFirst_; - pPartionInfo->startframe = dataSourceConfig_.iSkipInterval; - } - pPartionInfo->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); - - LogWarn << "--------- 向Paration 发送数据 --------"; - outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfo)); - - iPushSpaceFrameId_ = pPartionInfo->modelSpaceFrame; - bPushIsEnd_ = pPartionInfo->bIsEnd; - LogDebug << "pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfo->i64EndTimeStamp - << " ltx:" << pPartionInfo->fLTX << " rbx:" << pPartionInfo->fRBX - << " bPushIsEnd:" << bPushIsEnd_; - } - vecParationInfo.clear(); -} - -/** -* 处理车厢间隔 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SaveStepOneResultEngine::DealTrainSpaceInfo(std::shared_ptr pProcessData, Json::Value &jvStep1Space) -{ - /* - 无方向时,识别的内容都放入集合中。 - 有向时,按方向判断是否push车厢间隔框 - 向左行驶:帧间隔中心点小于画面1/3时,则处理车厢间隔集合。新车厢间隔必须大于上次车厢中心点再放入集合等待处理。 - 向右行驶:帧间隔中心点大于画面2/3时,则处理车厢间隔集合。新车厢间隔必须小于上次车厢中心点再放入集合等待处理。 - 注:最后一节不会再有帧间隔了,因此直接发送的结束帧,且坐标设置中心点。 - */ - if (jvStep1Space.size() <= 0 || pProcessData->iOrigFrameId < 50) - { - return; - } - - /* - 停车状态后不再放入信息到集合中,防止长时间停在间隔上导致集合持续增大。 - 停车状态且有间隔时需更新最后间隔框帧号。(防止在XXX帧停车且有间隔框,然后开始倒车再正向行驶,当再回到开始倒车的位置时,此时帧号为YYYY, - 会符合下面的partition_frame_span判断,导致bIntervalFlag为true而切分车厢) - */ - if (pProcessData->iStatus == TRAINSTATUS_STOP && !pProcessData->bIsEnd) - { - LogDebug << "status_stop parationInfoLast_:" << parationInfoLast_.modelSpaceFrame << " update by frameId:" << pProcessData->iFrameId; - parationInfoLast_.i64EndTimeStamp = pProcessData->i64TimeStamp; - parationInfoLast_.modelSpaceFrame = pProcessData->iFrameId; - return; - } - - if (iDirection_ == DIRECTION_UNKNOWN) - { - std::string strFilePath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/" + "direction.txt"; - Json::Value jvDirectionInfo; - if (MyUtils::getins()->ReadJsonInfo(jvDirectionInfo, strFilePath)) - { - iDirection_ = jvDirectionInfo["direction"].asInt(); - } - else - { - LogWarn << "暂未检测出行车方向"; - } - } - - bool bIntervalFlag = ((int)(pProcessData->iFrameId - parationInfoLast_.modelSpaceFrame)) > iSplitSpan_; - int iCenterCur = jvStep1Space[0]["ltx"].asFloat() + (jvStep1Space[0]["rbx"].asFloat() - jvStep1Space[0]["ltx"].asFloat()) / 2; - int iCenterLast = parationInfoLast_.fLTX + (parationInfoLast_.fRBX - parationInfoLast_.fLTX) / 2; - LogDebug << "当前帧:" << pProcessData->iFrameId << " 间隔框中心线:" << iCenterCur - << " 上一帧:" << parationInfoLast_.modelSpaceFrame << " 间隔框中心线:" << iCenterLast - << " 行车方向:" << iDirection_ << " 是否满足切分帧数:" << bIntervalFlag << " bDealCenterFlag_:" << bDealCenterFlag_; - - if (iDirection_ == DIRECTION_UNKNOWN || iCenterLast == 0) - { - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - vecParationInfo_.push_back(parationInfo); - } - else if (iDirection_ == DIRECTION_LEFT) - { - if (iCenterCur < (pProcessData->iWidth / 3)) - { - if (!bDealCenterFlag_) - { - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - vecParationInfo_.push_back(parationInfo); - DealCenterSpace(vecParationInfo_, pProcessData); - bDealCenterFlag_ = true; - } - //这需要替换parationInfoLast_, 确保parationInfoLast_是最靠左的一个间隔,但不需要加入集合 - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - } - else if ((iCenterLast < iCenterCur - iSplitSpanPX_) && bIntervalFlag) //该条件只会在新车间隔出来进入一次 - { - //防止上节车厢间隔框所有识别都大于画面的1/3,因此当前车厢间隔出来后也需处理下上节车厢间隔 - if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) - { - LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; - DealCenterSpace(vecParationInfo_, pProcessData); - } - - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - vecParationInfo_.push_back(parationInfo); - bDealCenterFlag_ = false; - } - else - { - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - //该条件是防止第一个XXX帧满足小于画面1/3后切割,后一帧XXX+1的中心点大于画面1/3导致的加入vec中出现的多切分现象。(向右增加30px的浮动) - if (!(bDealCenterFlag_ && !bIntervalFlag && (iCenterCur < (pProcessData->iWidth / 3 + 30)))) - { - vecParationInfo_.push_back(parationInfo); - } - } - } - else if (iDirection_ == DIRECTION_RIGHT) - { - if (iCenterCur > (pProcessData->iWidth / 3 * 2)) - { - if (!bDealCenterFlag_) - { - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - vecParationInfo_.push_back(parationInfo); - DealCenterSpace(vecParationInfo_, pProcessData); - bDealCenterFlag_ = true; - } - - //这需要替换parationInfoLast_, 确保parationInfoLast_是最靠右的一个间隔,但不需要加入集合 - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - } - else if ((iCenterLast - iSplitSpanPX_ > iCenterCur) && bIntervalFlag) //该条件只会在新车间隔出来进入一次 - { - //防止上节车厢间隔所有识别框都小于画面的2/3,因此当前车厢间隔出来后也需处理下上节车厢间隔 - if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) - { - LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; - DealCenterSpace(vecParationInfo_, pProcessData); - } - - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - vecParationInfo_.push_back(parationInfo); - bDealCenterFlag_ = false; - } - else - { - PartionInfo parationInfo; - MakeParationInfo(parationInfo, pProcessData, jvStep1Space); - //该条件是防止第一个XXX帧满足大于画面2/3后切割,后一帧XXX+1的中心点小于画面2/3导致的加入vec中出现的多切分现象。(向左增加30px的浮动) - if (!(bDealCenterFlag_ && !bIntervalFlag && (iCenterCur > (pProcessData->iWidth / 3 * 2 - 30)))) - { - vecParationInfo_.push_back(parationInfo); - } - } - } -} - -void SaveStepOneResultEngine::SplitTrainByNumPro(std::shared_ptr &pPartionInfo, std::shared_ptr &pProcessData) -{ - //向左行驶用车号位置,向右行驶用属性位置。 - std::map *pMapCenterInfoTemp_ = nullptr; - if (iDirection_ == DIRECTION_LEFT) - { - pMapCenterInfoTemp_ = &mapNumCenterInfo_; - mapProCenterInfo_.clear(); - } - else if (iDirection_ == DIRECTION_RIGHT) - { - pMapCenterInfoTemp_ = &mapProCenterInfo_; - mapNumCenterInfo_.clear(); - } - - if (pMapCenterInfoTemp_ == nullptr || pMapCenterInfoTemp_->size() <= 0) - { - return; - } - - LogDebug << "pPartionInfo->modelSpaceFrame:" << pPartionInfo->modelSpaceFrame << " mapsize:" << pMapCenterInfoTemp_->size(); - auto iter = pMapCenterInfoTemp_->begin(); - int iCenterXPre = iter->second; - uint32_t iFrameIdPre = iter->first; - bool bFlag = false; - uint32_t iSplitFrameId = 0; - while (++iter != pMapCenterInfoTemp_->end()) - { - bool bIntervalFlag = (int)(iter->first - iFrameIdPre) > iSplitSpan_; - LogDebug << "iFrameIdPre:" << iFrameIdPre << " iCenterXPre:" << iCenterXPre - << " iFrameid:" << iter->first << " iCenter:" << iter->second << " bIntervalFlag:" << bIntervalFlag; - if (iDirection_ == DIRECTION_LEFT && (iCenterXPre < iter->second - iSplitSpanPX_) && bIntervalFlag) - { - iSplitFrameId = iter->first; - bFlag = true; - } - if (iDirection_ == DIRECTION_RIGHT && (iCenterXPre - iSplitSpanPX_ > iter->second) && bIntervalFlag) - { - iSplitFrameId = iter->first; - //iSplitFrameId = iFrameIdPre; //向右行驶,从车号行驶到最右侧开始切分。 - bFlag = true; - } - - //比较完后,可更新前一帧数据 - iCenterXPre = iter->second; - iFrameIdPre = iter->first; - - if(bFlag) - { - if (iDirection_ == DIRECTION_LEFT && iter->second < (pProcessData->iWidth / 3)) - { - bFlag = false; - } - else if (iDirection_ == DIRECTION_RIGHT && iter->second > (pProcessData->iWidth / 3 * 2)) - { - bFlag = false; - } - if (!bFlag) - { - PartionInfo parationInfo; - std::shared_ptr pPartionInfoNew = std::make_shared(); - // pPartionInfoNew->i64EndTimeStamp = pProcessData->i64TimeStamp; - pPartionInfoNew->modelSpaceFrame = iSplitFrameId; - // parationInfo.iRate = pProcessData->iRate; - pPartionInfoNew->bmodelconfirmed = false; - // pPartionInfoNew->fLTX = jvStep1Space[0]["ltx"].asFloat(); - // pPartionInfoNew->fRBX = jvStep1Space[0]["rbx"].asFloat(); - pPartionInfoNew->strTrainDate = pProcessData->strTrainDate; - pPartionInfoNew->strTrainName = pProcessData->strTrainName; - pPartionInfoNew->bIsEnd = false; //**通过该函数切分的肯定不是最后一节 - pPartionInfoNew->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); - if (iPushSpaceFrameId_ == 0) - { - pPartionInfoNew->i64StartTimeStamp = i64TimeStampFirst_; - pPartionInfoNew->startframe = dataSourceConfig_.iSkipInterval; - } -// pPartionInfoNew->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); - - //构造一个间隔信息写入到切分帧中 - char szCameraNo[5] = {0}; - sprintf(szCameraNo, "%03d/", pProcessData->iDataSource + 1); - std::string strFilePath; - strFilePath = strResultPath_ + pProcessData->strOrigTrainDate + "/" + pProcessData->strOrigTrainName + "/" + - szCameraNo + std::to_string(iSplitFrameId) + ".txt"; - Json::Value jvFrameInfo; - MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFilePath); - Json::Value jvOneSpace; - jvOneSpace["classid"] = 18; - jvOneSpace["ltx"] = pMapCenterInfoTemp_->at(iSplitFrameId) + (iDirection_ == DIRECTION_LEFT ? -50 : 50); - jvOneSpace["lty"] = 0; - jvOneSpace["rbx"] = pMapCenterInfoTemp_->at(iSplitFrameId) + (iDirection_ == DIRECTION_LEFT ? -50 : 50); - jvOneSpace["rby"] = 0; - jvFrameInfo["step1Space"].append(jvOneSpace); - MyUtils::getins()->WriteJsonInfo(jvFrameInfo, strFilePath); - - LogWarn << "--------- 向Paration 发送数据 --------"; - outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfoNew)); - - iPushSpaceFrameId_ = pPartionInfoNew->modelSpaceFrame; - bPushIsEnd_ = pPartionInfoNew->bIsEnd; - LogDebug << "SplitTrainByNumPro pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfoNew->i64EndTimeStamp - << " ltx:" << pPartionInfoNew->fLTX << " rbx:" << pPartionInfoNew->fRBX - << " bPushIsEnd:" << bPushIsEnd_; - - while (pMapCenterInfoTemp_->size() > 0) - { - auto iterDel = pMapCenterInfoTemp_->begin(); - if(iterDel->first > iPushSpaceFrameId_) - { - break; - } - LogDebug << "erase iFrameId:" << iterDel->first; - pMapCenterInfoTemp_->erase(iterDel); - } - } - } - - if (iter->first >= pPartionInfo->modelSpaceFrame) - { - LogDebug << "frameid:"<< iter->first << " >= pPartionInfo->modelSpaceFrame:" << pPartionInfo->modelSpaceFrame << " break"; - break; - } - } - - while (pMapCenterInfoTemp_->size() > 0) - { - auto iterDel = pMapCenterInfoTemp_->begin(); - if (iterDel->first > pPartionInfo->modelSpaceFrame) - { - break; - } - LogDebug << "erase iFrameId:" << iterDel->first; - pMapCenterInfoTemp_->erase(iterDel); - } -} - -APP_ERROR SaveStepOneResultEngine::Process() -{ - int iRet = APP_ERR_OK; - while (!isStop_) - { - //pop端口0 - std::shared_ptr pVoidData0 = nullptr; - iRet = inputQueMap_[strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); - continue; - } - std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); - std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); - - if (pProcessData->iFrameId == dataSourceConfig_.iSkipInterval) - { - i64TimeStampFirst_ = pProcessData->i64TimeStamp; - } - - char szCameraNo[5] = {0}; - sprintf(szCameraNo, "%03d/", pProcessData->iDataSource + 1); - std::string strFilePath; - strFilePath = strResultPath_ + pProcessData->strOrigTrainDate + "/" + pProcessData->strOrigTrainName + "/" + - szCameraNo + std::to_string(pProcessData->iOrigFrameId) + ".txt"; - - - Json::Value jvStep1Num; - Json::Value jvStep1Pro; - Json::Value jvStep1ChkDate; - Json::Value jvStep1Container; - Json::Value jvStep1Space; - Json::Value jvStep1TrainSpace; - Json::Value jvStep1TopSpace; - for (int i = 0; i < pPostData->vecPostSubData.size(); i++) - { - PostSubData postSubData = pPostData->vecPostSubData[i]; - if (postSubData.vecSingleData.size() < 0) - { - continue; - } - - SingleData sdInfo = postSubData.vecSingleData.at(0); - Json::Value jvInfo; - jvInfo["classid"] = sdInfo.iClassId; - jvInfo["score"] = sdInfo.fScore; - jvInfo["clear"] = sdInfo.fClear; - jvInfo["ltx"] = sdInfo.fLTX; - jvInfo["lty"] = sdInfo.fLTY; - jvInfo["rbx"] = sdInfo.fRBX; - jvInfo["rby"] = sdInfo.fRBY; - float fCenter = sdInfo.fLTX + (sdInfo.fRBX - sdInfo.fLTX) / 2; - if (postSubData.iTargetType == NUM || postSubData.iTargetType == HEAD) - { - jvStep1Num.append(jvInfo); - if (pProcessData->iDataSource == 0 && pProcessData->iStatus != TRAINSTATUS_STOP) - { - if (postSubData.iTargetType != HEAD) - { - mapNumCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); - } - else - { - //车头没有属性,因此车头号也加入到属性中。保证向右行驶属性在前时最后2节的切分。 - //车头只加入一次,防止一个车头2个车头号的场景。但有两个车头且没识别车头间隔则无法处理。 - if (!bHaveHeadFlag_) - { - bool bIntervalFlag = ((int)(pProcessData->iFrameId - headInfo_.iFrameId) > iSplitSpan_ && headInfo_.iFrameId != 0); - - LogDebug << "frameid:" << pProcessData->iFrameId << " center:" << fCenter - << " preframeid:" << headInfo_.iFrameId << " precenter:" << headInfo_.fCenterX << " bIntervalFlag:" << bIntervalFlag; - if ((bIntervalFlag && abs((int)(headInfo_.fCenterX - fCenter)) > iSplitSpanPX_)) - { - bHaveHeadFlag_ = true; - } - else - { - headInfo_.fCenterX = fCenter; - headInfo_.iFrameId = pProcessData->iFrameId; - mapNumCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); - mapProCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); - } - } - } - } - } - else if (postSubData.iTargetType == PRO) - { - jvStep1Pro.append(jvInfo); - if (pProcessData->iDataSource == 0 && pProcessData->iStatus != TRAINSTATUS_STOP) - { - mapProCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); - } - } - else if (postSubData.iTargetType == CHKDATE) - { - jvStep1ChkDate.append(jvInfo); - } - else if (postSubData.iTargetType == CONTAINER) - { - jvStep1Container.append(jvInfo); - } - else if (postSubData.iTargetType == SPACE) - { - jvStep1Space.append(jvInfo); - } - else if (postSubData.iTargetType == TRAINSPACE) - { - jvStep1TrainSpace.append(jvInfo); - } - else if (postSubData.iTargetType == TOPSPACE) - { - jvStep1TopSpace.append(jvInfo); - } - } - - //先读取文本内容,追加新的信息后再写入 - Json::Value jvFrameInfo; - if (!MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFilePath)) - { - LogError << "read fail:" << strFilePath; - } - - if (jvStep1Num.size() > 0) - { - jvFrameInfo["step1Num"] = jvStep1Num; - } - if (jvStep1Pro.size() > 0) - { - jvFrameInfo["step1Pro"] = jvStep1Pro; - } - if (jvStep1ChkDate.size() > 0) - { - jvFrameInfo["step1ChkDate"] = jvStep1ChkDate; - } - if (jvStep1Container.size() > 0) - { - jvFrameInfo["step1Container"] = jvStep1Container; - } - if (jvStep1Space.size() > 0) - { - jvFrameInfo["step1Space"] = jvStep1Space; - } - if (jvStep1TrainSpace.size() > 0) - { - jvFrameInfo["step1TrainSpace"] = jvStep1TrainSpace; - if (jvStep1Space.size() <= 0) - { - jvFrameInfo["step1Space"] = jvStep1TrainSpace; - jvStep1Space = jvStep1TrainSpace; - } - } - if (jvStep1TopSpace.size() > 0) - { - jvFrameInfo["step1TopSpace"] = jvStep1TopSpace; - } - - int iInvokeModelCnt = jvFrameInfo["invokeModelCnt"].asInt(); - iInvokeModelCnt++; - jvFrameInfo["invokeModelCnt"] = iInvokeModelCnt; - if (mapInvokeModelCnt_[pProcessData->iDataSource] == iInvokeModelCnt) - { - jvFrameInfo["step1Finish"] = true; - } - jvFrameInfo["isEnd"] = (pProcessData->bIsEnd || jvFrameInfo["isEnd"].asBool()); - if (pProcessData->iStatus == TRAINSTATUS_STOP && pProcessData->iStatus != jvFrameInfo["status"].asInt()) - { - jvFrameInfo["status"] = pProcessData->iStatus; - } - MyUtils::getins()->WriteJsonInfo(jvFrameInfo, strFilePath); - //第一步处理结束后, push端口1,做复制图片文本数据和图片上传处理。 - if (jvFrameInfo["step1Finish"].asBool()) - { - iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast(pProcessData)); - } - - if (pProcessData->iDataSource == 0 && pPostData->iModelType == MODELTYPE_NUM) - { - DealTrainSpaceInfo(pProcessData, jvStep1Space); - - if (pProcessData->bIsEnd) - { - //最后一节处理下前一节信息 - if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) - { - LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; - DealCenterSpace(vecParationInfo_, pProcessData); - } - if (!bPushIsEnd_) - { - std::shared_ptr pPartionInfo = std::make_shared(); - pPartionInfo->iRate = pProcessData->iRate; - pPartionInfo->i64EndTimeStamp = pProcessData->i64TimeStamp; - pPartionInfo->modelSpaceFrame = pProcessData->iFrameId; - pPartionInfo->bmodelconfirmed = true; - pPartionInfo->strTrainDate = pProcessData->strTrainDate; - pPartionInfo->strTrainName = pProcessData->strTrainName; - pPartionInfo->bIsEnd = pProcessData->bIsEnd; - pPartionInfo->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); - - //最后一节和倒数第二节之间的间隔未能识别时,此时也需要通过车号属性切分下。 - SplitTrainByNumPro(pPartionInfo, pProcessData); - - LogWarn << "--------- 向Paration 发送数据 --------"; - outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfo)); - - iPushSpaceFrameId_ = pPartionInfo->modelSpaceFrame; - bPushIsEnd_ = pPartionInfo->bIsEnd; - LogDebug << "pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfo->i64EndTimeStamp - << " ltx:" << pPartionInfo->fLTX << " rbx:" << pPartionInfo->fRBX - << " bPushIsEnd:" << bPushIsEnd_; - } - InitParam(); - } - } - } - return APP_ERR_OK; -} +#include "SaveStepOneResultEngine.h" using namespace ai_matrix; SaveStepOneResultEngine::SaveStepOneResultEngine() {} SaveStepOneResultEngine::~SaveStepOneResultEngine() {} APP_ERROR SaveStepOneResultEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); iSplitSpan_ = MyYaml::GetIns()->GetIntValue("partition_frame_span"); iSplitSpanPX_ = MyYaml::GetIns()->GetIntValue("gc_split_frame_span_px"); dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); std::string delimiter(","); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { int iCnt = 0; std::vector vecSplit = MyUtils::getins()->split(iter->second.strTarget, delimiter); for (auto iter = vecSplit.begin(); iter != vecSplit.end(); iter++) { if (*iter == "NUM") { iCnt++; } else if (*iter == "CHKDATE") { iCnt++; } else if (*iter == "CONTAINER" || *iter == "CONTAINER_T") { iCnt++; } } mapInvokeModelCnt_[iter->first] = iCnt; } InitParam(); LogInfo << "SaveStepOneResultEngine Init ok"; return APP_ERR_OK; } APP_ERROR SaveStepOneResultEngine::DeInit() { LogInfo << "SaveStepOneResultEngine DeInit ok"; return APP_ERR_OK; } /** * 初始化参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void SaveStepOneResultEngine::InitParam() { iPushSpaceFrameId_ = 0; i64TimeStampFirst_ = 0; iDirection_ = DIRECTION_UNKNOWN; bPushIsEnd_ = false; vecParationInfo_.clear(); std::vector().swap(vecParationInfo_); bDealCenterFlag_ = false; parationInfoLast_.i64EndTimeStamp = 0; parationInfoLast_.modelSpaceFrame = 0; parationInfoLast_.iRate = 0; parationInfoLast_.bmodelconfirmed = false; parationInfoLast_.fLTX = 0.0; parationInfoLast_.fRBX = 0.0; parationInfoLast_.strTrainDate = ""; parationInfoLast_.strTrainName = ""; parationInfoLast_.bIsEnd = false; parationInfoLast_.nStatus = 0; mapNumCenterInfo_.clear(); mapProCenterInfo_.clear(); bHaveHeadFlag_ = false; headInfo_.iFrameId = 0; headInfo_.fCenterX = 0; } /** * 构造车厢间隔信息 * inParam : N/A * outParam: N/A * return : N/A */ void SaveStepOneResultEngine::MakeParationInfo(PartionInfo ¶tionInfo, std::shared_ptr pProcessData, Json::Value &jvStep1Space) { parationInfo.i64EndTimeStamp = pProcessData->i64TimeStamp; parationInfo.modelSpaceFrame = pProcessData->iFrameId; parationInfo.iRate = pProcessData->iRate; parationInfo.bmodelconfirmed = true; parationInfo.fLTX = jvStep1Space[0]["ltx"].asFloat(); parationInfo.fRBX = jvStep1Space[0]["rbx"].asFloat(); parationInfo.strTrainDate = pProcessData->strTrainDate; parationInfo.strTrainName = pProcessData->strTrainName; parationInfo.bIsEnd = pProcessData->bIsEnd; parationInfo.nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); parationInfoLast_ = parationInfo; } /** * 处理中心间隔信息 * inParam : N/A * outParam: N/A * return : N/A */ void SaveStepOneResultEngine::DealCenterSpace(std::vector &vecParationInfo, std::shared_ptr pProcessData) { int iVecSize = vecParationInfo.size(); if (iVecSize < 0) { return; } LogDebug << "积累的车厢切分信息数:" << iVecSize << " 帧:" << pProcessData->iFrameId << " 第一个车厢切分信息帧:" << vecParationInfo.at(0).modelSpaceFrame << " 最后一个车厢切分信息帧:" << vecParationInfo.at(iVecSize - 1).modelSpaceFrame << " 最后一个车厢切分信息是否为结束:" << vecParationInfo.at(iVecSize - 1).bIsEnd; /* 因停车后再行驶未能及时判断出为行驶状态,导致更新间隔信息,出现漏切分车厢(具体原因分析见正通2023-02-28的问题分析记录) 漏切分时vecParationInfo中保存的是两辆车的间隔信息,因此针对vecParationInfo做特殊处理,从此处切分出遗漏的车厢。 */ std::vector vecSpacePos; for (int i = 1; i < iVecSize; i++) { int iCenterXPre = vecParationInfo[i - 1].fLTX + (vecParationInfo[i - 1].fRBX - vecParationInfo[i - 1].fLTX) / 2; int iCenterX = vecParationInfo[i].fLTX + (vecParationInfo[i].fRBX - vecParationInfo[i].fLTX) / 2; bool bIntervalFlag = ((int)(vecParationInfo[i].modelSpaceFrame - vecParationInfo[i - 1].modelSpaceFrame)) > iSplitSpan_; LogDebug << "上一帧ID:" << vecParationInfo[i - 1].modelSpaceFrame << " 上一帧间隔X轴中线:" << iCenterXPre << " 本帧ID:" << vecParationInfo[i].modelSpaceFrame << " 本帧间隔X轴中线:" << iCenterX << " 满足帧间隔:" << bIntervalFlag << " i:" << i; if (iDirection_ == DIRECTION_LEFT && (iCenterXPre < iCenterX - iSplitSpanPX_) && bIntervalFlag) { vecSpacePos.push_back(i - 1); } if (iDirection_ == DIRECTION_RIGHT && (iCenterXPre - iSplitSpanPX_ > iCenterX) && bIntervalFlag) { vecSpacePos.push_back(i - 1); } } LogDebug << "vecSpacePos size:" << vecSpacePos.size(); vecSpacePos.push_back(iVecSize - 1); /* 如果集合中最后为列车结束帧,则表示停车在车厢间隔。这时用最后一个作为车厢划分帧。 其他场景使用靠近中心的间隔帧作为车厢划分帧 */ for (int iSpacePos = 0; iSpacePos < vecSpacePos.size(); iSpacePos++) { LogDebug << "index:" << vecSpacePos.at(iSpacePos) << " frameid:" << vecParationInfo[vecSpacePos.at(iSpacePos)].modelSpaceFrame; std::shared_ptr pPartionInfo = std::make_shared(); if (iSpacePos == vecSpacePos.size() - 1 && vecParationInfo[vecSpacePos.at(iSpacePos)].bIsEnd) { *pPartionInfo = vecParationInfo[vecSpacePos.at(iSpacePos)]; } else { int iPos = 0; int iImageCenter = pProcessData->iWidth / 2; int iToCenterXMin = iImageCenter; int iBegin = (iSpacePos == 0 ? 0 : vecSpacePos.at(iSpacePos - 1) + 1); for (int i = iBegin; i <= vecSpacePos.at(iSpacePos); i++) { int iCenterX = vecParationInfo[i].fLTX + (vecParationInfo[i].fRBX - vecParationInfo[i].fLTX) / 2; if (iToCenterXMin > abs(iCenterX - iImageCenter)) { iToCenterXMin = abs(iCenterX - iImageCenter); iPos = i; } } *pPartionInfo = vecParationInfo[iPos]; } //此处切分时,依据车号,属性判断是否有漏的车厢,如果有则依靠车号属性切分。 SplitTrainByNumPro(pPartionInfo, pProcessData); pPartionInfo->fLTX = pPartionInfo->fLTX / (pProcessData->iWidth / METHOD_BASE_WIDTH); pPartionInfo->fRBX = pPartionInfo->fRBX / (pProcessData->iWidth / METHOD_BASE_WIDTH); if (iPushSpaceFrameId_ == 0) { pPartionInfo->i64StartTimeStamp = i64TimeStampFirst_; pPartionInfo->startframe = dataSourceConfig_.iSkipInterval; } pPartionInfo->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); LogWarn << "--------- 向Paration 发送数据 --------"; outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfo)); iPushSpaceFrameId_ = pPartionInfo->modelSpaceFrame; bPushIsEnd_ = pPartionInfo->bIsEnd; LogDebug << "pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfo->i64EndTimeStamp << " ltx:" << pPartionInfo->fLTX << " rbx:" << pPartionInfo->fRBX << " bPushIsEnd:" << bPushIsEnd_; } vecParationInfo.clear(); } /** * 处理车厢间隔 * inParam : N/A * outParam: N/A * return : N/A */ void SaveStepOneResultEngine::DealTrainSpaceInfo(std::shared_ptr pProcessData, Json::Value &jvStep1Space) { /* 无方向时,识别的内容都放入集合中。 有向时,按方向判断是否push车厢间隔框 向左行驶:帧间隔中心点小于画面1/3时,则处理车厢间隔集合。新车厢间隔必须大于上次车厢中心点再放入集合等待处理。 向右行驶:帧间隔中心点大于画面2/3时,则处理车厢间隔集合。新车厢间隔必须小于上次车厢中心点再放入集合等待处理。 注:最后一节不会再有帧间隔了,因此直接发送的结束帧,且坐标设置中心点。 */ if (jvStep1Space.size() <= 0 || pProcessData->iOrigFrameId < 50) { return; } /* 停车状态后不再放入信息到集合中,防止长时间停在间隔上导致集合持续增大。 停车状态且有间隔时需更新最后间隔框帧号。(防止在XXX帧停车且有间隔框,然后开始倒车再正向行驶,当再回到开始倒车的位置时,此时帧号为YYYY, 会符合下面的partition_frame_span判断,导致bIntervalFlag为true而切分车厢) */ if (pProcessData->iStatus == TRAINSTATUS_STOP && !pProcessData->bIsEnd) { // LogDebug << "status_stop parationInfoLast_:" << parationInfoLast_.modelSpaceFrame << " update by frameId:" << pProcessData->iFrameId; parationInfoLast_.i64EndTimeStamp = pProcessData->i64TimeStamp; parationInfoLast_.modelSpaceFrame = pProcessData->iFrameId; return; } if (iDirection_ == DIRECTION_UNKNOWN) { std::string strFilePath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/" + "direction.txt"; Json::Value jvDirectionInfo; if (MyUtils::getins()->ReadJsonInfo(jvDirectionInfo, strFilePath)) { iDirection_ = jvDirectionInfo["direction"].asInt(); } else { LogWarn << "暂未检测出行车方向"; } } bool bIntervalFlag = ((int)(pProcessData->iFrameId - parationInfoLast_.modelSpaceFrame)) > iSplitSpan_; int iCenterCur = jvStep1Space[0]["ltx"].asFloat() + (jvStep1Space[0]["rbx"].asFloat() - jvStep1Space[0]["ltx"].asFloat()) / 2; int iCenterLast = parationInfoLast_.fLTX + (parationInfoLast_.fRBX - parationInfoLast_.fLTX) / 2; LogDebug << "当前帧:" << pProcessData->iFrameId << " 间隔框中心线:" << iCenterCur << " 上一帧:" << parationInfoLast_.modelSpaceFrame << " 间隔框中心线:" << iCenterLast << " 行车方向:" << iDirection_ << " 是否满足切分帧数:" << bIntervalFlag << " bDealCenterFlag_:" << bDealCenterFlag_; if (iDirection_ == DIRECTION_UNKNOWN || iCenterLast == 0) { PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); vecParationInfo_.push_back(parationInfo); } else if (iDirection_ == DIRECTION_LEFT) { if (iCenterCur < (pProcessData->iWidth / 3)) { if (!bDealCenterFlag_) { PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); vecParationInfo_.push_back(parationInfo); DealCenterSpace(vecParationInfo_, pProcessData); bDealCenterFlag_ = true; } //这需要替换parationInfoLast_, 确保parationInfoLast_是最靠左的一个间隔,但不需要加入集合 PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); } else if ((iCenterLast < iCenterCur - iSplitSpanPX_) && bIntervalFlag) //该条件只会在新车间隔出来进入一次 { //防止上节车厢间隔框所有识别都大于画面的1/3,因此当前车厢间隔出来后也需处理下上节车厢间隔 if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) { LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; DealCenterSpace(vecParationInfo_, pProcessData); } PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); vecParationInfo_.push_back(parationInfo); bDealCenterFlag_ = false; } else { PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); //该条件是防止第一个XXX帧满足小于画面1/3后切割,后一帧XXX+1的中心点大于画面1/3导致的加入vec中出现的多切分现象。(向右增加30px的浮动,因为大框可能不是同一种) if (!(bDealCenterFlag_ && !bIntervalFlag && (iCenterCur < (pProcessData->iWidth / 3 + 80)))) { vecParationInfo_.push_back(parationInfo); } } } else if (iDirection_ == DIRECTION_RIGHT) { if (iCenterCur > (pProcessData->iWidth / 3 * 2)) { if (!bDealCenterFlag_) { PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); vecParationInfo_.push_back(parationInfo); DealCenterSpace(vecParationInfo_, pProcessData); bDealCenterFlag_ = true; } //这需要替换parationInfoLast_, 确保parationInfoLast_是最靠右的一个间隔,但不需要加入集合 PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); } else if ((iCenterLast - iSplitSpanPX_ > iCenterCur) && bIntervalFlag) //该条件只会在新车间隔出来进入一次 { //防止上节车厢间隔所有识别框都小于画面的2/3,因此当前车厢间隔出来后也需处理下上节车厢间隔 if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) { LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; DealCenterSpace(vecParationInfo_, pProcessData); } PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); vecParationInfo_.push_back(parationInfo); bDealCenterFlag_ = false; } else { PartionInfo parationInfo; MakeParationInfo(parationInfo, pProcessData, jvStep1Space); //该条件是防止第一个XXX帧满足大于画面2/3后切割,后一帧XXX+1的中心点小于画面2/3导致的加入vec中出现的多切分现象。(向左增加80px的浮动因为大框可能不是同一种) if (!(bDealCenterFlag_ && !bIntervalFlag && (iCenterCur > (pProcessData->iWidth / 3 * 2 - 80)))) { vecParationInfo_.push_back(parationInfo); } } } } void SaveStepOneResultEngine::SplitTrainByNumPro(std::shared_ptr &pPartionInfo, std::shared_ptr &pProcessData) { //向左行驶用车号位置,向右行驶用属性位置。 std::map *pMapCenterInfoTemp_ = nullptr; if (iDirection_ == DIRECTION_LEFT) { pMapCenterInfoTemp_ = &mapNumCenterInfo_; mapProCenterInfo_.clear(); } else if (iDirection_ == DIRECTION_RIGHT) { pMapCenterInfoTemp_ = &mapProCenterInfo_; mapNumCenterInfo_.clear(); } if (pMapCenterInfoTemp_ == nullptr || pMapCenterInfoTemp_->size() <= 0) { return; } LogDebug << "pPartionInfo->modelSpaceFrame:" << pPartionInfo->modelSpaceFrame << " mapsize:" << pMapCenterInfoTemp_->size(); auto iter = pMapCenterInfoTemp_->begin(); int iCenterXPre = iter->second; uint32_t iFrameIdPre = iter->first; bool bFlag = false; uint32_t iSplitFrameId = 0; while (++iter != pMapCenterInfoTemp_->end()) { bool bIntervalFlag = (int)(iter->first - iFrameIdPre) > iSplitSpan_; LogDebug << "iFrameIdPre:" << iFrameIdPre << " iCenterXPre:" << iCenterXPre << " iFrameid:" << iter->first << " iCenter:" << iter->second << " bIntervalFlag:" << bIntervalFlag; if (iDirection_ == DIRECTION_LEFT && (iCenterXPre < iter->second - iSplitSpanPX_) && bIntervalFlag) { iSplitFrameId = iter->first; bFlag = true; } if (iDirection_ == DIRECTION_RIGHT && (iCenterXPre - iSplitSpanPX_ > iter->second) && bIntervalFlag) { iSplitFrameId = iter->first; //iSplitFrameId = iFrameIdPre; //向右行驶,从车号行驶到最右侧开始切分。 bFlag = true; } //比较完后,可更新前一帧数据 iCenterXPre = iter->second; iFrameIdPre = iter->first; if(bFlag) { if (iDirection_ == DIRECTION_LEFT && iter->second < (pProcessData->iWidth / 3)) { bFlag = false; } else if (iDirection_ == DIRECTION_RIGHT && iter->second > (pProcessData->iWidth / 3 * 2)) { bFlag = false; } if (!bFlag) { PartionInfo parationInfo; std::shared_ptr pPartionInfoNew = std::make_shared(); // pPartionInfoNew->i64EndTimeStamp = pProcessData->i64TimeStamp; pPartionInfoNew->modelSpaceFrame = iSplitFrameId; // parationInfo.iRate = pProcessData->iRate; pPartionInfoNew->bmodelconfirmed = false; // pPartionInfoNew->fLTX = jvStep1Space[0]["ltx"].asFloat(); // pPartionInfoNew->fRBX = jvStep1Space[0]["rbx"].asFloat(); pPartionInfoNew->strTrainDate = pProcessData->strTrainDate; pPartionInfoNew->strTrainName = pProcessData->strTrainName; pPartionInfoNew->bIsEnd = false; //**通过该函数切分的肯定不是最后一节 pPartionInfoNew->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); if (iPushSpaceFrameId_ == 0) { pPartionInfoNew->i64StartTimeStamp = i64TimeStampFirst_; pPartionInfoNew->startframe = dataSourceConfig_.iSkipInterval; } // pPartionInfoNew->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); //构造一个间隔信息写入到切分帧中 char szCameraNo[5] = {0}; sprintf(szCameraNo, "%03d/", pProcessData->iDataSource + 1); std::string strFilePath; strFilePath = strResultPath_ + pProcessData->strOrigTrainDate + "/" + pProcessData->strOrigTrainName + "/" + szCameraNo + std::to_string(iSplitFrameId) + ".txt"; Json::Value jvFrameInfo; MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFilePath); Json::Value jvOneSpace; jvOneSpace["classid"] = 18; jvOneSpace["ltx"] = pMapCenterInfoTemp_->at(iSplitFrameId) + (iDirection_ == DIRECTION_LEFT ? -50 : 50); jvOneSpace["lty"] = 0; jvOneSpace["rbx"] = pMapCenterInfoTemp_->at(iSplitFrameId) + (iDirection_ == DIRECTION_LEFT ? -50 : 50); jvOneSpace["rby"] = 0; jvFrameInfo["step1Space"].append(jvOneSpace); MyUtils::getins()->WriteJsonInfo(jvFrameInfo, strFilePath); LogWarn << "--------- 向Paration 发送数据 --------"; outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfoNew)); iPushSpaceFrameId_ = pPartionInfoNew->modelSpaceFrame; bPushIsEnd_ = pPartionInfoNew->bIsEnd; LogDebug << "SplitTrainByNumPro pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfoNew->i64EndTimeStamp << " ltx:" << pPartionInfoNew->fLTX << " rbx:" << pPartionInfoNew->fRBX << " bPushIsEnd:" << bPushIsEnd_; while (pMapCenterInfoTemp_->size() > 0) { auto iterDel = pMapCenterInfoTemp_->begin(); if(iterDel->first > iPushSpaceFrameId_) { break; } LogDebug << "erase iFrameId:" << iterDel->first; pMapCenterInfoTemp_->erase(iterDel); } } } if (iter->first >= pPartionInfo->modelSpaceFrame) { LogDebug << "frameid:"<< iter->first << " >= pPartionInfo->modelSpaceFrame:" << pPartionInfo->modelSpaceFrame << " break"; break; } } while (pMapCenterInfoTemp_->size() > 0) { auto iterDel = pMapCenterInfoTemp_->begin(); if (iterDel->first > pPartionInfo->modelSpaceFrame) { break; } LogDebug << "erase iFrameId:" << iterDel->first; pMapCenterInfoTemp_->erase(iterDel); } } APP_ERROR SaveStepOneResultEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { //pop端口0 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); if (pProcessData->iFrameId == dataSourceConfig_.iSkipInterval) { i64TimeStampFirst_ = pProcessData->i64TimeStamp; } char szCameraNo[5] = {0}; sprintf(szCameraNo, "%03d/", pProcessData->iDataSource + 1); std::string strFilePath; strFilePath = strResultPath_ + pProcessData->strOrigTrainDate + "/" + pProcessData->strOrigTrainName + "/" + szCameraNo + std::to_string(pProcessData->iOrigFrameId) + ".txt"; Json::Value jvStep1Num; Json::Value jvStep1Pro; Json::Value jvStep1ChkDate; Json::Value jvStep1Container; Json::Value jvStep1Space; Json::Value jvStep1TrainSpace; Json::Value jvStep1TopSpace; for (int i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubData = pPostData->vecPostSubData[i]; if (postSubData.vecSingleData.size() < 0) { continue; } SingleData sdInfo = postSubData.vecSingleData.at(0); Json::Value jvInfo; jvInfo["classid"] = sdInfo.iClassId; jvInfo["score"] = sdInfo.fScore; jvInfo["clear"] = sdInfo.fClear; jvInfo["ltx"] = sdInfo.fLTX; jvInfo["lty"] = sdInfo.fLTY; jvInfo["rbx"] = sdInfo.fRBX; jvInfo["rby"] = sdInfo.fRBY; float fCenter = sdInfo.fLTX + (sdInfo.fRBX - sdInfo.fLTX) / 2; if (postSubData.iTargetType == NUM || postSubData.iTargetType == HEAD) { jvStep1Num.append(jvInfo); if (pProcessData->iDataSource == 0 && pProcessData->iStatus != TRAINSTATUS_STOP) { if (postSubData.iTargetType != HEAD) { mapNumCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); } else { //车头没有属性,因此车头号也加入到属性中。保证向右行驶属性在前时最后2节的切分。 //车头只加入一次,防止一个车头2个车头号的场景。但有两个车头且没识别车头间隔则无法处理。 if (!bHaveHeadFlag_) { bool bIntervalFlag = ((int)(pProcessData->iFrameId - headInfo_.iFrameId) > iSplitSpan_ && headInfo_.iFrameId != 0); LogDebug << "frameid:" << pProcessData->iFrameId << " center:" << fCenter << " preframeid:" << headInfo_.iFrameId << " precenter:" << headInfo_.fCenterX << " bIntervalFlag:" << bIntervalFlag; if ((bIntervalFlag && abs((int)(headInfo_.fCenterX - fCenter)) > iSplitSpanPX_)) { bHaveHeadFlag_ = true; } else { headInfo_.fCenterX = fCenter; headInfo_.iFrameId = pProcessData->iFrameId; mapNumCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); mapProCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); } } } } } else if (postSubData.iTargetType == PRO) { jvStep1Pro.append(jvInfo); if (pProcessData->iDataSource == 0 && pProcessData->iStatus != TRAINSTATUS_STOP) { mapProCenterInfo_.insert(std::make_pair(pProcessData->iFrameId, fCenter)); } } else if (postSubData.iTargetType == CHKDATE) { jvStep1ChkDate.append(jvInfo); } else if (postSubData.iTargetType == CONTAINER) { jvStep1Container.append(jvInfo); } else if (postSubData.iTargetType == SPACE) { jvStep1Space.append(jvInfo); } else if (postSubData.iTargetType == TRAINSPACE) { jvStep1TrainSpace.append(jvInfo); } else if (postSubData.iTargetType == TOPSPACE) { jvStep1TopSpace.append(jvInfo); } } //先读取文本内容,追加新的信息后再写入 Json::Value jvFrameInfo; if (!MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFilePath)) { LogError << "read fail:" << strFilePath; } if (jvStep1Num.size() > 0) { jvFrameInfo["step1Num"] = jvStep1Num; } if (jvStep1Pro.size() > 0) { jvFrameInfo["step1Pro"] = jvStep1Pro; } if (jvStep1ChkDate.size() > 0) { jvFrameInfo["step1ChkDate"] = jvStep1ChkDate; } if (jvStep1Container.size() > 0) { jvFrameInfo["step1Container"] = jvStep1Container; } if (jvStep1Space.size() > 0) { jvFrameInfo["step1Space"] = jvStep1Space; } if (jvStep1TrainSpace.size() > 0) { jvFrameInfo["step1TrainSpace"] = jvStep1TrainSpace; if (jvStep1Space.size() <= 0) { jvFrameInfo["step1Space"] = jvStep1TrainSpace; jvStep1Space = jvStep1TrainSpace; } } if (jvStep1TopSpace.size() > 0) { jvFrameInfo["step1TopSpace"] = jvStep1TopSpace; } int iInvokeModelCnt = jvFrameInfo["invokeModelCnt"].asInt(); iInvokeModelCnt++; jvFrameInfo["invokeModelCnt"] = iInvokeModelCnt; if (mapInvokeModelCnt_[pProcessData->iDataSource] == iInvokeModelCnt) { jvFrameInfo["step1Finish"] = true; } jvFrameInfo["isEnd"] = (pProcessData->bIsEnd || jvFrameInfo["isEnd"].asBool()); if (pProcessData->iStatus == TRAINSTATUS_STOP && pProcessData->iStatus != jvFrameInfo["status"].asInt()) { jvFrameInfo["status"] = pProcessData->iStatus; } MyUtils::getins()->WriteJsonInfo(jvFrameInfo, strFilePath); //第一步处理结束后, push端口1,做复制图片文本数据和图片上传处理。 if (jvFrameInfo["step1Finish"].asBool()) { iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast(pProcessData)); } if (pProcessData->iDataSource == 0 && pPostData->iModelType == MODELTYPE_NUM) { DealTrainSpaceInfo(pProcessData, jvStep1Space); if (pProcessData->bIsEnd) { //最后一节处理下前一节信息 if (!bDealCenterFlag_ && vecParationInfo_.size() > 0) { LogDebug << "lastFrameid:" << vecParationInfo_[0].modelSpaceFrame << " frameid:" << pProcessData->iFrameId; DealCenterSpace(vecParationInfo_, pProcessData); } if (!bPushIsEnd_) { std::shared_ptr pPartionInfo = std::make_shared(); pPartionInfo->iRate = pProcessData->iRate; pPartionInfo->i64EndTimeStamp = pProcessData->i64TimeStamp; pPartionInfo->modelSpaceFrame = pProcessData->iFrameId; pPartionInfo->bmodelconfirmed = true; pPartionInfo->strTrainDate = pProcessData->strTrainDate; pPartionInfo->strTrainName = pProcessData->strTrainName; pPartionInfo->bIsEnd = pProcessData->bIsEnd; pPartionInfo->nStatus = ((pProcessData->iStatus == TRAINSTATUS_STOP) ? TRAIN_PAUSE : iDirection_); //最后一节和倒数第二节之间的间隔未能识别时,此时也需要通过车号属性切分下。 SplitTrainByNumPro(pPartionInfo, pProcessData); LogWarn << "--------- 向Paration 发送数据 --------"; outputQueMap_[strPort0_]->push(std::static_pointer_cast(pPartionInfo)); iPushSpaceFrameId_ = pPartionInfo->modelSpaceFrame; bPushIsEnd_ = pPartionInfo->bIsEnd; LogDebug << "pushSpaceFrameId:" << iPushSpaceFrameId_ << " timeStamp:" << pPartionInfo->i64EndTimeStamp << " ltx:" << pPartionInfo->fLTX << " rbx:" << pPartionInfo->fRBX << " bPushIsEnd:" << bPushIsEnd_; } InitParam(); } } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/SelectBestEngine/SelectBestEngine.cpp b/nvidia_ascend_engine/common_engine/SelectBestEngine/SelectBestEngine.cpp index 085783c..22e0173 100644 --- a/nvidia_ascend_engine/common_engine/SelectBestEngine/SelectBestEngine.cpp +++ b/nvidia_ascend_engine/common_engine/SelectBestEngine/SelectBestEngine.cpp @@ -1,765 +1 @@ -#include "SelectBestEngine.h" -#include "myutils.h" - -using namespace ai_matrix; - -SelectBestEngine::SelectBestEngine() {} - -SelectBestEngine::~SelectBestEngine() {} - -APP_ERROR SelectBestEngine::Init() -{ - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; - iSelectBestMode_ = MyYaml::GetIns()->GetIntValue("gc_select_best_mode"); - strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); - strBestPath_ = MyYaml::GetIns()->GetPathValue("gc_best_path"); - - //获取几个摄像头识别车号 - std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); - for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) - { - if (iter->second.strTarget.find("NUM") != std::string::npos) - { - mapDataSourceIsEnd_[iter->first] = false; - } - } - - InitParam(); - LogInfo << "SelectBestEngine Init ok"; - return APP_ERR_OK; -} - -APP_ERROR SelectBestEngine::DeInit() -{ - LogInfo << "SelectBestEngine DeInit ok"; - return APP_ERR_OK; -} - -/** -* push数据到队列,队列满时则休眠一段时间再push -* inParam : const std::string strPort push的端口 - : const std::shared_ptr &pTrain push的数据 -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::PushData(const std::string &strPort, const std::shared_ptr &pTrain) -{ - while (true) - { - int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pTrain)); - if (iRet != 0) - { - LogDebug << "num:" << pTrain->trainNum.strTrainNum << " push fail iRet:" << iRet; - if (iRet == 2) - { - usleep(10000); // 10ms - continue; - } - } - break; - } -} - -/** -* 初始化车号参数信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::InitNumParam() -{ - mapTrainTypeId_.clear(); - mapNumInfo_.clear(); - strBestNumImg_ = ""; - i64TimeStampNum_ = 0; - fMaxScoreSumNum_ = 0; - memset(&step1LocationBestNum_, 0, sizeof(step1LocationBestNum_)); - iDataSourceNum_ = 0; -} - -/** -* 初始化属性参数信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::InitProParam() -{ - mapProInfo_.clear(); - strBestProImg_ = ""; - i64TimeStampPro_ = 0; - fMaxScoreSumPro_ = 0; - memset(&step1LocationBestPro_, 0, sizeof(step1LocationBestPro_)); - iDataSourcePro_ = 0; -} - -/** -* 初始化车号参数信息(只有车结束调用) -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::InitHeadParam() -{ - mapHeadInfo_.clear(); - strBestHeadImg_ = ""; - i64TimeStampHead_ = 0; - fMaxScoreSumHead_ = 0; - memset(&step1LocationBestHead_, 0, sizeof(step1LocationBestHead_)); - iDataSourceHead_ = 0; -} - -/** -* 初始化参数信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::InitParam() -{ - iNumIndex_ = 1; - iProIndex_ = 1; - InitNumParam(); - InitProParam(); - InitHeadParam(); - - for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) - { - iter->second = false; - } -} - -/** -* 获取最优长度 -* inParam : std::vector &vecAllTransInfo 待汇总取优的结果集 -* : TargetMaxLen iMaxLen 目标最大长度 -* outParam: N/A -* return : 最优长度 -*/ -int SelectBestEngine::GetBestLength(std::vector &vecAllTransInfo, TargetMaxLen iMaxLen) -{ - //1.获取结果中每种长度出现的次数 - std::map mapResultSize; - for (size_t i = 0; i < vecAllTransInfo.size(); i++) - { - int iNowSize = vecAllTransInfo[i].vecValue.size(); - if (mapResultSize.find(iNowSize) != mapResultSize.end()) - { - mapResultSize[iNowSize]++; - continue; - } - mapResultSize[iNowSize] = 1; - } - - int iBestLen = 0; - //2.获取最优长度 - if (iSelectBestMode_ == FREQUENCY) - { - //2.1 按长度出现的频次最多,作为最优长度 - int iCnt = 0; - for (auto it = mapResultSize.begin(); it != mapResultSize.end(); it++) - { - if (iCnt < it->second && it->first <= iMaxLen) - { - iCnt = it->second; - iBestLen = it->first; - } - } - } - else if (iSelectBestMode_ == LENGTH) - { - //2.2 按最长长度且不能大于最大长度,作为最优长度 - for (auto rit = mapResultSize.rbegin(); rit != mapResultSize.rend(); rit++) - { - if (rit->first <= iMaxLen) - { - iBestLen = rit->first; - break; - } - } - } - - return iBestLen; -} - -/** -* 获取最优结果 -* inParam : std::vector &vecAllTransInfo 待汇总取优的结果集 -* : TargetMaxLen iMaxLen 目标最大长度 -* outParam: N/A -* return : 最优结果 -*/ -std::string SelectBestEngine::GetBest(std::vector &vecAllTransInfo, TargetMaxLen iMaxLen) -{ - std::string strValue = ""; - if (vecAllTransInfo.size() <= 0) - { - return strValue; - } - - //优先使用校验通过的数据选优。 - std::vector vecTransInfoTemp; - for (size_t i = 0; i < vecAllTransInfo.size(); i++) - { - TransInfo transInfo = vecAllTransInfo[i]; - if (transInfo.IsChkFlag) - { - vecTransInfoTemp.emplace_back(transInfo); - } - } - if (vecTransInfoTemp.size() > 0) - { - vecAllTransInfo = vecTransInfoTemp; - } - else - { - // 此处因车厢太脏。识别效果很差,难以与RFID识别结果融合,所以增加eles - return strValue; - } - - //获取最优长度 - int iBestLen = GetBestLength(vecAllTransInfo, iMaxLen); - - //初始化最优结果 - TransInfo transInfoBest; - transInfoBest.vecScore.reserve(iBestLen); - transInfoBest.vecValue.reserve(iBestLen); - for (int i = 0; i < iBestLen; i++) - { - transInfoBest.vecScore.emplace_back(0); - transInfoBest.vecValue.emplace_back(""); - } - - std::map mapResult; //符合最优长度的结果集 [key:结果; value:结果出现次数] - for (size_t iIndex = 0; iIndex < vecAllTransInfo.size(); iIndex++) - { - if (vecAllTransInfo[iIndex].vecValue.size() != iBestLen) - { - continue; - } - - std::string strValueTemp; - for (int j = 0; j < iBestLen; j++) - { - strValueTemp += vecAllTransInfo[iIndex].vecValue[j]; - if (transInfoBest.vecScore[j] < vecAllTransInfo[iIndex].vecScore[j]) - { - transInfoBest.vecScore[j] = vecAllTransInfo[iIndex].vecScore[j]; - transInfoBest.vecValue[j] = vecAllTransInfo[iIndex].vecValue[j]; - } - } - - if (mapResult.find(strValueTemp) != mapResult.end()) - { - mapResult[strValueTemp]++; - } - else - { - mapResult[strValueTemp] = 1; - } - } - - //按字符最高得分汇总结果 - for (size_t i = 0; i < transInfoBest.vecValue.size(); ++i) - { - strValue += transInfoBest.vecValue[i]; - } - - //按出现次数汇总结果 - int iMaxCnt = 0; - std::string strValue2; - for (auto iter = mapResult.begin(); iter != mapResult.end(); iter++) - { - if (iter->second > iMaxCnt) - { - iMaxCnt = iter->second; - strValue2 = iter->first; - } - } - - //最高得分汇总和最高次数汇总不相等,且识别同一结果次数大于等于3次,则使用按次数汇总结果。 - if (strValue != strValue2) - { - LogWarn << "engineId:" << engineId_ << " value1:" << strValue << " value2:" << strValue2 - << " not equal value2cnt:" << iMaxCnt; - if (iMaxCnt >= 3) - { - strValue = strValue2; - } - } - - return strValue; -} - -/** -* 车号数据加入到待选优集合中 -* inParam : std::shared_ptr pProcessData :处理帧数据 - : TransSubData &transSubData :转换后子数据 -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::NumAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) -{ - for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) - { - TransInfo transInfo = transSubData.vecTransInfo[i]; - mapNumInfo_[transInfo.iLine].emplace_back(transInfo); - } - - //记录车厢类型ID - if (mapTrainTypeId_.find(transSubData.iBigClassId) != mapTrainTypeId_.end()) - { - mapTrainTypeId_[transSubData.iBigClassId]++; - } - else - { - mapTrainTypeId_[transSubData.iBigClassId] = 1; - } - - //最高分和最优帧号 - if (fMaxScoreSumNum_ < transSubData.fScoreSum) - { - fMaxScoreSumNum_ = transSubData.fScoreSum; - strBestNumImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; - i64TimeStampNum_ = pProcessData->i64TimeStamp; - step1LocationBestNum_ = transSubData.step1Location; - iDataSourceNum_ = pProcessData->iDataSource; - } -} - -/** -* 属性数据加入到待选优集合中 -* inParam : std::shared_ptr pProcessData :处理帧数据 - : TransSubData &transSubData :转换后子数据 -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::ProAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) -{ - for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) - { - TransInfo transInfo = transSubData.vecTransInfo[i]; - mapProInfo_[transInfo.iLine].emplace_back(transInfo); - } - - //最高分和最优帧号 - if (fMaxScoreSumPro_ < transSubData.fScoreSum) - { - fMaxScoreSumPro_ = transSubData.fScoreSum; - strBestProImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; - i64TimeStampPro_ = pProcessData->i64TimeStamp; - step1LocationBestPro_ = transSubData.step1Location; - iDataSourcePro_ = pProcessData->iDataSource; - } -} - -/** -* 车头数据加入到待选优集合中 -* inParam : std::shared_ptr pProcessData :处理帧数据 - : TransSubData &transSubData :转换后子数据 -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::HeadAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) -{ - for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) - { - TransInfo transInfo = transSubData.vecTransInfo[i]; - mapHeadInfo_[transInfo.iLine].emplace_back(transInfo); - } - - //记录车头大框识别次数 - auto iter = mapTrainTypeId_.find(0); - if (iter == mapTrainTypeId_.end()) - { - mapTrainTypeId_.insert(std::make_pair(0, 1)); - } - else - { - iter->second++; - } - - //最高分和最优帧号 - if (fMaxScoreSumHead_ < transSubData.fScoreSum) - { - fMaxScoreSumHead_ = transSubData.fScoreSum; - strBestHeadImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; - i64TimeStampHead_ = pProcessData->i64TimeStamp; - step1LocationBestHead_ = transSubData.step1Location; - iDataSourceHead_ = pProcessData->iDataSource; - } -} - -/** -* 汇总车头最佳值 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -bool SelectBestEngine::GetHeadBest(std::shared_ptr pProcessData) -{ - //2.无识别车头信息,不汇总 - if (mapHeadInfo_.empty()) - { - LogDebug << "engineId:" << engineId_ << " no head info"; - return false; - } - - std::shared_ptr pTrain = std::make_shared(); - pTrain->trainNum.iDataSource = iDataSourceHead_; - pTrain->trainNum.bIsEnd = pProcessData->bIsEnd; - pTrain->trainNum.strTrainDate = pProcessData->strTrainDate; - pTrain->trainNum.strTrainName = pProcessData->strTrainName; - pTrain->trainNum.iDirection = pProcessData->iDirection; - - //车头型号 - if (mapHeadInfo_.find(0) != mapHeadInfo_.end()) - { - pTrain->trainNum.strTrainType = GetBest(mapHeadInfo_.at(0), TYPE_MAXLEN); - } - - //车头编号 - if (mapHeadInfo_.find(1) != mapHeadInfo_.end()) - { - pTrain->trainNum.strTrainNum = GetBest(mapHeadInfo_.at(1), NUM_MAXLEN); - } - - pTrain->trainNum.strBestImg = strBestHeadImg_; - pTrain->trainNum.iCarXH = 0; - pTrain->trainNum.step1Location = step1LocationBestHead_; - pTrain->trainNum.i64TimeStamp = i64TimeStampHead_; - pTrain->trainNum.iTrainTypeId = 0; //车头 - - - //push端口1,车头属性 - pTrain->trainPro.iDataSource = iDataSourceHead_; - pTrain->trainPro.bIsEnd = pProcessData->bIsEnd; - pTrain->trainPro.strTrainDate = pProcessData->strTrainDate; - pTrain->trainPro.strTrainName = pProcessData->strTrainName; - pTrain->trainPro.iDirection = pProcessData->iDirection; - pTrain->trainPro.iCarXH = 0; - - pTrain->strTrainDate = pTrain->trainNum.strTrainDate; - pTrain->strTrainName = pTrain->trainNum.strTrainName; - pTrain->iDirection = pTrain->trainNum.iDirection; - pTrain->iDataSource = pTrain->trainNum.iDataSource >= pTrain->trainPro.iDataSource ? pTrain->trainNum.iDataSource : pTrain->trainPro.iDataSource; - - LogInfo << "\n ---汇总结果--- \n" - << "日期时间: " << pTrain->strTrainDate << " " << pTrain->strTrainName << "\n" - << "车厢序号: " << pTrain->iCarXH << "\n" - << "车型Id: " << pTrain->trainNum.iTrainTypeId << "\n" - << "车型: " << pTrain->trainNum.strTrainType << "\n" - << "车号: " << pTrain->trainNum.strTrainNum << "\n" - << "载重: " << pTrain->trainPro.strLoad << "\n" - << "自重: " << pTrain->trainPro.strSelf << "\n" - << "容积: " << pTrain->trainPro.strVolume << "\n" - << "换长: " << pTrain->trainPro.strChange << "\n" - << "容量记表: " << pTrain->trainPro.strVolumeSurface << "\n" - << "编号图片: " << pTrain->trainNum.strBestImg << "\n" - << "属性图片: " << pTrain->trainPro.strBestImg << "\n" - << "行驶方向: " << pTrain->iDirection << "\n" - << " ---汇总结果 END--- "; - - //拷贝最优图片到最优路径下 - CopyBestImgToBestPath(pTrain); - - std::shared_ptr pTrainToCsv = std::make_shared(); - *pTrainToCsv = *pTrain; - PushData(strPort0_, pTrain); - PushData(strPort1_, pTrainToCsv); - return true; -} - -/** -* 汇总车号最佳值 -* inParam : std::shared_ptr pProcessData -* outParam: TrainNum &trainNum -* return : N/A -*/ -void SelectBestEngine::GetNumBest(TrainNum &trainNum, std::shared_ptr pProcessData) -{ - trainNum.iDataSource = iDataSourceNum_; - trainNum.bIsEnd = pProcessData->bIsEnd; - trainNum.strTrainDate = pProcessData->strTrainDate; - trainNum.strTrainName = pProcessData->strTrainName; - trainNum.iDirection = pProcessData->iDirection; - trainNum.iCarXH = pProcessData->iTrainIndex; - - //车型 - if (mapNumInfo_.find(0) != mapNumInfo_.end()) - { - trainNum.strTrainType = GetBest(mapNumInfo_.at(0), TYPE_MAXLEN); - } - //编号 - if (mapNumInfo_.find(1) != mapNumInfo_.end()) - { - trainNum.strTrainNum = GetBest(mapNumInfo_.at(1), NUM_MAXLEN); - } - - //按出现次数选车厢类型ID - int iMaxCnt = 0; - for (auto iter = mapTrainTypeId_.begin(); iter != mapTrainTypeId_.end(); iter++) - { - if (iter->second > iMaxCnt) - { - iMaxCnt = iter->second; - trainNum.iTrainTypeId = iter->first; - } - } - - trainNum.strBestImg = strBestNumImg_; - trainNum.fScoreSum = fMaxScoreSumNum_; - trainNum.iCarXH = iNumIndex_++; - trainNum.step1Location = step1LocationBestNum_; - trainNum.i64TimeStamp = i64TimeStampNum_; - //初始化车号信息 - InitNumParam(); -} - -/** -* 汇总属性最佳值 -* inParam : std::shared_ptr pProcessData -* outParam: TrainPro &trainPro -* return : N/A -*/ -void SelectBestEngine::GetProBest(TrainPro &trainPro, std::shared_ptr pProcessData) -{ - trainPro.iDataSource = iDataSourcePro_; - trainPro.bIsEnd = pProcessData->bIsEnd; - trainPro.strTrainDate = pProcessData->strTrainDate; - trainPro.strTrainName = pProcessData->strTrainName; - trainPro.iDirection = pProcessData->iDirection; - trainPro.iCarXH = pProcessData->iTrainIndex; - - //载重 - if (mapProInfo_.find(0) != mapProInfo_.end()) - { - trainPro.strLoad = GetBest(mapProInfo_.at(0), LOAD_MAXLEN); - } - //自重 - if (mapProInfo_.find(1) != mapProInfo_.end()) - { - trainPro.strSelf = GetBest(mapProInfo_.at(1), SELF_MAXLEN); - if (trainPro.strSelf.length() == 3) - { - trainPro.strSelf = trainPro.strSelf.substr(0, 2) + "." + trainPro.strSelf.substr(2, 1); - } - } - //容积 - if (mapProInfo_.find(2) != mapProInfo_.end()) - { - trainPro.strVolume = GetBest(mapProInfo_.at(2), VOLUME_MAXLEN); - //棚车容器一般为1开头得三位整数,因此不需要额外补小数点处理。 - if (trainPro.strVolume.length() == 3 && trainPro.strVolume.substr(0, 1) != "1") - { - trainPro.strVolume = trainPro.strVolume.substr(0, 2) + "." + trainPro.strVolume.substr(2, 1); - } - } - - //换长 - if (mapProInfo_.find(3) != mapProInfo_.end()) - { - trainPro.strChange = GetBest(mapProInfo_.at(3), CHANGE_MAXLEN); - if (trainPro.strChange.length() == 1) - { - if (trainPro.strChange.at(0) != '1') - { - trainPro.strChange = "1." + trainPro.strChange; - } - } - else if (trainPro.strChange.length() == 2) - { - trainPro.strChange = trainPro.strChange.substr(0, 1) + "." + trainPro.strChange.substr(1, 1); - } - } - - //罐车容量记表 - if (mapProInfo_.find(4) != mapProInfo_.end()) - { - trainPro.strVolumeSurface = GetBest(mapProInfo_.at(4), VOLUMESURFACE_MAXLEN); - } - - trainPro.strBestImg = strBestProImg_; - trainPro.fScoreSum = fMaxScoreSumPro_; - trainPro.iCarXH = iProIndex_++; - trainPro.step1Location = step1LocationBestPro_; - trainPro.i64TimeStamp = i64TimeStampPro_; - //初始化属性信息 - InitProParam(); -} - -/** -* 拷贝最优图片到最优路径下 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::CopyBestImgToBestPath(const std::shared_ptr &pTrain) -{ - //拷贝最优图片到最优路径下 - if (!pTrain->trainNum.strBestImg.empty()) - { - char szCameraNo[6] = {0}; //车号最优图片路径 - sprintf(szCameraNo, "/%03d/", pTrain->trainNum.iDataSource + 1); - std::string strDes = strBestPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo; - if (!MyUtils::getins()->CreateDirPath(strDes)) - { - LogError << "engineId:" << engineId_ << " CreateDirPath err strDes:" << strDes; - return; - } - - std::string strSrc = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo + pTrain->trainNum.strBestImg; - strDes += pTrain->trainNum.strBestImg; - MyUtils::getins()->copyFile(strSrc, strDes); - } - if (!pTrain->trainPro.strBestImg.empty()) - { - char szCameraNo[6] = {0}; //车号最优图片路径 - sprintf(szCameraNo, "/%03d/", pTrain->trainPro.iDataSource + 1); - std::string strDes = strBestPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo; - if (!MyUtils::getins()->CreateDirPath(strDes)) - { - LogError << "engineId:" << engineId_ << " CreateDirPath err strDes:" << strDes; - return; - } - std::string strSrc = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo + pTrain->trainPro.strBestImg; - strDes += pTrain->trainPro.strBestImg; - MyUtils::getins()->copyFile(strSrc, strDes); - } -} - - -/** -* 汇总车厢最佳值 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void SelectBestEngine::GetTrainBest(std::shared_ptr pProcessData) -{ - std::shared_ptr pTrain = std::make_shared(); - //1.汇总车号信息 - GetNumBest(pTrain->trainNum, pProcessData); - - //2.汇总属性信息 - GetProBest(pTrain->trainPro, pProcessData); - - /*按车型删除误识别的属性 - 1.非罐车删除容量计表 - 2.平车删除容积 - */ - if (pTrain->trainNum.iTrainTypeId != 5 && pTrain->trainNum.iTrainTypeId != -1) - { - pTrain->trainPro.strVolumeSurface = ""; - } - if (pTrain->trainNum.iTrainTypeId == 6) - { - pTrain->trainPro.strVolume = ""; - } - - pTrain->strTrainDate = pTrain->trainNum.strTrainDate; - pTrain->strTrainName = pTrain->trainNum.strTrainName; - pTrain->iDirection = pTrain->trainNum.iDirection; - pTrain->iCarXH = pTrain->trainNum.iCarXH; - pTrain->iDataSource = pTrain->trainNum.iDataSource >= pTrain->trainPro.iDataSource ? pTrain->trainNum.iDataSource : pTrain->trainPro.iDataSource; - - LogInfo << "\n ---汇总结果--- \n" - << "日期时间: " << pTrain->strTrainDate << " " << pTrain->strTrainName << "\n" - << "车厢序号: " << pTrain->iCarXH << "\n" - << "车型Id: " << pTrain->trainNum.iTrainTypeId << "\n" - << "车型: " << pTrain->trainNum.strTrainType << "\n" - << "车号: " << pTrain->trainNum.strTrainNum << "\n" - << "载重: " << pTrain->trainPro.strLoad << "\n" - << "自重: " << pTrain->trainPro.strSelf << "\n" - << "容积: " << pTrain->trainPro.strVolume << "\n" - << "换长: " << pTrain->trainPro.strChange << "\n" - << "容量记表: " << pTrain->trainPro.strVolumeSurface << "\n" - << "编号图片: " << pTrain->trainNum.strBestImg << "\n" - << "属性图片: " << pTrain->trainPro.strBestImg << "\n" - << "行驶方向: " << pTrain->iDirection << "\n" - << " ---汇总结果 END--- "; - - //拷贝最优图片到最优路径下 - CopyBestImgToBestPath(pTrain); - - std::shared_ptr pTrainToCsv = std::make_shared(); - *pTrainToCsv = *pTrain; - PushData(strPort0_, pTrain); - PushData(strPort1_, pTrainToCsv); -} - -APP_ERROR SelectBestEngine::Process() -{ - int iRet = APP_ERR_OK; - while (!isStop_) - { - //pop端口0 - std::shared_ptr pVoidData0 = nullptr; - iRet = inputQueMap_[strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); - continue; - } - - std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); - std::shared_ptr pTransData = std::static_pointer_cast(pProcessData->pVoidData); - if (pProcessData->bIsEnd) - { - mapDataSourceIsEnd_[pProcessData->iDataSource] = pProcessData->bIsEnd; - } - - for (size_t i = 0; i < pTransData->vecTransSubData.size(); i++) - { - TransSubData transSubData = pTransData->vecTransSubData[i]; - //车头 - if (transSubData.iBigClassId == 0) - { - //车头加入待汇总集合中 - HeadAddSelectBestMap(pProcessData, transSubData); - } - //属性 - else if (transSubData.iBigClassId == 1) - { - //属性加入待汇总集合中 - ProAddSelectBestMap(pProcessData, transSubData); - } - //车号 - else if (transSubData.iBigClassId >= 2 && transSubData.iBigClassId <= 6) - { - //车号加入待汇总集合中 - NumAddSelectBestMap(pProcessData, transSubData); - } - } - - //3. 结束帧,需汇总 - bool bAllEnd = true; - for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) - { - bAllEnd = bAllEnd && iter->second; - } - - if (bAllEnd) - { - bool bHeadFlag = false; - //第一节或最后一节汇总车头 - //(注:针对2个车头的场景,除判断第一节和最后一节外,额外增加车头的次数,当车头大框次数大于3次时,则认为车头。因此后续第一个节和最后一节的条件可以删除) - if (pProcessData->iTrainIndex == 1 || pProcessData->bIsTrainEnd || - (mapTrainTypeId_.find(0) != mapTrainTypeId_.end() && (mapTrainTypeId_[0] >= 2 || mapTrainTypeId_.size() == 1))) - { - bHeadFlag = GetHeadBest(pProcessData); - } - - //汇总车厢 车号和属性 - if (!bHeadFlag) - { - GetTrainBest(pProcessData); - } - - //初始化参数变量 - InitParam(); - } - } - return APP_ERR_OK; -} +#include "SelectBestEngine.h" #include "myutils.h" using namespace ai_matrix; SelectBestEngine::SelectBestEngine() {} SelectBestEngine::~SelectBestEngine() {} APP_ERROR SelectBestEngine::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1"; iSelectBestMode_ = MyYaml::GetIns()->GetIntValue("gc_select_best_mode"); strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); strBestPath_ = MyYaml::GetIns()->GetPathValue("gc_best_path"); //获取几个摄像头识别车号 std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { if (iter->second.strTarget.find("NUM") != std::string::npos) { mapDataSourceIsEnd_[iter->first] = false; } } InitParam(); LogInfo << "SelectBestEngine Init ok"; return APP_ERR_OK; } APP_ERROR SelectBestEngine::DeInit() { LogInfo << "SelectBestEngine DeInit ok"; return APP_ERR_OK; } /** * push数据到队列,队列满时则休眠一段时间再push * inParam : const std::string strPort push的端口 : const std::shared_ptr &pTrain push的数据 * outParam: N/A * return : N/A */ void SelectBestEngine::PushData(const std::string &strPort, const std::shared_ptr &pTrain) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pTrain)); if (iRet != 0) { LogDebug << "num:" << pTrain->trainNum.strTrainNum << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } /** * 初始化车号参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::InitNumParam() { mapTrainTypeId_.clear(); mapNumInfo_.clear(); strBestNumImg_ = ""; i64TimeStampNum_ = 0; fMaxScoreSumNum_ = 0; memset(&step1LocationBestNum_, 0, sizeof(step1LocationBestNum_)); iDataSourceNum_ = 0; } /** * 初始化属性参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::InitProParam() { mapProInfo_.clear(); strBestProImg_ = ""; i64TimeStampPro_ = 0; fMaxScoreSumPro_ = 0; memset(&step1LocationBestPro_, 0, sizeof(step1LocationBestPro_)); iDataSourcePro_ = 0; } /** * 初始化车号参数信息(只有车结束调用) * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::InitHeadParam() { mapHeadInfo_.clear(); strBestHeadImg_ = ""; i64TimeStampHead_ = 0; fMaxScoreSumHead_ = 0; memset(&step1LocationBestHead_, 0, sizeof(step1LocationBestHead_)); iDataSourceHead_ = 0; } /** * 初始化参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::InitParam() { iNumIndex_ = 1; iProIndex_ = 1; InitNumParam(); InitProParam(); InitHeadParam(); for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { iter->second = false; } } /** * 获取最优长度 * inParam : std::vector &vecAllTransInfo 待汇总取优的结果集 * : TargetMaxLen iMaxLen 目标最大长度 * outParam: N/A * return : 最优长度 */ int SelectBestEngine::GetBestLength(std::vector &vecAllTransInfo, TargetMaxLen iMaxLen) { //1.获取结果中每种长度出现的次数 std::map mapResultSize; for (size_t i = 0; i < vecAllTransInfo.size(); i++) { int iNowSize = vecAllTransInfo[i].vecValue.size(); if (mapResultSize.find(iNowSize) != mapResultSize.end()) { mapResultSize[iNowSize]++; continue; } mapResultSize[iNowSize] = 1; } int iBestLen = 0; //2.获取最优长度 if (iSelectBestMode_ == FREQUENCY) { //2.1 按长度出现的频次最多,作为最优长度 int iCnt = 0; for (auto it = mapResultSize.begin(); it != mapResultSize.end(); it++) { if (iCnt < it->second && it->first <= iMaxLen) { iCnt = it->second; iBestLen = it->first; } } } else if (iSelectBestMode_ == LENGTH) { //2.2 按最长长度且不能大于最大长度,作为最优长度 for (auto rit = mapResultSize.rbegin(); rit != mapResultSize.rend(); rit++) { if (rit->first <= iMaxLen) { iBestLen = rit->first; break; } } } return iBestLen; } /** * 获取最优结果 * inParam : std::vector &vecAllTransInfo 待汇总取优的结果集 * : TargetMaxLen iMaxLen 目标最大长度 * outParam: N/A * return : 最优结果 */ std::string SelectBestEngine::GetBest(std::vector &vecAllTransInfo, TargetMaxLen iMaxLen) { std::string strValue = ""; if (vecAllTransInfo.size() <= 0) { LogInfo << "<<< --- 没数据 --- >>>"; return strValue; } //优先使用校验通过的数据选优。 std::vector vecTransInfoTemp; for (size_t i = 0; i < vecAllTransInfo.size(); i++) { TransInfo transInfo = vecAllTransInfo[i]; if (transInfo.IsChkFlag) { vecTransInfoTemp.emplace_back(transInfo); } } if (vecTransInfoTemp.size() > 0) { vecAllTransInfo = vecTransInfoTemp; } else { // LogInfo << "--->>> 没有符合正则的??"; // 此处因车厢太脏。识别效果很差,难以与RFID识别结果融合,所以增加eles return strValue; } //获取最优长度 int iBestLen = GetBestLength(vecAllTransInfo, iMaxLen); // LogInfo << "--->>> 最优长度:" << iBestLen; //初始化最优结果 TransInfo transInfoBest; transInfoBest.vecScore.reserve(iBestLen); transInfoBest.vecValue.reserve(iBestLen); for (int i = 0; i < iBestLen; i++) { transInfoBest.vecScore.emplace_back(0); transInfoBest.vecValue.emplace_back(""); } std::map mapResult; //符合最优长度的结果集 [key:结果; value:结果出现次数] for (size_t iIndex = 0; iIndex < vecAllTransInfo.size(); iIndex++) { if (vecAllTransInfo[iIndex].vecValue.size() != iBestLen) { continue; } std::string strValueTemp; for (int j = 0; j < iBestLen; j++) { strValueTemp += vecAllTransInfo[iIndex].vecValue[j]; if (transInfoBest.vecScore[j] < vecAllTransInfo[iIndex].vecScore[j]) { transInfoBest.vecScore[j] = vecAllTransInfo[iIndex].vecScore[j]; transInfoBest.vecValue[j] = vecAllTransInfo[iIndex].vecValue[j]; } } if (mapResult.find(strValueTemp) != mapResult.end()) { mapResult[strValueTemp]++; } else { mapResult[strValueTemp] = 1; } } //按字符最高得分汇总结果 for (size_t i = 0; i < transInfoBest.vecValue.size(); ++i) { strValue += transInfoBest.vecValue[i]; } //按出现次数汇总结果 int iMaxCnt = 0; std::string strValue2; for (auto iter = mapResult.begin(); iter != mapResult.end(); iter++) { if (iter->second > iMaxCnt) { iMaxCnt = iter->second; strValue2 = iter->first; } } //最高得分汇总和最高次数汇总不相等,且识别同一结果次数大于等于3次,则使用按次数汇总结果。 if (strValue != strValue2) { LogWarn << "engineId:" << engineId_ << " value1:" << strValue << " value2:" << strValue2 << " not equal value2cnt:" << iMaxCnt; if (iMaxCnt >= 3) { strValue = strValue2; } } return strValue; } /** * 车号数据加入到待选优集合中 * inParam : std::shared_ptr pProcessData :处理帧数据 : TransSubData &transSubData :转换后子数据 * outParam: N/A * return : N/A */ void SelectBestEngine::NumAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) { for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) { TransInfo transInfo = transSubData.vecTransInfo[i]; // LogInfo << "待选优 >>> " << transInfo.vecValue[0]; mapNumInfo_[transInfo.iLine].emplace_back(transInfo); } //记录车厢类型ID if (mapTrainTypeId_.find(transSubData.iBigClassId) != mapTrainTypeId_.end()) { mapTrainTypeId_[transSubData.iBigClassId]++; } else { mapTrainTypeId_[transSubData.iBigClassId] = 1; } //最高分和最优帧号 if (fMaxScoreSumNum_ < transSubData.fScoreSum) { fMaxScoreSumNum_ = transSubData.fScoreSum; strBestNumImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; i64TimeStampNum_ = pProcessData->i64TimeStamp; step1LocationBestNum_ = transSubData.step1Location; iDataSourceNum_ = pProcessData->iDataSource; } } /** * 属性数据加入到待选优集合中 * inParam : std::shared_ptr pProcessData :处理帧数据 : TransSubData &transSubData :转换后子数据 * outParam: N/A * return : N/A */ void SelectBestEngine::ProAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) { for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) { TransInfo transInfo = transSubData.vecTransInfo[i]; mapProInfo_[transInfo.iLine].emplace_back(transInfo); } //最高分和最优帧号 if (fMaxScoreSumPro_ < transSubData.fScoreSum) { fMaxScoreSumPro_ = transSubData.fScoreSum; strBestProImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; i64TimeStampPro_ = pProcessData->i64TimeStamp; step1LocationBestPro_ = transSubData.step1Location; iDataSourcePro_ = pProcessData->iDataSource; } } /** * 车头数据加入到待选优集合中 * inParam : std::shared_ptr pProcessData :处理帧数据 : TransSubData &transSubData :转换后子数据 * outParam: N/A * return : N/A */ void SelectBestEngine::HeadAddSelectBestMap(std::shared_ptr pProcessData, TransSubData &transSubData) { for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) { TransInfo transInfo = transSubData.vecTransInfo[i]; mapHeadInfo_[transInfo.iLine].emplace_back(transInfo); } //记录车头大框识别次数 auto iter = mapTrainTypeId_.find(0); if (iter == mapTrainTypeId_.end()) { mapTrainTypeId_.insert(std::make_pair(0, 1)); } else { iter->second++; } //最高分和最优帧号 if (fMaxScoreSumHead_ < transSubData.fScoreSum) { fMaxScoreSumHead_ = transSubData.fScoreSum; strBestHeadImg_ = std::to_string(pProcessData->iFrameId) + ".jpg"; i64TimeStampHead_ = pProcessData->i64TimeStamp; step1LocationBestHead_ = transSubData.step1Location; iDataSourceHead_ = pProcessData->iDataSource; } } /** * 汇总车头最佳值 * inParam : N/A * outParam: N/A * return : N/A */ bool SelectBestEngine::GetHeadBest(std::shared_ptr pProcessData) { //2.无识别车头信息,不汇总 if (mapHeadInfo_.empty()) { LogDebug << "engineId:" << engineId_ << " no head info"; return false; } std::shared_ptr pTrain = std::make_shared(); pTrain->trainNum.iDataSource = iDataSourceHead_; pTrain->trainNum.bIsEnd = pProcessData->bIsEnd; pTrain->trainNum.strTrainDate = pProcessData->strTrainDate; pTrain->trainNum.strTrainName = pProcessData->strTrainName; pTrain->trainNum.iDirection = pProcessData->iDirection; //车头型号 if (mapHeadInfo_.find(0) != mapHeadInfo_.end()) { pTrain->trainNum.strTrainType = GetBest(mapHeadInfo_.at(0), TYPE_MAXLEN); } //车头编号 if (mapHeadInfo_.find(1) != mapHeadInfo_.end()) { pTrain->trainNum.strTrainNum = GetBest(mapHeadInfo_.at(1), NUM_MAXLEN); } pTrain->trainNum.strBestImg = strBestHeadImg_; pTrain->trainNum.iCarXH = 0; pTrain->trainNum.step1Location = step1LocationBestHead_; pTrain->trainNum.i64TimeStamp = i64TimeStampHead_; pTrain->trainNum.iTrainTypeId = 0; //车头 //push端口1,车头属性 pTrain->trainPro.iDataSource = iDataSourceHead_; pTrain->trainPro.bIsEnd = pProcessData->bIsEnd; pTrain->trainPro.strTrainDate = pProcessData->strTrainDate; pTrain->trainPro.strTrainName = pProcessData->strTrainName; pTrain->trainPro.iDirection = pProcessData->iDirection; pTrain->trainPro.iCarXH = 0; pTrain->strTrainDate = pTrain->trainNum.strTrainDate; pTrain->strTrainName = pTrain->trainNum.strTrainName; pTrain->iDirection = pTrain->trainNum.iDirection; pTrain->iDataSource = pTrain->trainNum.iDataSource >= pTrain->trainPro.iDataSource ? pTrain->trainNum.iDataSource : pTrain->trainPro.iDataSource; LogInfo << "\n ---汇总结果--- \n" << "日期时间: " << pTrain->strTrainDate << " " << pTrain->strTrainName << "\n" << "车厢序号: " << pTrain->iCarXH << "\n" << "车型Id: " << pTrain->trainNum.iTrainTypeId << "\n" << "车型: " << pTrain->trainNum.strTrainType << "\n" << "车号: " << pTrain->trainNum.strTrainNum << "\n" << "载重: " << pTrain->trainPro.strLoad << "\n" << "自重: " << pTrain->trainPro.strSelf << "\n" << "容积: " << pTrain->trainPro.strVolume << "\n" << "换长: " << pTrain->trainPro.strChange << "\n" << "容量记表: " << pTrain->trainPro.strVolumeSurface << "\n" << "编号图片: " << pTrain->trainNum.strBestImg << "\n" << "属性图片: " << pTrain->trainPro.strBestImg << "\n" << "行驶方向: " << pTrain->iDirection << "\n" << " ---汇总结果 END--- "; //拷贝最优图片到最优路径下 CopyBestImgToBestPath(pTrain); std::shared_ptr pTrainToCsv = std::make_shared(); *pTrainToCsv = *pTrain; PushData(strPort0_, pTrain); PushData(strPort1_, pTrainToCsv); return true; } /** * 汇总车号最佳值 * inParam : std::shared_ptr pProcessData * outParam: TrainNum &trainNum * return : N/A */ void SelectBestEngine::GetNumBest(TrainNum &trainNum, std::shared_ptr pProcessData) { trainNum.iDataSource = iDataSourceNum_; trainNum.bIsEnd = pProcessData->bIsEnd; trainNum.strTrainDate = pProcessData->strTrainDate; trainNum.strTrainName = pProcessData->strTrainName; trainNum.iDirection = pProcessData->iDirection; trainNum.iCarXH = pProcessData->iTrainIndex; //车型 if (mapNumInfo_.find(0) != mapNumInfo_.end()) { trainNum.strTrainType = GetBest(mapNumInfo_.at(0), TYPE_MAXLEN); // LogInfo << "-->>> " << trainNum.strTrainType; } //编号 if (mapNumInfo_.find(1) != mapNumInfo_.end()) { trainNum.strTrainNum = GetBest(mapNumInfo_.at(1), NUM_MAXLEN); } //按出现次数选车厢类型ID int iMaxCnt = 0; for (auto iter = mapTrainTypeId_.begin(); iter != mapTrainTypeId_.end(); iter++) { if (iter->second > iMaxCnt) { iMaxCnt = iter->second; trainNum.iTrainTypeId = iter->first; } } trainNum.strBestImg = strBestNumImg_; trainNum.fScoreSum = fMaxScoreSumNum_; trainNum.iCarXH = iNumIndex_++; trainNum.step1Location = step1LocationBestNum_; trainNum.i64TimeStamp = i64TimeStampNum_; //初始化车号信息 InitNumParam(); } /** * 汇总属性最佳值 * inParam : std::shared_ptr pProcessData * outParam: TrainPro &trainPro * return : N/A */ void SelectBestEngine::GetProBest(TrainPro &trainPro, std::shared_ptr pProcessData) { trainPro.iDataSource = iDataSourcePro_; trainPro.bIsEnd = pProcessData->bIsEnd; trainPro.strTrainDate = pProcessData->strTrainDate; trainPro.strTrainName = pProcessData->strTrainName; trainPro.iDirection = pProcessData->iDirection; trainPro.iCarXH = pProcessData->iTrainIndex; //载重 if (mapProInfo_.find(0) != mapProInfo_.end()) { trainPro.strLoad = GetBest(mapProInfo_.at(0), LOAD_MAXLEN); } //自重 if (mapProInfo_.find(1) != mapProInfo_.end()) { trainPro.strSelf = GetBest(mapProInfo_.at(1), SELF_MAXLEN); if (trainPro.strSelf.length() == 3) { trainPro.strSelf = trainPro.strSelf.substr(0, 2) + "." + trainPro.strSelf.substr(2, 1); } } //容积 if (mapProInfo_.find(2) != mapProInfo_.end()) { trainPro.strVolume = GetBest(mapProInfo_.at(2), VOLUME_MAXLEN); //棚车容器一般为1开头得三位整数,因此不需要额外补小数点处理。 if (trainPro.strVolume.length() == 3 && trainPro.strVolume.substr(0, 1) != "1") { trainPro.strVolume = trainPro.strVolume.substr(0, 2) + "." + trainPro.strVolume.substr(2, 1); } } //换长 if (mapProInfo_.find(3) != mapProInfo_.end()) { trainPro.strChange = GetBest(mapProInfo_.at(3), CHANGE_MAXLEN); if (trainPro.strChange.length() == 1) { if (trainPro.strChange.at(0) != '1') { trainPro.strChange = "1." + trainPro.strChange; } } else if (trainPro.strChange.length() == 2) { trainPro.strChange = trainPro.strChange.substr(0, 1) + "." + trainPro.strChange.substr(1, 1); } } //罐车容量记表 if (mapProInfo_.find(4) != mapProInfo_.end()) { trainPro.strVolumeSurface = GetBest(mapProInfo_.at(4), VOLUMESURFACE_MAXLEN); } trainPro.strBestImg = strBestProImg_; trainPro.fScoreSum = fMaxScoreSumPro_; trainPro.iCarXH = iProIndex_++; trainPro.step1Location = step1LocationBestPro_; trainPro.i64TimeStamp = i64TimeStampPro_; //初始化属性信息 InitProParam(); } /** * 拷贝最优图片到最优路径下 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::CopyBestImgToBestPath(const std::shared_ptr &pTrain) { //拷贝最优图片到最优路径下 if (!pTrain->trainNum.strBestImg.empty()) { char szCameraNo[6] = {0}; //车号最优图片路径 sprintf(szCameraNo, "/%03d/", pTrain->trainNum.iDataSource + 1); std::string strDes = strBestPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo; if (!MyUtils::getins()->CreateDirPath(strDes)) { LogError << "engineId:" << engineId_ << " CreateDirPath err strDes:" << strDes; return; } std::string strSrc = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo + pTrain->trainNum.strBestImg; strDes += pTrain->trainNum.strBestImg; MyUtils::getins()->copyFile(strSrc, strDes); } if (!pTrain->trainPro.strBestImg.empty()) { char szCameraNo[6] = {0}; //车号最优图片路径 sprintf(szCameraNo, "/%03d/", pTrain->trainPro.iDataSource + 1); std::string strDes = strBestPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo; if (!MyUtils::getins()->CreateDirPath(strDes)) { LogError << "engineId:" << engineId_ << " CreateDirPath err strDes:" << strDes; return; } std::string strSrc = strResultPath_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szCameraNo + pTrain->trainPro.strBestImg; strDes += pTrain->trainPro.strBestImg; MyUtils::getins()->copyFile(strSrc, strDes); } } /** * 汇总车厢最佳值 * inParam : N/A * outParam: N/A * return : N/A */ void SelectBestEngine::GetTrainBest(std::shared_ptr pProcessData) { std::shared_ptr pTrain = std::make_shared(); //1.汇总车号信息 GetNumBest(pTrain->trainNum, pProcessData); //2.汇总属性信息 GetProBest(pTrain->trainPro, pProcessData); /*按车型删除误识别的属性 1.非罐车删除容量计表 2.平车删除容积 */ if (pTrain->trainNum.iTrainTypeId != 5 && pTrain->trainNum.iTrainTypeId != -1) { pTrain->trainPro.strVolumeSurface = ""; } if (pTrain->trainNum.iTrainTypeId == 6) { pTrain->trainPro.strVolume = ""; } pTrain->strTrainDate = pTrain->trainNum.strTrainDate; pTrain->strTrainName = pTrain->trainNum.strTrainName; pTrain->iDirection = pTrain->trainNum.iDirection; pTrain->iCarXH = pTrain->trainNum.iCarXH; pTrain->iDataSource = pTrain->trainNum.iDataSource >= pTrain->trainPro.iDataSource ? pTrain->trainNum.iDataSource : pTrain->trainPro.iDataSource; LogInfo << "\n ---汇总结果--- \n" << "日期时间: " << pTrain->strTrainDate << " " << pTrain->strTrainName << "\n" << "车厢序号: " << pTrain->iCarXH << "\n" << "车型Id: " << pTrain->trainNum.iTrainTypeId << "\n" << "车型: " << pTrain->trainNum.strTrainType << "\n" << "车号: " << pTrain->trainNum.strTrainNum << "\n" << "载重: " << pTrain->trainPro.strLoad << "\n" << "自重: " << pTrain->trainPro.strSelf << "\n" << "容积: " << pTrain->trainPro.strVolume << "\n" << "换长: " << pTrain->trainPro.strChange << "\n" << "容量记表: " << pTrain->trainPro.strVolumeSurface << "\n" << "编号图片: " << pTrain->trainNum.strBestImg << "\n" << "属性图片: " << pTrain->trainPro.strBestImg << "\n" << "行驶方向: " << pTrain->iDirection << "\n" << " ---汇总结果 END--- "; //拷贝最优图片到最优路径下 CopyBestImgToBestPath(pTrain); std::shared_ptr pTrainToCsv = std::make_shared(); *pTrainToCsv = *pTrain; PushData(strPort0_, pTrain); PushData(strPort1_, pTrainToCsv); } APP_ERROR SelectBestEngine::Process() { int iRet = APP_ERR_OK; while (!isStop_) { //pop端口0 std::shared_ptr pVoidData0 = nullptr; iRet = inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); std::shared_ptr pTransData = std::static_pointer_cast(pProcessData->pVoidData); if (pProcessData->bIsEnd) { mapDataSourceIsEnd_[pProcessData->iDataSource] = pProcessData->bIsEnd; } for (size_t i = 0; i < pTransData->vecTransSubData.size(); i++) { TransSubData transSubData = pTransData->vecTransSubData[i]; //车头 if (transSubData.iBigClassId == 0) { //车头加入待汇总集合中 HeadAddSelectBestMap(pProcessData, transSubData); } //属性 else if (transSubData.iBigClassId == 1) { //属性加入待汇总集合中 ProAddSelectBestMap(pProcessData, transSubData); } //车号 else if (transSubData.iBigClassId >= 2 && transSubData.iBigClassId <= 6) { //车号加入待汇总集合中 NumAddSelectBestMap(pProcessData, transSubData); } } //3. 结束帧,需汇总 bool bAllEnd = true; for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { bAllEnd = bAllEnd && iter->second; } if (bAllEnd) { bool bHeadFlag = false; //第一节或最后一节汇总车头 //(注:针对2个车头的场景,除判断第一节和最后一节外,额外增加车头的次数,当车头大框次数大于3次时,则认为车头。因此后续第一个节和最后一节的条件可以删除) if (pProcessData->iTrainIndex == 1 || pProcessData->bIsTrainEnd || (mapTrainTypeId_.find(0) != mapTrainTypeId_.end() && (mapTrainTypeId_[0] >= 2 || mapTrainTypeId_.size() == 1))) { bHeadFlag = GetHeadBest(pProcessData); } //汇总车厢 车号和属性 if (!bHeadFlag) { GetTrainBest(pProcessData); } //初始化参数变量 InitParam(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/SocketEngine/SocketEngine.cpp b/nvidia_ascend_engine/common_engine/SocketEngine/SocketEngine.cpp index 92d39f2..07348d7 100644 --- a/nvidia_ascend_engine/common_engine/SocketEngine/SocketEngine.cpp +++ b/nvidia_ascend_engine/common_engine/SocketEngine/SocketEngine.cpp @@ -4,276 +4,276 @@ SocketEngine::SocketEngine() { - isStop_ = false; + isStop_ = false; } SocketEngine::~SocketEngine() {} APP_ERROR SocketEngine::Init() { - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; + strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - this->socketOpenType_ = MyYaml::GetIns()->GetIntValue("socket_server_open"); - this->socketPort_ = MyYaml::GetIns()->GetIntValue("socket_server_port"); - this->socketQueueLen_ = MyYaml::GetIns()->GetIntValue("socket_server_queue_len"); + this->socketOpenType_ = MyYaml::GetIns()->GetIntValue("socket_server_open"); + this->socketPort_ = MyYaml::GetIns()->GetIntValue("socket_server_port"); + this->socketQueueLen_ = MyYaml::GetIns()->GetIntValue("socket_server_queue_len"); - MyShellInfo << "SocketEngine init ok"; - return APP_ERR_OK; + MyShellInfo << "SocketEngine init ok"; + return APP_ERR_OK; } APP_ERROR SocketEngine::DeInit() { - for (int fd = 0; fd <= max_fd; ++fd) - { - if (FD_ISSET(fd, &master_set)) - { - close(fd); - } - } + for (int fd = 0; fd <= max_fd; ++fd) + { + if (FD_ISSET(fd, &master_set)) + { + close(fd); + } + } - MyShellInfo << "SocketEngine deinit ok"; - return APP_ERR_OK; + MyShellInfo << "SocketEngine deinit ok"; + return APP_ERR_OK; } APP_ERROR SocketEngine::Process() { - int ret = APP_ERR_OK; + int ret = APP_ERR_OK; - if (this->socketOpenType_) - { - while (!isStop_) - { - if (!this->Socket_(this->socketPort_)) continue; - if (!this->Bind()) continue; - this->Listen(this->socketQueueLen_); - this->Run(); - } + if (this->socketOpenType_) + { + while (!isStop_) + { + if (!this->Socket_(this->socketPort_)) continue; + if (!this->Bind()) continue; + this->Listen(this->socketQueueLen_); + this->Run(); + } - } - else - { - while (!isStop_) - { - usleep(1000); - } - } + } + else + { + while (!isStop_) + { + usleep(1000); + } + } - return APP_ERR_OK; + return APP_ERR_OK; } bool SocketEngine::Socket_(int port) { - bzero(&server_addr, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htons(INADDR_ANY); - server_addr.sin_port = htons(port); - // create socket to listen - listen_fd = socket(PF_INET, SOCK_STREAM, 0); - if (listen_fd < 0) - { - LogError << "Create Scoket_Server Failed!"; - return false; - } - int opt = 1; - setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - return true; + bzero(&server_addr, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htons(INADDR_ANY); + server_addr.sin_port = htons(port); + // create socket to listen + listen_fd = socket(PF_INET, SOCK_STREAM, 0); + if (listen_fd < 0) + { + LogError << "Create Scoket_Server Failed!"; + return false; + } + int opt = 1; + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + return true; } bool SocketEngine::Bind() { - if (-1 == (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)))) - { - LogError << "Scoket_Server Bind Failed!"; - return false; - } - LogInfo << "Scoket_Server Bind Successfully."; - return true; + if (-1 == (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)))) + { + LogError << "Scoket_Server Bind Failed!"; + return false; + } + LogInfo << "Scoket_Server Bind Successfully."; + return true; } bool SocketEngine::Listen(int queue_len) { - if (-1 == listen(listen_fd, queue_len)) - { - LogError << "Scoket_Server Listen Failed!"; - return false; - } - LogInfo << "Scoket_Server Listen Successfully."; - return true; + if (-1 == listen(listen_fd, queue_len)) + { + LogError << "Scoket_Server Listen Failed!"; + return false; + } + LogInfo << "Scoket_Server Listen Successfully."; + return true; } bool SocketEngine::Accept() { - struct sockaddr_in client_addr; - socklen_t client_addr_len = sizeof(client_addr); + struct sockaddr_in client_addr; + socklen_t client_addr_len = sizeof(client_addr); - int new_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_addr_len); - if (new_fd < 0) - { - LogError << "Scoket_Server Accept Failed!"; - return false; - } + int new_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_addr_len); + if (new_fd < 0) + { + LogError << "Scoket_Server Accept Failed!"; + return false; + } - std::string ip(inet_ntoa(client_addr.sin_addr)); // 获取客户端IP + std::string ip(inet_ntoa(client_addr.sin_addr)); // 获取客户端IP - LogInfo << ip << " new connection was accepted."; + LogInfo << ip << " new connection was accepted."; - mmap.insert(std::make_pair(new_fd, std::make_pair(ip, 0))); + mmap.insert(std::make_pair(new_fd, std::make_pair(ip, 0))); - // 将新建立的连接的fd加入master_set - FD_SET(new_fd, &master_set); - if (new_fd > max_fd) - { - max_fd = new_fd; - } - return true; + // 将新建立的连接的fd加入master_set + FD_SET(new_fd, &master_set); + if (new_fd > max_fd) + { + max_fd = new_fd; + } + return true; } bool SocketEngine::Recv(int nums) { - for (int fd = 0; fd <= max_fd; ++fd) - { - if (FD_ISSET(fd, &working_set)) - { - bool close_conn = false; // 标记当前连接是否断开了 + for (int fd = 0; fd <= max_fd; ++fd) + { + if (FD_ISSET(fd, &working_set)) + { + bool close_conn = false; // 标记当前连接是否断开了 - char order_str[512] = { 0 }; + char order_str[512] = { 0 }; - int size_get = recv(fd, (char*)&order_str, sizeof(order_str) - 1, 0); + int size_get = recv(fd, (char*)&order_str, sizeof(order_str) - 1, 0); - if (size_get <= 0) - { - continue; - } - else - { + if (size_get <= 0) + { + continue; + } + else + { - bool isHeart_beat = (std::string(order_str) == "matrixai"); - if (isHeart_beat) - { - mmap[fd].second = 0; // 每次收到心跳包,count置0 - //LogDebug << "Scoket_Server Received heart-beat from client."; - } - else - { - LogInfo << "Received message from client:" << std::string(order_str); - } - } + bool isHeart_beat = (std::string(order_str) == "matrixai"); + if (isHeart_beat) + { + mmap[fd].second = 0; // 每次收到心跳包,count置0 + //LogDebug << "Scoket_Server Received heart-beat from client."; + } + else + { + LogInfo << "Received message from client:" << std::string(order_str); + } + } - if (close_conn) // 当前这个连接有问题,关闭它 - { - close(fd); - FD_CLR(fd, &master_set); - if (fd == max_fd) // 需要更新max_fd; - { - while (FD_ISSET(max_fd, &master_set) == false) - --max_fd; - } - } - } - } + if (close_conn) // 当前这个连接有问题,关闭它 + { + close(fd); + FD_CLR(fd, &master_set); + if (fd == max_fd) // 需要更新max_fd; + { + while (FD_ISSET(max_fd, &master_set) == false) + --max_fd; + } + } + } + } - return true; + return true; } bool SocketEngine::Run() { - pthread_t id; // 创建心跳检测线程 - int ret = pthread_create(&id, NULL, heart_handler, (void*)this); - if (ret != 0) - { - LogError << "Scoket_Server Can not create heart-beat checking thread."; - return false; - } + pthread_t id; // 创建心跳检测线程 + int ret = pthread_create(&id, NULL, heart_handler, (void*)this); + if (ret != 0) + { + LogError << "Scoket_Server Can not create heart-beat checking thread."; + return false; + } - ret = pthread_create(&id, NULL, sendInfo, (void*)this); - if (ret != 0) - { - LogError << "Scoket_Server Can not create message send thread."; - return false; - } + ret = pthread_create(&id, NULL, sendInfo, (void*)this); + if (ret != 0) + { + LogError << "Scoket_Server Can not create message send thread."; + return false; + } - max_fd = listen_fd; // 初始化max_fd - FD_ZERO(&master_set); - FD_SET(listen_fd, &master_set); // 添加监听fd + max_fd = listen_fd; // 初始化max_fd + FD_ZERO(&master_set); + FD_SET(listen_fd, &master_set); // 添加监听fd - while (!isStop_) - { - FD_ZERO(&working_set); - memcpy(&working_set, &master_set, sizeof(master_set)); + while (!isStop_) + { + FD_ZERO(&working_set); + memcpy(&working_set, &master_set, sizeof(master_set)); - timeout.tv_sec = 30; - timeout.tv_usec = 0; + timeout.tv_sec = 30; + timeout.tv_usec = 0; - int nums = select(max_fd + 1, &working_set, NULL, NULL, &timeout); - /*if (nums < 0) - { - LogError << "Scoket_Server select() error!"; - return false; - }*/ + int nums = select(max_fd + 1, &working_set, NULL, NULL, &timeout); + /*if (nums < 0) + { + LogError << "Scoket_Server select() error!"; + return false; + }*/ - if (nums <= 0) - { - //cout << "select() is timeout!"; - continue; - } + if (nums <= 0) + { + //cout << "select() is timeout!"; + continue; + } - if (FD_ISSET(listen_fd, &working_set)) - Accept(); // 有新的客户端请求 - else - Recv(nums); // 接收客户端的消息 + if (FD_ISSET(listen_fd, &working_set)) + Accept(); // 有新的客户端请求 + else + Recv(nums); // 接收客户端的消息 - } + } - return true; + return true; } //解析命令 bool SocketEngine::getOrder(const std::string &recv, Json::Value &order) { - Json::CharReaderBuilder readerBuilder; - std::shared_ptr reader(readerBuilder.newCharReader()); + Json::CharReaderBuilder readerBuilder; + std::shared_ptr reader(readerBuilder.newCharReader()); - JSONCPP_STRING errs; - if (!reader->parse(recv.data(), recv.data() + recv.size(), &order, &errs)) - return false; + JSONCPP_STRING errs; + if (!reader->parse(recv.data(), recv.data() + recv.size(), &order, &errs)) + return false; - if (order.isArray()) { - if (order.size() > 0) order = order[0]; - return true; - } - return true; + if (order.isArray()) { + if (order.size() > 0) order = order[0]; + return true; + } + return true; } std::string SocketEngine::getFeedBack(const std::string poundNo, const std::string type, const std::string info) { - Json::Value feedBack; - Json::StreamWriterBuilder strbuild; + Json::Value feedBack; + Json::StreamWriterBuilder strbuild; - feedBack["poundNo"] = poundNo; - feedBack["type"] = type; - feedBack["info"] = info; - // - return Json::writeString(strbuild, feedBack); + feedBack["poundNo"] = poundNo; + feedBack["type"] = type; + feedBack["info"] = info; + // + return Json::writeString(strbuild, feedBack); } void* SocketEngine::sendInfo(void* arg) { - SocketEngine* s = (SocketEngine*)arg; - while (!s->isStop_) { - //pop端口0 - std::shared_ptr pVoidData0 = nullptr; - s->inputQueMap_[s->strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); //1ms - continue; - } + SocketEngine* s = (SocketEngine*)arg; + while (!s->isStop_) { + //pop端口0 + std::shared_ptr pVoidData0 = nullptr; + s->inputQueMap_[s->strPort0_]->pop(pVoidData0); + if (nullptr == pVoidData0) + { + usleep(1000); //1ms + continue; + } - std::shared_ptr pMessage = std::static_pointer_cast(pVoidData0); + std::shared_ptr pMessage = std::static_pointer_cast(pVoidData0); - SendAllClient(s->mmap, *pMessage); - } + SendAllClient(s->mmap, *pMessage); + } } @@ -281,176 +281,176 @@ void* SocketEngine::sendInfo(void* arg) { // thread function void* SocketEngine::heart_handler(void* arg) { - LogInfo << "Scoket_Server The heartbeat checking thread started.\n"; - SocketEngine* s = (SocketEngine*)arg; - while (1) - { - std::map >::iterator it = s->mmap.begin(); - for (; it != s->mmap.end(); ) - { - if (it->second.second == 5) // sleep(3)*5没有收到心跳包,判定客户端掉线 - { - LogInfo << "The client " << it->second.first << " has be offline.\n"; + LogInfo << "Scoket_Server The heartbeat checking thread started.\n"; + SocketEngine* s = (SocketEngine*)arg; + while (1) + { + std::map >::iterator it = s->mmap.begin(); + for (; it != s->mmap.end(); ) + { + if (it->second.second == 5) // sleep(3)*5没有收到心跳包,判定客户端掉线 + { + LogInfo << "The client " << it->second.first << " has be offline.\n"; - int fd = it->first; - close(fd); // 关闭该连接 - FD_CLR(fd, &s->master_set); - if (fd == s->max_fd) // 需要更新max_fd; - { - while (FD_ISSET(s->max_fd, &s->master_set) == false) - s->max_fd--; - } + int fd = it->first; + close(fd); // 关闭该连接 + FD_CLR(fd, &s->master_set); + if (fd == s->max_fd) // 需要更新max_fd; + { + while (FD_ISSET(s->max_fd, &s->master_set) == false) + s->max_fd--; + } - s->mmap.erase(it++); // 从map中移除该记录 - } - else if (it->second.second < 5 && it->second.second >= 0) - { - it->second.second += 1; - ++it; - } - else - { - ++it; - } - } - sleep(3); // 定时三秒 - } + s->mmap.erase(it++); // 从map中移除该记录 + } + else if (it->second.second < 5 && it->second.second >= 0) + { + it->second.second += 1; + ++it; + } + else + { + ++it; + } + } + sleep(1); // 定时三秒 + } } bool SocketEngine::SendClient(std::map > mmap, const std::string ip, const std::string message) { - try - { - std::map >::iterator it = mmap.begin(); - for (; it != mmap.end(); ++it) - { - if (it->second.first == ip) // 遍历找雷达ip - { - int fd = it->first; + try + { + std::map >::iterator it = mmap.begin(); + for (; it != mmap.end(); ++it) + { + if (it->second.first == ip) // 遍历找雷达ip + { + int fd = it->first; - if (send(fd, message.c_str(), message.size(), 0) <= 0) - { - LogError << "Socker Server send message to IP:" << ip << " failed, message:" << message; - return false; - } - else - { - char clientFeedBack[256] = { 0 }; - if (recv(fd, clientFeedBack, sizeof(clientFeedBack), 0) > 0) - { - Json::Value feedBack; + if (send(fd, message.c_str(), message.size(), 0) <= 0) + { + LogError << "Socker Server send message to IP:" << ip << " failed, message:" << message; + return false; + } + else + { + char clientFeedBack[256] = { 0 }; + if (recv(fd, clientFeedBack, sizeof(clientFeedBack), 0) > 0) + { + Json::Value feedBack; - if (!getOrder(clientFeedBack, feedBack)) { - LogError << "Get Client IP:" << ip << " feekBack format is error : " << clientFeedBack; - return false; - } + if (!getOrder(clientFeedBack, feedBack)) { + LogError << "Get Client IP:" << ip << " feekBack format is error : " << clientFeedBack; + return false; + } - if (feedBack.get("success", "").asString() == "true") - { - return true; - } - else - { - LogError << "Client FeedBack Error: " << feedBack.get("error_msg", "").asString(); - return false; - } - } - else { + if (feedBack.get("success", "").asString() == "true") + { + return true; + } + else + { + LogError << "Client FeedBack Error: " << feedBack.get("error_msg", "").asString(); + return false; + } + } + else { - LogError << "Socker Server send message to IP:" << ip << " successful, But recv error!"; - return false; - } - } - } - } - } - catch (const std::exception&) - { - LogError << "Socker Server send message to IP:" << ip << " failed, message:" << message; - return false; - } - LogError << "Socker Server send message to IP:" << ip << " failed, because no find connection"; - return false; + LogError << "Socker Server send message to IP:" << ip << " successful, But recv error!"; + return false; + } + } + } + } + } + catch (const std::exception&) + { + LogError << "Socker Server send message to IP:" << ip << " failed, message:" << message; + return false; + } + LogError << "Socker Server send message to IP:" << ip << " failed, because no find connection"; + return false; } bool SocketEngine::SendAllClient(std::map > mmap, const std::string message) { - try - { - std::map >::iterator it = mmap.begin(); - for (; it != mmap.end(); ++it) - { - int fd = it->first; - LogInfo << "Socket send IP: " << it->second.first << " msg:" << message; - if (send(fd, message.c_str(), message.size(), MSG_NOSIGNAL) <= 0) - { - LogError << "Socker Server send message to IP:" << it->second.first << " failed, message:" << message; - return false; - } - else - { - // char clientFeedBack[256] = { 0 }; - // if (recv(fd, clientFeedBack, sizeof(clientFeedBack), 0) > 0) - // { - // Json::Value feedBack; + try + { + std::map >::iterator it = mmap.begin(); + for (; it != mmap.end(); ++it) + { + int fd = it->first; + LogInfo << "Socket send IP: " << it->second.first << " msg:" << message; + if (send(fd, message.c_str(), message.size(), MSG_NOSIGNAL) <= 0) + { + LogError << "Socker Server send message to IP:" << it->second.first << " failed, message:" << message; + return false; + } + else + { + // char clientFeedBack[256] = { 0 }; + // if (recv(fd, clientFeedBack, sizeof(clientFeedBack), 0) > 0) + // { + // Json::Value feedBack; - // if (!getOrder(clientFeedBack, feedBack)) { - // LogError << "Get Client IP: "<< it->second.first << " feekBack format is error : " << clientFeedBack; - // return false; - // } + // if (!getOrder(clientFeedBack, feedBack)) { + // LogError << "Get Client IP: "<< it->second.first << " feekBack format is error : " << clientFeedBack; + // return false; + // } - // if (feedBack.get("success", "").asString() == "true") - // { - // return true; - // } - // else - // { - // LogError << "Client FeedBack Error: " << feedBack.get("error_msg", "").asString(); - // return false; - // } - // } - // else { + // if (feedBack.get("success", "").asString() == "true") + // { + // return true; + // } + // else + // { + // LogError << "Client FeedBack Error: " << feedBack.get("error_msg", "").asString(); + // return false; + // } + // } + // else { - // LogError << "Socker Server send message to IP:" << it->second.first << " successful, But recv error!"; - // return false; - // } - } - } - } - catch (const std::exception&) - { - LogError << "Socker Server send message to all client failed, message:" << message; - return false; - } - return false; + // LogError << "Socker Server send message to IP:" << it->second.first << " successful, But recv error!"; + // return false; + // } + } + } + } + catch (const std::exception&) + { + LogError << "Socker Server send message to all client failed, message:" << message; + return false; + } + return false; } std::string SocketEngine::HexToStr(const std::string &str) { - std::string hex = str; - long len = hex.length(); - std::string newString; - for (long i = 0; i < len; i += 2) - { - std::string byte = hex.substr(i, 2); - char chr = (char)(int)strtol(byte.c_str(), NULL, 16); - newString.push_back(chr); - } - return newString; + std::string hex = str; + long len = hex.length(); + std::string newString; + for (long i = 0; i < len; i += 2) + { + std::string byte = hex.substr(i, 2); + char chr = (char)(int)strtol(byte.c_str(), NULL, 16); + newString.push_back(chr); + } + return newString; } std::string SocketEngine::StrToHex(const std::string &str) { - unsigned char c; - char buf[2]; - std::string result = ""; - std::stringstream ss; - ss << str; - while (ss.read((char*)(&c), sizeof(c))) - { - sprintf(buf, "%02x", c); - result += buf; - } - return result; + unsigned char c; + char buf[2]; + std::string result = ""; + std::stringstream ss; + ss << str; + while (ss.read((char*)(&c), sizeof(c))) + { + sprintf(buf, "%02x", c); + result += buf; + } + return result; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/TrainAnaEngine/TrainParationMgr.cpp b/nvidia_ascend_engine/common_engine/TrainAnaEngine/TrainParationMgr.cpp index 98ba244..ad62c5d 100644 --- a/nvidia_ascend_engine/common_engine/TrainAnaEngine/TrainParationMgr.cpp +++ b/nvidia_ascend_engine/common_engine/TrainAnaEngine/TrainParationMgr.cpp @@ -1 +1 @@ -#include "TrainParationMgr.h" using namespace ai_matrix; TrainParationMgr::TrainParationMgr() {} TrainParationMgr::~TrainParationMgr() {} APP_ERROR TrainParationMgr::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); //获取主摄像头信息 mainCfg_ = MyYaml::GetIns()->GetDataSourceConfigById(0); nFrameRate = 25; InitParam(); nTailPixOffset = getTailPixOffset(); LogInfo << "TrainParationMgr Init ok"; return APP_ERR_OK; } APP_ERROR TrainParationMgr::DeInit() { LogInfo << "TrainParationMgr DeInit ok"; return APP_ERR_OK; } int TrainParationMgr::getTailPixOffset() { LogInfo << "TrainParationMgr getTailPixOffset start"; // 单位计算 // 帧宽像素/米 float fframewidth_meter = ((METHOD_BASE_WIDTH * 1.0) / (TRAIN_IN_CAMERA_WIDTH)); // 车尾车钩像素位置 float fOffsetPosistion = TRAIN_WIDTH * fframewidth_meter; int nretOffset = (int)fOffsetPosistion; return nretOffset; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void TrainParationMgr::InitParam() { } /** * 计算车钩移动的像素值 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::getCouplerOffsetPosition(float fspeed, int nframeindex) { LogInfo << "TrainAnaEngine getCouplerOffsetPosition start"; //单位换算 // 米/秒 -> 米/帧 // 米/帧 = 米/秒 * 秒/帧(即:1/帧率) float fmeter_frame = fspeed / nFrameRate; // 米/帧 -> 像素/帧 // 像素/帧 = 米/帧 * 像素/米 float fpix_frame = fmeter_frame * (METHOD_BASE_WIDTH / TRAIN_IN_CAMERA_WIDTH); int nretPixOffet = (int)fpix_frame; nretPixOffet = nretPixOffet * nframeindex; LogInfo << "TrainAnaEngine getCouplerOffsetPosition nretPixOffet:" << nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPosition end"; return nretPixOffet; } /** * 计算车钩移动的像素值 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::getCouplerOffsetPix(float fspeed, int noffsetPix) { LogInfo << "TrainAnaEngine getCouplerOffsetPix start"; LogInfo << "TrainAnaEngine getCouplerOffsetPix fspeed:" << fspeed; // LogInfo << "TrainAnaEngine getCouplerOffsetPix start:" << nframeindex; //单位换算 // 米/秒 -> 米/帧 // 米/帧 = 米/秒 * 秒/帧(即:1/帧率) float fmeter_frame = fspeed / nFrameRate; LogInfo << "TrainAnaEngine getCouplerOffsetPix fmeter_frame:" << fmeter_frame; // 米/帧 -> 像素/帧 // 像素/帧 = 米/帧 * 像素/米 float fpix_frame = fmeter_frame * (METHOD_BASE_WIDTH / TRAIN_IN_CAMERA_WIDTH); LogInfo << "TrainAnaEngine getCouplerOffsetPix fpix_frame:" << fpix_frame; int nretPixOffet = (int)fpix_frame; nretPixOffet = (noffsetPix - (METHOD_BASE_WIDTH / 2)) / nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPix nretPixOffet:" << nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPix end"; return nretPixOffet; } /** * 计算车钩从中间到边缘的间隔帧 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::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; } APP_ERROR TrainParationMgr::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pPartionInfo = std::static_pointer_cast(pVoidData0); int nSize = lstPartInfo.size(); int nPartionIndex = nSize - 1; //当然车厢通过的数量 if (nSize == 0) { PartionInfo stTempInfo; stTempInfo.endframe = pPartionInfo->modelSpaceFrame; stTempInfo.i64EndTimeStamp = pPartionInfo->i64EndTimeStamp; stTempInfo.nindex = 1; //第一节车厢开始帧为跳帧数,开始帧时间设置为来车时间 stTempInfo.startframe = mainCfg_.iSkipInterval; std::string strTemp = pPartionInfo->strTrainDate + " " + pPartionInfo->strTrainName; stTempInfo.i64StartTimeStamp = MyUtils::getins()->GetParamTimeMilliSeconds(strTemp); stTempInfo.fspeed = TRAIN_DEFAULT_SPEED; stTempInfo.fLTX = (abs(pPartionInfo->fLTX - pPartionInfo->fRBX) / 2) + pPartionInfo->fLTX; lstPartInfo.push_back(stTempInfo); //lstPartInfo.push_back(stTempInfo); nPartionIndex++; } lstPartInfo[nPartionIndex].i64EndTimeStamp = pPartionInfo->i64EndTimeStamp; lstPartInfo[nPartionIndex].endframe = pPartionInfo->modelSpaceFrame; // 根据开始帧时间戳和结束帧时间错 计算当节车厢的行车速度 // 根据时间戳计算时间差 float nTimePassed = (abs(lstPartInfo[nPartionIndex].i64EndTimeStamp - lstPartInfo[nPartionIndex].i64StartTimeStamp)) * 1.0; //防止停车导致速度过小 if(pPartionInfo->nStatus != TRAIN_PAUSE && nTimePassed <= 50000) { lstPartInfo[nPartionIndex].fspeed = (TRAIN_WIDTH * 1000.0) /nTimePassed; } else { if (nPartionIndex >= 1){ lstPartInfo[nPartionIndex].fspeed = lstPartInfo[nPartionIndex - 1].fspeed / 3; } else { lstPartInfo[nPartionIndex].fspeed = TRAIN_DEFAULT_SPEED / 10; } } // //nSamePartionIgnoreCount = (nTimePassed / (3 * 5000)) * nFrameRate; // 结束帧为当前帧再往后 (除以2的原因:中间为车钩,车钩后的车体宽度为整个镜头的宽度除以2) lstPartInfo[nPartionIndex].bmodelconfirmed = true; /// write json info to file //先读取文本内容,追加新的信息后再写入 //划分信息 JSON格式 Json::Value jvPartionInfo; //JSON保存路径 std::string strFilePath; //检测到车厢划分信息 strFilePath = strResultPath_ + pPartionInfo->strTrainDate + "/" + pPartionInfo->strTrainName + "/" + std::to_string(nPartionIndex + 1) + ".txt"; LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].startframe:" << lstPartInfo[nPartionIndex].startframe ; LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].endframe:" << lstPartInfo[nPartionIndex].endframe; PartionInfo stTempInfo; // 开始记录新的一节车厢信息(从索引变成序号+1 ,新增一节车厢信息+1) stTempInfo.nindex = nPartionIndex + 2; // 上一节车厢的结束帧 - (偏移帧 = (镜头内的车体宽度/ (速度) -> 通过时间) * 帧/秒 ) 作为下一节车厢的开始帧 int ntempOffsetFrame = lstPartInfo[nPartionIndex].endframe; stTempInfo.startframe = ntempOffsetFrame; stTempInfo.i64StartTimeStamp = pPartionInfo->i64EndTimeStamp; // 初始化下一节的结束帧 //stTempInfo.endframe = 0; lstPartInfo.push_back(stTempInfo); // 记录过车日期 jvPartionInfo["trainDate"] = pPartionInfo->strTrainDate; // 记录过车时间 jvPartionInfo["trainName"] = pPartionInfo->strTrainName; // 记录车厢节数 (索引从0开始 所以这里+1) jvPartionInfo["trainNo"] = nPartionIndex + 1; // 记录行车开始帧 jvPartionInfo["startFrameId"] = lstPartInfo[nPartionIndex].startframe; jvPartionInfo["startTimeStamp"] = lstPartInfo[nPartionIndex].i64StartTimeStamp; // 记录行车结束帧 jvPartionInfo["endFrameId"] = lstPartInfo[nPartionIndex].endframe; jvPartionInfo["endTimeStamp"] = lstPartInfo[nPartionIndex].i64EndTimeStamp; // 记录车厢是否完全通过 jvPartionInfo["isEnd"] = pPartionInfo->bIsEnd; //是否是间隔模型切分的车厢 jvPartionInfo["modelconfirmed"] = pPartionInfo->bmodelconfirmed; // 记录当前车厢的信息到JSON文件 MyUtils::getins()->WriteJsonInfo(jvPartionInfo, strFilePath); std::shared_ptr pTrainRange = std::make_shared(); pTrainRange->strTrainDate = jvPartionInfo["trainDate"].asString(); pTrainRange->strTrainName = jvPartionInfo["trainName"].asString(); pTrainRange->iTrainIndex = jvPartionInfo["trainNo"].asInt(); pTrainRange->iStartFrameId = jvPartionInfo["startFrameId"].asInt(); pTrainRange->i64StartTimeStamp = jvPartionInfo["startTimeStamp"].asInt64(); pTrainRange->iEndFrameId = jvPartionInfo["endFrameId"].asInt(); pTrainRange->i64EndTimeStamp = jvPartionInfo["endTimeStamp"].asInt64(); pTrainRange->bIsEnd = jvPartionInfo["isEnd"].asBool(); pTrainRange->bmodelconfirmed = jvPartionInfo["modelconfirmed"].asBool(); iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pTrainRange)); if (pPartionInfo->bIsEnd) { lstPartInfo.clear(); } } return APP_ERR_OK; } \ No newline at end of file +#include "TrainParationMgr.h" using namespace ai_matrix; TrainParationMgr::TrainParationMgr() {} TrainParationMgr::~TrainParationMgr() {} APP_ERROR TrainParationMgr::Init() { strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); //获取主摄像头信息 mainCfg_ = MyYaml::GetIns()->GetDataSourceConfigById(0); nFrameRate = 25; InitParam(); nTailPixOffset = getTailPixOffset(); LogInfo << "TrainParationMgr Init ok"; return APP_ERR_OK; } APP_ERROR TrainParationMgr::DeInit() { LogInfo << "TrainParationMgr DeInit ok"; return APP_ERR_OK; } int TrainParationMgr::getTailPixOffset() { LogInfo << "TrainParationMgr getTailPixOffset start"; // 单位计算 // 帧宽像素/米 float fframewidth_meter = ((METHOD_BASE_WIDTH * 1.0) / (TRAIN_IN_CAMERA_WIDTH)); // 车尾车钩像素位置 float fOffsetPosistion = TRAIN_WIDTH * fframewidth_meter; int nretOffset = (int)fOffsetPosistion; return nretOffset; } /** * 参数初始化(列车结束时需调用) * inParam : N/A * outParam: N/A * return : N/A */ void TrainParationMgr::InitParam() { } /** * 计算车钩移动的像素值 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::getCouplerOffsetPosition(float fspeed, int nframeindex) { LogInfo << "TrainAnaEngine getCouplerOffsetPosition start"; //单位换算 // 米/秒 -> 米/帧 // 米/帧 = 米/秒 * 秒/帧(即:1/帧率) float fmeter_frame = fspeed / nFrameRate; // 米/帧 -> 像素/帧 // 像素/帧 = 米/帧 * 像素/米 float fpix_frame = fmeter_frame * (METHOD_BASE_WIDTH / TRAIN_IN_CAMERA_WIDTH); int nretPixOffet = (int)fpix_frame; nretPixOffet = nretPixOffet * nframeindex; LogInfo << "TrainAnaEngine getCouplerOffsetPosition nretPixOffet:" << nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPosition end"; return nretPixOffet; } /** * 计算车钩移动的像素值 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::getCouplerOffsetPix(float fspeed, int noffsetPix) { LogInfo << "TrainAnaEngine getCouplerOffsetPix start"; LogInfo << "TrainAnaEngine getCouplerOffsetPix fspeed:" << fspeed; // LogInfo << "TrainAnaEngine getCouplerOffsetPix start:" << nframeindex; //单位换算 // 米/秒 -> 米/帧 // 米/帧 = 米/秒 * 秒/帧(即:1/帧率) float fmeter_frame = fspeed / nFrameRate; LogInfo << "TrainAnaEngine getCouplerOffsetPix fmeter_frame:" << fmeter_frame; // 米/帧 -> 像素/帧 // 像素/帧 = 米/帧 * 像素/米 float fpix_frame = fmeter_frame * (METHOD_BASE_WIDTH / TRAIN_IN_CAMERA_WIDTH); LogInfo << "TrainAnaEngine getCouplerOffsetPix fpix_frame:" << fpix_frame; int nretPixOffet = (int)fpix_frame; nretPixOffet = (noffsetPix - (METHOD_BASE_WIDTH / 2)) / nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPix nretPixOffet:" << nretPixOffet; LogInfo << "TrainAnaEngine getCouplerOffsetPix end"; return nretPixOffet; } /** * 计算车钩从中间到边缘的间隔帧 * inParam : 行车速度(单位:米/秒) * inParam : 宽度 * inParam : 相机帧率(单位:帧/秒) * outParam: N/A * return : 间隔帧 */ int TrainParationMgr::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; } APP_ERROR TrainParationMgr::Process() { int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pPartionInfo = std::static_pointer_cast(pVoidData0); int nSize = lstPartInfo.size(); int nPartionIndex = nSize - 1; //当然车厢通过的数量 if (nSize == 0) { PartionInfo stTempInfo; stTempInfo.endframe = pPartionInfo->modelSpaceFrame; stTempInfo.i64EndTimeStamp = pPartionInfo->i64EndTimeStamp; stTempInfo.nindex = 1; //第一节车厢开始帧为跳帧数,开始帧时间设置为来车时间 stTempInfo.startframe = mainCfg_.iSkipInterval; std::string strTemp = pPartionInfo->strTrainDate + " " + pPartionInfo->strTrainName; stTempInfo.i64StartTimeStamp = MyUtils::getins()->GetParamTimeMilliSeconds(strTemp); // LogWarn << "日期:" << strTemp << " -- 时间戳:" << stTempInfo.i64StartTimeStamp; stTempInfo.fspeed = TRAIN_DEFAULT_SPEED; stTempInfo.fLTX = (abs(pPartionInfo->fLTX - pPartionInfo->fRBX) / 2) + pPartionInfo->fLTX; lstPartInfo.push_back(stTempInfo); //lstPartInfo.push_back(stTempInfo); nPartionIndex++; } lstPartInfo[nPartionIndex].i64EndTimeStamp = pPartionInfo->i64EndTimeStamp; lstPartInfo[nPartionIndex].endframe = pPartionInfo->modelSpaceFrame; // 根据开始帧时间戳和结束帧时间错 计算当节车厢的行车速度 // 根据时间戳计算时间差 float nTimePassed = (abs(lstPartInfo[nPartionIndex].i64EndTimeStamp - lstPartInfo[nPartionIndex].i64StartTimeStamp)) * 1.0; //防止停车导致速度过小 if(pPartionInfo->nStatus != TRAIN_PAUSE && nTimePassed <= 50000) { lstPartInfo[nPartionIndex].fspeed = (TRAIN_WIDTH * 1000.0) /nTimePassed; } else { if (nPartionIndex >= 1){ lstPartInfo[nPartionIndex].fspeed = lstPartInfo[nPartionIndex - 1].fspeed / 3; } else { lstPartInfo[nPartionIndex].fspeed = TRAIN_DEFAULT_SPEED / 10; } } // //nSamePartionIgnoreCount = (nTimePassed / (3 * 5000)) * nFrameRate; // 结束帧为当前帧再往后 (除以2的原因:中间为车钩,车钩后的车体宽度为整个镜头的宽度除以2) lstPartInfo[nPartionIndex].bmodelconfirmed = true; /// write json info to file //先读取文本内容,追加新的信息后再写入 //划分信息 JSON格式 Json::Value jvPartionInfo; //JSON保存路径 std::string strFilePath; //检测到车厢划分信息 strFilePath = strResultPath_ + pPartionInfo->strTrainDate + "/" + pPartionInfo->strTrainName + "/" + std::to_string(nPartionIndex + 1) + ".txt"; LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].startframe:" << lstPartInfo[nPartionIndex].startframe ; LogInfo << "TrainAnaEngine Process lstPartInfo[nPartionIndex].endframe:" << lstPartInfo[nPartionIndex].endframe; PartionInfo stTempInfo; // 开始记录新的一节车厢信息(从索引变成序号+1 ,新增一节车厢信息+1) stTempInfo.nindex = nPartionIndex + 2; // 上一节车厢的结束帧 - (偏移帧 = (镜头内的车体宽度/ (速度) -> 通过时间) * 帧/秒 ) 作为下一节车厢的开始帧 int ntempOffsetFrame = lstPartInfo[nPartionIndex].endframe; stTempInfo.startframe = ntempOffsetFrame; stTempInfo.i64StartTimeStamp = pPartionInfo->i64EndTimeStamp; // 初始化下一节的结束帧 //stTempInfo.endframe = 0; lstPartInfo.push_back(stTempInfo); // 记录过车日期 jvPartionInfo["trainDate"] = pPartionInfo->strTrainDate; // 记录过车时间 jvPartionInfo["trainName"] = pPartionInfo->strTrainName; // 记录车厢节数 (索引从0开始 所以这里+1) jvPartionInfo["trainNo"] = nPartionIndex + 1; // 记录行车开始帧 jvPartionInfo["startFrameId"] = lstPartInfo[nPartionIndex].startframe; jvPartionInfo["startTimeStamp"] = lstPartInfo[nPartionIndex].i64StartTimeStamp; // 记录行车结束帧 jvPartionInfo["endFrameId"] = lstPartInfo[nPartionIndex].endframe; jvPartionInfo["endTimeStamp"] = lstPartInfo[nPartionIndex].i64EndTimeStamp; // 记录车厢是否完全通过 jvPartionInfo["isEnd"] = pPartionInfo->bIsEnd; //是否是间隔模型切分的车厢 jvPartionInfo["modelconfirmed"] = pPartionInfo->bmodelconfirmed; // 记录当前车厢的信息到JSON文件 MyUtils::getins()->WriteJsonInfo(jvPartionInfo, strFilePath); std::shared_ptr pTrainRange = std::make_shared(); pTrainRange->strTrainDate = jvPartionInfo["trainDate"].asString(); pTrainRange->strTrainName = jvPartionInfo["trainName"].asString(); pTrainRange->iTrainIndex = jvPartionInfo["trainNo"].asInt(); pTrainRange->iStartFrameId = jvPartionInfo["startFrameId"].asInt(); pTrainRange->i64StartTimeStamp = jvPartionInfo["startTimeStamp"].asInt64(); pTrainRange->iEndFrameId = jvPartionInfo["endFrameId"].asInt(); pTrainRange->i64EndTimeStamp = jvPartionInfo["endTimeStamp"].asInt64(); pTrainRange->bIsEnd = jvPartionInfo["isEnd"].asBool(); pTrainRange->bmodelconfirmed = jvPartionInfo["modelconfirmed"].asBool(); iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pTrainRange)); if (pPartionInfo->bIsEnd) { lstPartInfo.clear(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/common_engine/TransEngine/TransTrainEngine.cpp b/nvidia_ascend_engine/common_engine/TransEngine/TransTrainEngine.cpp index c66fa42..0854254 100644 --- a/nvidia_ascend_engine/common_engine/TransEngine/TransTrainEngine.cpp +++ b/nvidia_ascend_engine/common_engine/TransEngine/TransTrainEngine.cpp @@ -1,840 +1 @@ -#include "TransTrainEngine.h" -#include "myutils.h" -#include -#include - -using namespace ai_matrix; - -namespace -{ - //按照x坐标排列 - bool CompareX(const SingleData &v1, const SingleData &v2) - { - return (v1.fLTX < v2.fLTX); - } - - //自定义比较规则 - bool CmpVec(const pair &P1, const pair &P2) - { - return P1.second < P2.second; - } -} - -TransTrainEngine::TransTrainEngine() {} - -TransTrainEngine::~TransTrainEngine() {} - -APP_ERROR TransTrainEngine::Init() -{ - bUseEngine_ = MyUtils::getins()->ChkIsHaveTarget("NUM"); - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - modelConfig_ = MyYaml::GetIns()->GetModelConfig("TrainStepTwoEngine"); - strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); - - //读取模型参数信息文件 - Json::Value jvModelInfo; - if (!MyUtils::getins()->ReadJsonInfo(jvModelInfo, modelConfig_.strModelInfoPath)) - { - LogError << "ModelInfoPath:" << modelConfig_.strModelInfoPath << " doesn't exist or read failed!"; - return APP_ERR_COMM_NO_EXIST; - } - for (int i = 0; i < jvModelInfo["class"].size(); i++) - { - vecClassNames_.push_back(jvModelInfo["class"][i].asString()); - } - - // 获取几个摄像头识别车号 - std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); - for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) - { - iSkipInterval_ = iter->second.iSkipInterval; - if (iter->second.strTarget.find("NUM") != std::string::npos) - { - LogDebug << "sourceid:" << iter->first << " deal Num"; - mapDataSourceIsEnd_[iter->first] = false; - } - } - - InitParam(); - LogInfo << "TransTrainEngine Init ok"; - return APP_ERR_OK; -} - -APP_ERROR TransTrainEngine::DeInit() -{ - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - LogInfo << "TransTrainEngine DeInit ok"; - return APP_ERR_OK; -} - -/** -* 初始化参数信息 -* inParam : N/A -* outParam: N/A -* return : N/A -*/ -void TransTrainEngine::InitParam() -{ - for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) - { - iter->second = false; - } - mapNumInfo_.clear(); - mapPreFrameId_.clear(); -} - -/** - * 校验车型是否符合验证 - * inParam : int classId 大框类别id - * : const std::string &trainNum 车型字符信息 - * outParam: N/A - * return : true:符合; false:不符合 - */ -bool TransTrainEngine::AuthTransNum(int classId, const std::string &trainNum) -{ -// LogInfo << "classId:" << classId << " trainNum:" << trainNum; - switch (classId) - { - case TRAIN_HEAD: // 车头上的编号 - break; - case K_TRAIN_NUM: // 编号 矿车、煤炭漏斗车(兖矿自备、枣矿自备) - { - if (trainNum == "K13" || trainNum == "KM100AH") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 4: - reg = "^K[1FMZ]{1}[36789]{1}[018ABKNT]{1}"; - break; - case 5: - reg = "^K[1M]{1}[368]{1}[1ABDN]{1}[AGKNT]{1}"; - break; - case 6: - reg = "^K[MF]{1}[69]{1}[80]{1}A[KH]{1}"; - break; - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - case C_TRAIN_NUM: // 敞车 特殊车型 C5D CF CFK - { - if (trainNum == "CF" || trainNum == "C62A(N)") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 3: - reg = "^C[15678F]{1}[0123456DK]{1}"; - break; - case 4: - reg = "^C[1678]{1}[012346]{1}[0ABCEFHKMTY]{1}"; - break; - case 5: - reg = "^C[1678]{1}[01246]{1}[0ABCEY]{1}[KAFHNT]{1}"; - break; - case 6: - reg = "^C[17]{1}0[0E]{1}[A-]{1}[AH]{1}"; - break; - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - case P_TRAIN_NUM: // 编号 棚车 - { - if (trainNum == "P70(H)" || trainNum == "P62(N)") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 3: - reg = "^P[1678]{1}[012345]{1}"; - break; - case 4: - reg = "^P[678]{1}[023456]{1}[ABHKNST]{1}"; - break; - case 5: - reg = "^P6[24]{1}[ANG]{1}[KT]{1}"; - break; - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - case G_TRAIN_NUM: // 编号 罐车 - { - if (trainNum == "GY100SK") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 2: - reg = "^G[HLS]{1}"; - break; - case 3: - reg = "^[GL]{1}[1567HL]{1}[01246789K]{1}"; - break; - case 4: - reg = "^[GU]{1}[167FJLNQSWY]{1}[170689]{1}[KSABDGTM075W]{1}"; - break; - case 5: - reg = "^[GU]{1}[17FHNQY6]{1}[1706A89]{1}[SBDAM057W]{1}[KEHTB0ZAS]{1}"; - break; - case 6: - reg = "^[UG]{1}[6YH]{1}[1489A]{1}[057W]{1}[Z0LSA]{1}[KSAT]{1}"; - break; - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - case NX_TRAIN_NUM: // 编号 平车 - { - if (trainNum == "N6") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 3: - reg = "^[NQX]{1}[1234678T]{1}[0124567HK]{1}"; - break; - case 4: - reg = "^[BNX]{1}[16X]{1}[17BC]{1}[07AGKT]{1}"; - break; - case 5: - reg = "^[NX]{1}[16NX]{1}[17C]{1}[07AGT]{1}[KTABH]{1}"; - break; - case 6: - reg = "^NX17[AB]{1}[KTH]{1}"; - break; - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - case J_TRAIN_NUM: // 编号 牲畜车 特种车 - { - if (trainNum == "TP64GK") - { - return true; - } - std::regex reg; - switch (trainNum.size()) - { - case 2: - reg = "^[DT]{1}[2678]{1}"; - break; - case 3: - reg = "^[DST]{1}[12346789LQ]{1}[012578ADFGP]{1}"; - break; - case 4: - reg = "^[DJNT]{1}[12356AFKQS]{1}[012345678DFQS]{1}[A12345679GHKQ]{1}"; - break; - case 5: - reg = "^[DJQT]{1}[2KNSH1P]{1}[613XQ2]{1}[A761234B]{1}[KA70G]{1}"; - break; - default: - LogWarn << "Unknow train, classId: " << classId << " trainNum:" << trainNum; - return false; - } - return std::regex_match(trainNum, reg); - } - default: - LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; - return false; - } - return true; -} - -/** -* 过滤第二步字段代号的误识别 -* inParam : std::vector &vecObjs -* : TargetMaxLen iMaxLen -* outParam: N/A -* return : N/A -*/ -void TransTrainEngine::FilterSingleData(std::vector &vecObjs, TargetMaxLen iMaxLen) -{ - /*误识别场景 - 例: 车厢容积属性只有2位时,但因误识别导致自重的某个字符字段代号错误,划归到容积中,这样实际只有2位的容积变为3位。导致选优时错误。 - 只处理1个字段代号的误识别,若有多个字段代号同时错误,无法区分哪些字符字段代号是正确的。(字段代号误识别较多时,则增强模型训练) - - 排除一个最大和最小值后计算平局坐标值,每个框左上角和平局值左上角高度差大于平局值的高度则剔除. - */ - if (vecObjs.size() != iMaxLen || vecObjs.size() <= 2) - { - return; - } - - std::deque dqObjs(vecObjs.begin(), vecObjs.end()); - std::sort(dqObjs.begin(), dqObjs.end(), [](SingleData &a, SingleData &b) - { - return a.fLTY < b.fLTY; - }); - dqObjs.pop_front(); - dqObjs.pop_back(); - - SingleData singleDataAvg; - for (auto iter = dqObjs.begin(); iter != dqObjs.end(); iter++) - { - singleDataAvg.fLTX += iter->fLTX; - singleDataAvg.fLTY += iter->fLTY; - singleDataAvg.fRBX += iter->fRBX; - singleDataAvg.fRBY += iter->fRBY; - } - singleDataAvg.fLTX = singleDataAvg.fLTX / dqObjs.size(); - singleDataAvg.fLTY = singleDataAvg.fLTY / dqObjs.size(); - singleDataAvg.fRBX = singleDataAvg.fRBX / dqObjs.size(); - singleDataAvg.fRBY = singleDataAvg.fRBY / dqObjs.size(); - float fAvgHeight = singleDataAvg.fRBY - singleDataAvg.fLTY; - - //剔除位置错误的字符信息 - for (auto iter = vecObjs.begin(); iter != vecObjs.end(); iter++) - { - float fTemp = fabs(iter->fLTY - singleDataAvg.fLTY); - if (fTemp > (fAvgHeight - 5)) - { - std::string strOne = vecClassNames_.at(iter->iClassId); - LogWarn << "engineId:" << engineId_ << " " << strOne << " Line wrong "; - vecObjs.erase(iter); - break; - } - } -} - -/** -* 属性框内容转换 -* inParam : std::map> &mapLine -* outParam: TransSubData &transSubData -* return : N/A -*/ -void TransTrainEngine::TransPro(TransSubData &transSubData, std::map> &mapLine) -{ - //载重 - if (mapLine.find(0) != mapLine.end()) - { - TransInfo loadInfo; - loadInfo.iLine = 0; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(0).size(); j++) - { - //过滤非数字 - std::string strOne = vecClassNames_.at(mapLine.at(0).at(j).iClassId); - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in load"; - continue; - } - strTemp += strOne; - loadInfo.vecValue.emplace_back(strOne); - loadInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); - transSubData.fScoreSum += mapLine.at(0).at(j).fScore; - } - - //匹配正则表达式 - //std::regex reg("^[0-9]{2}"); - std::regex reg("^[1,4,5,6,7,8,9]{1}[0-9]{1,2}$"); //(第1位:棚车:4 5; K自备车:1 5 7 8 9; 平车:7; 罐车:6 7; 敞车:6 7 8) - if (std::regex_match(strTemp, reg)) - { - loadInfo.IsChkFlag = true; - } - transSubData.vecTransInfo.emplace_back(loadInfo); - } - - //自重 - if (mapLine.find(1) != mapLine.end()) - { - FilterSingleData(mapLine.at(1), SELF_MAXLEN); - TransInfo selfInfo; - selfInfo.iLine = 1; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(1).size(); j++) - { - //过滤非数字 - std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in self"; - continue; - } - strTemp += strOne; - selfInfo.vecValue.emplace_back(strOne); - selfInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); - transSubData.fScoreSum += mapLine.at(1).at(j).fScore; - } - - //匹配正则表达式 - std::regex reg("^[1,2,3]{1}[0-9]{1,2}$"); - if (std::regex_match(strTemp, reg)) - { - selfInfo.IsChkFlag = true; - } - transSubData.vecTransInfo.emplace_back(selfInfo); - } - - //容积 - if (mapLine.find(2) != mapLine.end()) - { - FilterSingleData(mapLine.at(2), VOLUME_MAXLEN); - TransInfo volumeInfo; - volumeInfo.iLine = 2; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(2).size(); j++) - { - //过滤非数字 - std::string strOne = vecClassNames_.at(mapLine.at(2).at(j).iClassId); - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in volume"; - continue; - } - strTemp += strOne; - volumeInfo.vecValue.emplace_back(strOne); - volumeInfo.vecScore.emplace_back(mapLine.at(2).at(j).fScore); - transSubData.fScoreSum += mapLine.at(2).at(j).fScore; - } - - //匹配正则表达式 - //std::regex reg("^[0-9]{2,3}$"); - std::regex reg("^[1,6,7,8,9]{1}[0-9]{1,2}$"); //(第1位:棚车:1; K自备车:1或9; 罐车:6或7; 敞车:7或8) - if (std::regex_match(strTemp, reg)) - { - volumeInfo.IsChkFlag = true; - } - transSubData.vecTransInfo.emplace_back(volumeInfo); - } - - //换长 - if (mapLine.find(3) != mapLine.end()) - { - TransInfo changeInfo; - changeInfo.iLine = 3; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(3).size(); j++) - { - //过滤非数字 - std::string strOne = vecClassNames_.at(mapLine.at(3).at(j).iClassId); - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in change"; - continue; - } - strTemp += strOne; - changeInfo.vecValue.emplace_back(strOne); - changeInfo.vecScore.emplace_back(mapLine.at(3).at(j).fScore); - transSubData.fScoreSum += mapLine.at(3).at(j).fScore; - } - - //匹配正则表达式 - //std::regex reg("^[0-9]{2}$"); - std::regex reg("^[1]{1}[0-9]{1}$"); - if (std::regex_match(strTemp, reg)) - { - changeInfo.IsChkFlag = true; - } - transSubData.vecTransInfo.emplace_back(changeInfo); - } - - //罐车容量计表 - if (mapLine.find(4) != mapLine.end()) - { - TransInfo volumeSurfaceInfo; - volumeSurfaceInfo.iLine = 4; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(4).size(); j++) - { - strTemp += vecClassNames_.at(mapLine.at(4).at(j).iClassId); - volumeSurfaceInfo.vecValue.emplace_back(vecClassNames_.at(mapLine.at(4).at(j).iClassId)); - volumeSurfaceInfo.vecScore.emplace_back(mapLine.at(4).at(j).fScore); - transSubData.fScoreSum += mapLine.at(4).at(j).fScore; - } - - volumeSurfaceInfo.IsChkFlag = true; //暂不校验 - transSubData.vecTransInfo.emplace_back(volumeSurfaceInfo); - } -} - -/** -* 车号框内容转换 -* inParam : std::map> &mapLine -* outParam: TransSubData &transSubData -* return : N/A -*/ -void TransTrainEngine::TransNum(TransSubData &transSubData, std::map> &mapLine) -{ - //车型 - if (mapLine.find(0) != mapLine.end()) - { - TransInfo typeInfo; - typeInfo.iLine = 0; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(0).size(); j++) - { - std::string strOne = vecClassNames_.at(mapLine.at(0).at(j).iClassId); - - /*20230117 该逻辑删除,有厂区发现有C70C DF4DD等车型。 针对重复印刷的场景需想其他方法处理。 - //注:车型多次印刷会导致之前印刷的个别字符会识别,导致最终的识别内容变多。针对车型没有重复字符的特点,因此剔除重复的字符 - auto iter = find(typeInfo.vecValue.begin(), typeInfo.vecValue.end(), strOne); - if (iter != typeInfo.vecValue.end()) - { - LogWarn << "Possible duplicate recognition strOne:" << strOne; - continue; - } - */ - - strTemp += strOne; - typeInfo.vecValue.emplace_back(strOne); - typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); - transSubData.fScoreSum += mapLine.at(0).at(j).fScore; - } - - //校验车型是否符合验证 - typeInfo.IsChkFlag = AuthTransNum(transSubData.iBigClassId, strTemp); - - transSubData.vecTransInfo.emplace_back(typeInfo); - } - - //编号 - if (mapLine.find(1) != mapLine.end()) - { - TransInfo numInfo; - numInfo.iLine = 1; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(1).size(); j++) - { - std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); - //过滤非数字 - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in num"; - continue; - } - strTemp += strOne; - numInfo.vecValue.emplace_back(strOne); - numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); - transSubData.fScoreSum += mapLine.at(1).at(j).fScore; - } - - //匹配正则表达式 - std::regex reg("^[0-9]{7}$"); //车厢编号,固定7位 - if (std::regex_match(strTemp, reg)) - { - numInfo.IsChkFlag = true; - } - - transSubData.vecTransInfo.emplace_back(numInfo); - } -} - -/** -* 车头框内容转换 -* inParam : std::map> &mapLine -* outParam: TransSubData &transSubData -* return : N/A -*/ -void TransTrainEngine::TransHead(TransSubData &transSubData, std::map> &mapLine) -{ - //车头型号 - if (mapLine.find(0) != mapLine.end()) - { - TransInfo typeInfo; - typeInfo.iLine = 0; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(0).size(); j++) - { - strTemp += vecClassNames_.at(mapLine.at(0).at(j).iClassId); - typeInfo.vecValue.emplace_back(vecClassNames_.at(mapLine.at(0).at(j).iClassId)); - typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); - transSubData.fScoreSum += mapLine.at(0).at(j).fScore; - } - - //不做结果校验,IsChkFlag默认为true - typeInfo.IsChkFlag = true; - transSubData.vecTransInfo.emplace_back(typeInfo); - } - - //车头编号 - if (mapLine.find(1) != mapLine.end()) - { - TransInfo numInfo; - numInfo.iLine = 1; - std::string strTemp = ""; - for (auto j = 0; j < mapLine.at(1).size(); j++) - { - std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); - //过滤非数字 - if (strOne[0] < '0' || strOne[0] > '9') - { - LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in headnum"; - continue; - } - strTemp += strOne; - numInfo.vecValue.emplace_back(strOne); - numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); - transSubData.fScoreSum += mapLine.at(1).at(j).fScore; - } - - //不做结果校验,IsChkFlag默认为true - numInfo.IsChkFlag = true; - transSubData.vecTransInfo.emplace_back(numInfo); - } -} - - -/** -* 记录在画面中间位置识别的车号 -* inParam : const TransSubData &transSubData 车号信息 - : const std::shared_ptr &pProcessData 帧数据 -* outParam: N/A -* return : N/A -*/ -void TransTrainEngine::RecordNum(const TransSubData &transSubData, const std::shared_ptr &pProcessData) -{ - int iCenterX = transSubData.step1Location.fLTX + (transSubData.step1Location.fRBX - transSubData.step1Location.fLTX) / 2; - int iImgL = pProcessData->iWidth / 3; - int iImgR = pProcessData->iWidth / 3 * 2; - if (iCenterX <= iImgL || iCenterX >= iImgR) - { - return; - } - - std::string strValue; - for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) - { - TransInfo transInfo = transSubData.vecTransInfo[i]; - if (transInfo.iLine != 1) - { - continue; - } - for (size_t j = 0; j < transInfo.vecValue.size(); j++) - { - strValue += transInfo.vecValue[j]; - } - } - - bool bIntervalFlag = ((int)(pProcessData->iFrameId - mapPreFrameId_[pProcessData->iDataSource]) > iSkipInterval_ * 2); - if (mapNumInfo_[pProcessData->iDataSource].find(strValue) == mapNumInfo_[pProcessData->iDataSource].end()) - { - LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " NUM:" << strValue - << " bIntervalFlag:" << bIntervalFlag; - if (bIntervalFlag) - { - mapNumInfo_[pProcessData->iDataSource][strValue] = pProcessData->iFrameId; - } - } - LogDebug << "sourceid:" << pProcessData->iDataSource << " preframeid:" << mapPreFrameId_[pProcessData->iDataSource] - << " frameid:" << pProcessData->iFrameId << " mapsize:" << mapNumInfo_[pProcessData->iDataSource].size(); - mapPreFrameId_[pProcessData->iDataSource] = pProcessData->iFrameId; -} - -/** -* 保存中间位置识别车号信息到csv中 -* inParam : std::shared_ptr pTrain :列车信息 -* outParam: -* return : true/false -*/ -bool TransTrainEngine::SaveMiddleNumCsv(const std::vector> &vecNums, const std::shared_ptr &pProcessData, - int iSourceId) -{ - //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/) - std::string strTrainPath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/"; - if (!MyUtils::getins()->CreateDirPath(strTrainPath)) - { - LogError << "fail CreateDirPath:" << strTrainPath; - return false; - } - - //2. 保存csv - std::string strCsvName = pProcessData->strTrainDate + pProcessData->strTrainName + "_" + std::to_string(iSourceId) + ".csv"; - strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); - strTrainPath += strCsvName; - - try - { - // 写文件 - std::ofstream outFile; - outFile.open(strTrainPath, std::ios::app); - - outFile << "num" << ',' << "frameid" << std::endl; - - for (auto iterVec = vecNums.begin(); iterVec != vecNums.end(); iterVec++) - { - outFile << iterVec->first << "," << iterVec->second << std::endl; - } - outFile.close(); - } - catch (const std::exception &) - { - LogError << "fail open dirPath:" << strTrainPath; - return false; - } - return true; -} - -/** -* push数据到队列,队列满时则休眠一段时间再push -* inParam : const std::string strPort push的端口 - : const std::shared_ptr &pProcessData push的数据 -* outParam: N/A -* return : N/A -*/ -void TransTrainEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) -{ - while (true) - { - int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); - if (iRet != 0) - { - LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; - if (iRet == 2) - { - usleep(10000); // 10ms - continue; - } - } - break; - } -} - -APP_ERROR TransTrainEngine::Process() -{ - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - - int iRet = APP_ERR_OK; - while (!isStop_) - { - std::shared_ptr pVoidData0 = nullptr; - inputQueMap_[strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); //1ms - continue; - } - - std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); - //第2步后处理结果 - std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); - - //最后一节的最后一帧为整列车的结束 - if (pProcessData->bIsTrainEnd && pProcessData->bIsEnd) - { - mapDataSourceIsEnd_[pProcessData->iDataSource] = true; - } - - //组织输出数据 - std::shared_ptr pTransData = std::make_shared(); - for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) - { - PostSubData postSubData = pPostData->vecPostSubData[i]; - - //按字段代号分类 - std::map> mapLine; - for (size_t j = 0; j < postSubData.vecSingleData.size(); j++) - { - mapLine[postSubData.vecSingleData.at(j).iLine].push_back(postSubData.vecSingleData.at(j)); - } - - //每一行按x坐标排序 - for (auto it = mapLine.begin(); it != mapLine.end(); it++) - { - std::sort(it->second.begin(), it->second.end(), CompareX); - - std::string strTemp = ""; - for (auto j = 0; j < it->second.size(); j++) - { - strTemp += vecClassNames_.at(it->second.at(j).iClassId); - } -// LogDebug << "step2 char sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId -// << " bigclassId:" << postSubData.iBigClassId << " line:" << it->first << "," << strTemp; - } - - TransSubData transSubData; - transSubData.iBigClassId = postSubData.iBigClassId; - transSubData.iCarXH = postSubData.iCarXH; - transSubData.step1Location = postSubData.step1Location; - //按大类处理 - if(postSubData.iBigClassId == 1) - { - TransPro(transSubData, mapLine); - } - else if (postSubData.iBigClassId >= 2 && postSubData.iBigClassId <= 6) - { - TransNum(transSubData, mapLine); - RecordNum(transSubData, pProcessData); - } - else if(postSubData.iBigClassId == 0) - { - TransHead(transSubData, mapLine); - RecordNum(transSubData, pProcessData); - } - else - { - continue; - } - - pTransData->vecTransSubData.emplace_back(transSubData); - } - - //是否全部结束 - bool bAllEnd = true; - for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) - { - bAllEnd = bAllEnd && iter->second; - } - - pProcessData->pVoidData = std::static_pointer_cast(pTransData); - // push端口0,车号属性选优处理 - PushData(strPort0_, pProcessData); - - if (bAllEnd) - { - for(auto iter = mapNumInfo_.begin(); iter != mapNumInfo_.end(); iter++) - { - std::vector> vecTemp(iter->second.begin(), iter->second.end()); - sort(vecTemp.begin(), vecTemp.end(), CmpVec); //按帧号排序 - SaveMiddleNumCsv(vecTemp, pProcessData, iter->first); - - // for(auto iterVec = vecTemp.begin(); iterVec != vecTemp.end(); iterVec++) - // { - // LogDebug << "sourceid:" << iter->first << " num:" << iterVec->first << " frameid:" << iterVec->second; - // } - } - //转个json数组发送后面用于比较。(车厢个数和该json数据是否相等,相等则不处理。不相等则挨个比较下。) - - //初始化参数变量 - InitParam(); - } - } - - return APP_ERR_OK; -} +#include "TransTrainEngine.h" #include "myutils.h" #include #include using namespace ai_matrix; namespace { //按照x坐标排列 bool CompareX(const SingleData &v1, const SingleData &v2) { return (v1.fLTX < v2.fLTX); } //自定义比较规则 bool CmpVec(const pair &P1, const pair &P2) { return P1.second < P2.second; } } TransTrainEngine::TransTrainEngine() {} TransTrainEngine::~TransTrainEngine() {} APP_ERROR TransTrainEngine::Init() { bUseEngine_ = MyUtils::getins()->ChkIsHaveTarget("NUM"); if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; modelConfig_ = MyYaml::GetIns()->GetModelConfig("TrainStepTwoEngine"); strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path"); //读取模型参数信息文件 Json::Value jvModelInfo; if (!MyUtils::getins()->ReadJsonInfo(jvModelInfo, modelConfig_.strModelInfoPath)) { LogError << "ModelInfoPath:" << modelConfig_.strModelInfoPath << " doesn't exist or read failed!"; return APP_ERR_COMM_NO_EXIST; } for (int i = 0; i < jvModelInfo["class"].size(); i++) { vecClassNames_.push_back(jvModelInfo["class"][i].asString()); } // 获取几个摄像头识别车号 std::map mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig(); for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++) { iSkipInterval_ = iter->second.iSkipInterval; if (iter->second.strTarget.find("NUM") != std::string::npos) { LogDebug << "sourceid:" << iter->first << " deal Num"; mapDataSourceIsEnd_[iter->first] = false; } } InitParam(); LogInfo << "TransTrainEngine Init ok"; return APP_ERR_OK; } APP_ERROR TransTrainEngine::DeInit() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } LogInfo << "TransTrainEngine DeInit ok"; return APP_ERR_OK; } /** * 初始化参数信息 * inParam : N/A * outParam: N/A * return : N/A */ void TransTrainEngine::InitParam() { for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { iter->second = false; } mapNumInfo_.clear(); mapPreFrameId_.clear(); } /** * 校验车型是否符合验证 * inParam : int classId 大框类别id * : const std::string &trainNum 车型字符信息 * outParam: N/A * return : true:符合; false:不符合 */ bool TransTrainEngine::AuthTransNum(int classId, const std::string &trainNum) { // LogInfo << "classId:" << classId << " trainNum:" << trainNum; switch (classId) { case TRAIN_HEAD: // 车头上的编号 break; case K_TRAIN_NUM: // 编号 矿车、煤炭漏斗车(兖矿自备、枣矿自备) { if (trainNum == "K13" || trainNum == "KM100AH") { return true; } std::regex reg; switch (trainNum.size()) { case 4: reg = "^K[1FMZ]{1}[36789]{1}[018ABKNT]{1}"; break; case 5: reg = "^K[1M]{1}[368]{1}[1ABDN]{1}[AGKNT]{1}"; break; case 6: reg = "^K[MF]{1}[69]{1}[80]{1}A[KH]{1}"; break; default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } case C_TRAIN_NUM: // 敞车 特殊车型 C5D CF CFK { if (trainNum == "CF" || trainNum == "C62A(N)") { return true; } std::regex reg; switch (trainNum.size()) { case 3: reg = "^C[15678F]{1}[0123456DK]{1}"; break; case 4: reg = "^C[1678]{1}[012346]{1}[0ABCEFHKMTY]{1}"; break; case 5: reg = "^C[1678]{1}[01246]{1}[0ABCEY]{1}[KAFHNT]{1}"; break; case 6: reg = "^C[17]{1}0[0E]{1}[A-]{1}[AH]{1}"; break; default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } case P_TRAIN_NUM: // 编号 棚车 { if (trainNum == "P70(H)" || trainNum == "P62(N)") { return true; } std::regex reg; switch (trainNum.size()) { case 3: reg = "^P[1678]{1}[012345]{1}"; break; case 4: reg = "^P[678]{1}[023456]{1}[ABHKNST]{1}"; break; case 5: reg = "^P6[24]{1}[ANG]{1}[KT]{1}"; break; default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } case G_TRAIN_NUM: // 编号 罐车 { if (trainNum == "GY100SK") { return true; } std::regex reg; switch (trainNum.size()) { case 2: reg = "^G[HLS]{1}"; break; case 3: reg = "^[GL]{1}[1567HL]{1}[01246789K]{1}"; break; case 4: reg = "^[GU]{1}[167FJLNQSWY]{1}[170689]{1}[KSABDGTM075W]{1}"; break; case 5: reg = "^[GU]{1}[17FHNQY6]{1}[1706A89]{1}[SBDAM057W]{1}[KEHTB0ZAS]{1}"; break; case 6: reg = "^[UG]{1}[6YH]{1}[1489A]{1}[057W]{1}[Z0LSA]{1}[KSAT]{1}"; break; default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } case NX_TRAIN_NUM: // 编号 平车 { if (trainNum == "N6") { return true; } std::regex reg; switch (trainNum.size()) { case 3: reg = "^[NQX]{1}[1234678T]{1}[0124567HK]{1}"; break; case 4: reg = "^[BNX]{1}[16X]{1}[17BC]{1}[07AGKT]{1}"; break; case 5: reg = "^[NX]{1}[16NX]{1}[17C]{1}[07AGT]{1}[KTABH]{1}"; break; case 6: reg = "^NX17[AB]{1}[KTH]{1}"; break; default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } case J_TRAIN_NUM: // 编号 牲畜车 特种车 { if (trainNum == "TP64GK") { return true; } std::regex reg; switch (trainNum.size()) { case 2: reg = "^[DT]{1}[2678]{1}"; break; case 3: reg = "^[DST]{1}[12346789LQ]{1}[012578ADFGP]{1}"; break; case 4: reg = "^[DJNT]{1}[12356AFKQS]{1}[012345678DFQS]{1}[A12345679GHKQ]{1}"; break; case 5: reg = "^[DJQT]{1}[2KNSH1P]{1}[613XQ2]{1}[A761234B]{1}[KA70G]{1}"; break; default: LogWarn << "Unknow train, classId: " << classId << " trainNum:" << trainNum; return false; } return std::regex_match(trainNum, reg); } default: LogWarn << "Unknow train,classId:" << classId << " trainNum:" << trainNum; return false; } return true; } /** * 过滤第二步字段代号的误识别 * inParam : std::vector &vecObjs * : TargetMaxLen iMaxLen * outParam: N/A * return : N/A */ void TransTrainEngine::FilterSingleData(std::vector &vecObjs, TargetMaxLen iMaxLen) { /*误识别场景 例: 车厢容积属性只有2位时,但因误识别导致自重的某个字符字段代号错误,划归到容积中,这样实际只有2位的容积变为3位。导致选优时错误。 只处理1个字段代号的误识别,若有多个字段代号同时错误,无法区分哪些字符字段代号是正确的。(字段代号误识别较多时,则增强模型训练) 排除一个最大和最小值后计算平局坐标值,每个框左上角和平局值左上角高度差大于平局值的高度则剔除. */ if (vecObjs.size() != iMaxLen || vecObjs.size() <= 2) { return; } std::deque dqObjs(vecObjs.begin(), vecObjs.end()); std::sort(dqObjs.begin(), dqObjs.end(), [](SingleData &a, SingleData &b) { return a.fLTY < b.fLTY; }); dqObjs.pop_front(); dqObjs.pop_back(); SingleData singleDataAvg; for (auto iter = dqObjs.begin(); iter != dqObjs.end(); iter++) { singleDataAvg.fLTX += iter->fLTX; singleDataAvg.fLTY += iter->fLTY; singleDataAvg.fRBX += iter->fRBX; singleDataAvg.fRBY += iter->fRBY; } singleDataAvg.fLTX = singleDataAvg.fLTX / dqObjs.size(); singleDataAvg.fLTY = singleDataAvg.fLTY / dqObjs.size(); singleDataAvg.fRBX = singleDataAvg.fRBX / dqObjs.size(); singleDataAvg.fRBY = singleDataAvg.fRBY / dqObjs.size(); float fAvgHeight = singleDataAvg.fRBY - singleDataAvg.fLTY; //剔除位置错误的字符信息 for (auto iter = vecObjs.begin(); iter != vecObjs.end(); iter++) { float fTemp = fabs(iter->fLTY - singleDataAvg.fLTY); if (fTemp > (fAvgHeight - 5)) { std::string strOne = vecClassNames_.at(iter->iClassId); LogWarn << "engineId:" << engineId_ << " " << strOne << " Line wrong "; vecObjs.erase(iter); break; } } } /** * 属性框内容转换 * inParam : std::map> &mapLine * outParam: TransSubData &transSubData * return : N/A */ void TransTrainEngine::TransPro(TransSubData &transSubData, std::map> &mapLine) { //载重 if (mapLine.find(0) != mapLine.end()) { TransInfo loadInfo; loadInfo.iLine = 0; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(0).size(); j++) { //过滤非数字 std::string strOne = vecClassNames_.at(mapLine.at(0).at(j).iClassId); if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in load"; continue; } strTemp += strOne; loadInfo.vecValue.emplace_back(strOne); loadInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); transSubData.fScoreSum += mapLine.at(0).at(j).fScore; } //匹配正则表达式 //std::regex reg("^[0-9]{2}"); std::regex reg("^([4,5,6,7,8,9]{1}[0-9]{1}|[1]{1}[0-3]{1}[0-9]{1})$"); //(第1位:棚车:4 5; K自备车:1 5 7 8 9; 平车:7; 罐车:6 7; 敞车:6 7 8) if (std::regex_match(strTemp, reg)) { loadInfo.IsChkFlag = true; } transSubData.vecTransInfo.emplace_back(loadInfo); } //自重 if (mapLine.find(1) != mapLine.end()) { FilterSingleData(mapLine.at(1), SELF_MAXLEN); TransInfo selfInfo; selfInfo.iLine = 1; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(1).size(); j++) { //过滤非数字 std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in self"; continue; } strTemp += strOne; selfInfo.vecValue.emplace_back(strOne); selfInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); transSubData.fScoreSum += mapLine.at(1).at(j).fScore; } //匹配正则表达式 std::regex reg("^[1,2,3]{1}[0-9]{1,2}$"); if (std::regex_match(strTemp, reg)) { selfInfo.IsChkFlag = true; } transSubData.vecTransInfo.emplace_back(selfInfo); } //容积 if (mapLine.find(2) != mapLine.end()) { FilterSingleData(mapLine.at(2), VOLUME_MAXLEN); TransInfo volumeInfo; volumeInfo.iLine = 2; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(2).size(); j++) { //过滤非数字 std::string strOne = vecClassNames_.at(mapLine.at(2).at(j).iClassId); if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in volume"; continue; } strTemp += strOne; volumeInfo.vecValue.emplace_back(strOne); volumeInfo.vecScore.emplace_back(mapLine.at(2).at(j).fScore); transSubData.fScoreSum += mapLine.at(2).at(j).fScore; } //匹配正则表达式 //std::regex reg("^[0-9]{2,3}$"); std::regex reg("^[1,6,7,8,9]{1}[0-9]{1,2}$"); //(第1位:棚车:1; K自备车:1或9; 罐车:6或7; 敞车:7或8) if (std::regex_match(strTemp, reg)) { volumeInfo.IsChkFlag = true; } transSubData.vecTransInfo.emplace_back(volumeInfo); } //换长 if (mapLine.find(3) != mapLine.end()) { TransInfo changeInfo; changeInfo.iLine = 3; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(3).size(); j++) { //过滤非数字 std::string strOne = vecClassNames_.at(mapLine.at(3).at(j).iClassId); if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in change"; continue; } strTemp += strOne; changeInfo.vecValue.emplace_back(strOne); changeInfo.vecScore.emplace_back(mapLine.at(3).at(j).fScore); transSubData.fScoreSum += mapLine.at(3).at(j).fScore; } //匹配正则表达式 //std::regex reg("^[0-9]{2}$"); std::regex reg("^[1]{1}[0-9]{1}$"); if (std::regex_match(strTemp, reg)) { changeInfo.IsChkFlag = true; } transSubData.vecTransInfo.emplace_back(changeInfo); } //罐车容量计表 if (mapLine.find(4) != mapLine.end()) { TransInfo volumeSurfaceInfo; volumeSurfaceInfo.iLine = 4; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(4).size(); j++) { strTemp += vecClassNames_.at(mapLine.at(4).at(j).iClassId); volumeSurfaceInfo.vecValue.emplace_back(vecClassNames_.at(mapLine.at(4).at(j).iClassId)); volumeSurfaceInfo.vecScore.emplace_back(mapLine.at(4).at(j).fScore); transSubData.fScoreSum += mapLine.at(4).at(j).fScore; } volumeSurfaceInfo.IsChkFlag = true; //暂不校验 transSubData.vecTransInfo.emplace_back(volumeSurfaceInfo); } } /** * 车号框内容转换 * inParam : std::map> &mapLine * outParam: TransSubData &transSubData * return : N/A */ void TransTrainEngine::TransNum(TransSubData &transSubData, std::map> &mapLine) { //车型 if (mapLine.find(0) != mapLine.end()) { TransInfo typeInfo; typeInfo.iLine = 0; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(0).size(); j++) { std::string strOne = vecClassNames_.at(mapLine.at(0).at(j).iClassId); /*20230117 该逻辑删除,有厂区发现有C70C DF4DD等车型。 针对重复印刷的场景需想其他方法处理。 //注:车型多次印刷会导致之前印刷的个别字符会识别,导致最终的识别内容变多。针对车型没有重复字符的特点,因此剔除重复的字符 auto iter = find(typeInfo.vecValue.begin(), typeInfo.vecValue.end(), strOne); if (iter != typeInfo.vecValue.end()) { LogWarn << "Possible duplicate recognition strOne:" << strOne; continue; } */ strTemp += strOne; typeInfo.vecValue.emplace_back(strOne); typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); transSubData.fScoreSum += mapLine.at(0).at(j).fScore; } //校验车型是否符合验证 typeInfo.IsChkFlag = AuthTransNum(transSubData.iBigClassId, strTemp); // LogInfo << "--->>> 符合正则吗?" << typeInfo.IsChkFlag << " --- " << strTemp; transSubData.vecTransInfo.emplace_back(typeInfo); } //编号 if (mapLine.find(1) != mapLine.end()) { TransInfo numInfo; numInfo.iLine = 1; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(1).size(); j++) { std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); //过滤非数字 if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in num"; continue; } strTemp += strOne; numInfo.vecValue.emplace_back(strOne); numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); transSubData.fScoreSum += mapLine.at(1).at(j).fScore; } //匹配正则表达式 std::regex reg("^[0-9]{7}$"); //车厢编号,固定7位 if (std::regex_match(strTemp, reg)) { numInfo.IsChkFlag = true; } transSubData.vecTransInfo.emplace_back(numInfo); } } /** * 车头框内容转换 * inParam : std::map> &mapLine * outParam: TransSubData &transSubData * return : N/A */ void TransTrainEngine::TransHead(TransSubData &transSubData, std::map> &mapLine) { //车头型号 if (mapLine.find(0) != mapLine.end()) { TransInfo typeInfo; typeInfo.iLine = 0; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(0).size(); j++) { strTemp += vecClassNames_.at(mapLine.at(0).at(j).iClassId); typeInfo.vecValue.emplace_back(vecClassNames_.at(mapLine.at(0).at(j).iClassId)); typeInfo.vecScore.emplace_back(mapLine.at(0).at(j).fScore); transSubData.fScoreSum += mapLine.at(0).at(j).fScore; } //不做结果校验,IsChkFlag默认为true typeInfo.IsChkFlag = true; transSubData.vecTransInfo.emplace_back(typeInfo); } //车头编号 if (mapLine.find(1) != mapLine.end()) { TransInfo numInfo; numInfo.iLine = 1; std::string strTemp = ""; for (auto j = 0; j < mapLine.at(1).size(); j++) { std::string strOne = vecClassNames_.at(mapLine.at(1).at(j).iClassId); //过滤非数字 if (strOne[0] < '0' || strOne[0] > '9') { LogWarn << "engineId:" << engineId_ << " " << strOne << " not digit in headnum"; continue; } strTemp += strOne; numInfo.vecValue.emplace_back(strOne); numInfo.vecScore.emplace_back(mapLine.at(1).at(j).fScore); transSubData.fScoreSum += mapLine.at(1).at(j).fScore; } //不做结果校验,IsChkFlag默认为true numInfo.IsChkFlag = true; transSubData.vecTransInfo.emplace_back(numInfo); } } /** * 记录在画面中间位置识别的车号 * inParam : const TransSubData &transSubData 车号信息 : const std::shared_ptr &pProcessData 帧数据 * outParam: N/A * return : N/A */ void TransTrainEngine::RecordNum(const TransSubData &transSubData, const std::shared_ptr &pProcessData) { int iCenterX = transSubData.step1Location.fLTX + (transSubData.step1Location.fRBX - transSubData.step1Location.fLTX) / 2; int iImgL = pProcessData->iWidth / 3; int iImgR = pProcessData->iWidth / 3 * 2; if (iCenterX <= iImgL || iCenterX >= iImgR) { return; } std::string strValue; for (size_t i = 0; i < transSubData.vecTransInfo.size(); i++) { TransInfo transInfo = transSubData.vecTransInfo[i]; if (transInfo.iLine != 1) { continue; } for (size_t j = 0; j < transInfo.vecValue.size(); j++) { strValue += transInfo.vecValue[j]; } } bool bIntervalFlag = ((int)(pProcessData->iFrameId - mapPreFrameId_[pProcessData->iDataSource]) > iSkipInterval_ * 2); if (mapNumInfo_[pProcessData->iDataSource].find(strValue) == mapNumInfo_[pProcessData->iDataSource].end()) { LogDebug << " frameid:" << pProcessData->iFrameId << " NUM:" << strValue << " bIntervalFlag:" << bIntervalFlag; if (bIntervalFlag) { mapNumInfo_[pProcessData->iDataSource][strValue] = pProcessData->iFrameId; } } // LogDebug << " preframeid:" << mapPreFrameId_[pProcessData->iDataSource] // << " frameid:" << pProcessData->iFrameId << " mapsize:" << mapNumInfo_[pProcessData->iDataSource].size(); mapPreFrameId_[pProcessData->iDataSource] = pProcessData->iFrameId; } /** * 保存中间位置识别车号信息到csv中 * inParam : std::shared_ptr pTrain :列车信息 * outParam: * return : true/false */ bool TransTrainEngine::SaveMiddleNumCsv(const std::vector> &vecNums, const std::shared_ptr &pProcessData, int iSourceId) { //1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/) std::string strTrainPath = strResultPath_ + pProcessData->strTrainDate + "/" + pProcessData->strTrainName + "/"; if (!MyUtils::getins()->CreateDirPath(strTrainPath)) { LogError << "fail CreateDirPath:" << strTrainPath; return false; } //2. 保存csv std::string strCsvName = pProcessData->strTrainDate + pProcessData->strTrainName + "_" + std::to_string(iSourceId) + ".csv"; strCsvName = MyUtils::getins()->replace_all_distinct(strCsvName, std::string("-"), std::string("")); strTrainPath += strCsvName; try { // 写文件 std::ofstream outFile; outFile.open(strTrainPath, std::ios::app); outFile << "num" << ',' << "frameid" << std::endl; for (auto iterVec = vecNums.begin(); iterVec != vecNums.end(); iterVec++) { outFile << iterVec->first << "," << iterVec->second << std::endl; } outFile.close(); } catch (const std::exception &) { LogError << "fail open dirPath:" << strTrainPath; return false; } return true; } /** * push数据到队列,队列满时则休眠一段时间再push * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void TransTrainEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } APP_ERROR TransTrainEngine::Process() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); //第2步后处理结果 std::shared_ptr pPostData = std::static_pointer_cast(pProcessData->pVoidData); //最后一节的最后一帧为整列车的结束 if (pProcessData->bIsTrainEnd && pProcessData->bIsEnd) { mapDataSourceIsEnd_[pProcessData->iDataSource] = true; } //组织输出数据 std::shared_ptr pTransData = std::make_shared(); for (size_t i = 0; i < pPostData->vecPostSubData.size(); i++) { PostSubData postSubData = pPostData->vecPostSubData[i]; //按字段代号分类 std::map> mapLine; for (size_t j = 0; j < postSubData.vecSingleData.size(); j++) { mapLine[postSubData.vecSingleData.at(j).iLine].push_back(postSubData.vecSingleData.at(j)); } //每一行按x坐标排序 for (auto it = mapLine.begin(); it != mapLine.end(); it++) { std::sort(it->second.begin(), it->second.end(), CompareX); std::string strTemp = ""; for (auto j = 0; j < it->second.size(); j++) { strTemp += vecClassNames_.at(it->second.at(j).iClassId); } // LogDebug << "step2 char sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId // << " bigclassId:" << postSubData.iBigClassId << " line:" << it->first << "," << strTemp; } TransSubData transSubData; transSubData.iBigClassId = postSubData.iBigClassId; transSubData.iCarXH = postSubData.iCarXH; transSubData.step1Location = postSubData.step1Location; //按大类处理 if(postSubData.iBigClassId == 1) { TransPro(transSubData, mapLine); } else if (postSubData.iBigClassId >= 2 && postSubData.iBigClassId <= 6) { TransNum(transSubData, mapLine); RecordNum(transSubData, pProcessData); } else if(postSubData.iBigClassId == 0) { TransHead(transSubData, mapLine); RecordNum(transSubData, pProcessData); } else { continue; } pTransData->vecTransSubData.emplace_back(transSubData); } //是否全部结束 bool bAllEnd = true; for (auto iter = mapDataSourceIsEnd_.begin(); iter != mapDataSourceIsEnd_.end(); iter++) { bAllEnd = bAllEnd && iter->second; } pProcessData->pVoidData = std::static_pointer_cast(pTransData); // push端口0,车号属性选优处理 PushData(strPort0_, pProcessData); if (bAllEnd) { for(auto iter = mapNumInfo_.begin(); iter != mapNumInfo_.end(); iter++) { std::vector> vecTemp(iter->second.begin(), iter->second.end()); sort(vecTemp.begin(), vecTemp.end(), CmpVec); //按帧号排序 SaveMiddleNumCsv(vecTemp, pProcessData, iter->first); // for(auto iterVec = vecTemp.begin(); iterVec != vecTemp.end(); iterVec++) // { // LogDebug << "sourceid:" << iter->first << " num:" << iterVec->first << " frameid:" << iterVec->second; // } } //转个json数组发送后面用于比较。(车厢个数和该json数据是否相等,相等则不处理。不相等则挨个比较下。) //初始化参数变量 InitParam(); } } return APP_ERR_OK; } \ No newline at end of file diff --git a/nvidia_ascend_engine/nvidia_engine/MoveEngine/MoveEngine.cpp b/nvidia_ascend_engine/nvidia_engine/MoveEngine/MoveEngine.cpp index 1fb6f43..89ebcc0 100644 --- a/nvidia_ascend_engine/nvidia_engine/MoveEngine/MoveEngine.cpp +++ b/nvidia_ascend_engine/nvidia_engine/MoveEngine/MoveEngine.cpp @@ -192,7 +192,9 @@ void MoveEngine::SingleDeviceProcess(std::shared_ptr pProcessData, { outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_" + std::to_string(*iter)]->push(std::static_pointer_cast(pMoveData)); } - //通知第一步开始识别 + + // LogInfo << "【来车检测】" << pMoveData->iFrameId << " isEnd:" << pProcessData->bIsEnd; + //通知第一步开始识别 outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_5"]->push(std::static_pointer_cast(pMoveData)); } @@ -283,16 +285,16 @@ APP_ERROR MoveEngine::Process() // LogInfo<<"来车当前状态:"<< (nType == 0 ? "有车头" : (nType == 1 ? "无车")); switch (nType) { case 0: - LogDebug << "来车状态:有车头"; + LogDebug << iMoveDataNO_ * dataSourceCfg_.iSkipInterval << "来车状态:有车头"; break; case 1: - LogDebug << "来车状态:无车"; + LogDebug << iMoveDataNO_ * dataSourceCfg_.iSkipInterval << "来车状态:无车"; break; case 2: - LogDebug << "来车状态:车尾"; + LogDebug << iMoveDataNO_ * dataSourceCfg_.iSkipInterval << "来车状态:车尾"; break; case 3: - LogDebug << "来车状态:有车"; + LogDebug << iMoveDataNO_ * dataSourceCfg_.iSkipInterval << "来车状态:有车"; break; } diff --git a/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/TrainStepOneEngine.cpp b/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/TrainStepOneEngine.cpp index cfaee5a..c6bf8d6 100644 --- a/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/TrainStepOneEngine.cpp +++ b/nvidia_ascend_engine/nvidia_engine/TrainStepOneEngine/TrainStepOneEngine.cpp @@ -194,9 +194,9 @@ void TrainStepOneEngine::FilterInvalidInfo(std::vector &vecRet, std std::vector vecSpaceInfo; for (auto it = vecRet.begin(); it != vecRet.end();) { - LogDebug << "frameId:" << pProcessData->iFrameId - << " bigclassid:" << it->class_id << " ltx:" << it->bbox[0] << " lty:" << it->bbox[1] - << " rbx:" << it->bbox[2] << " rby:" << it->bbox[3]; + // LogDebug << "frameId:" << pProcessData->iFrameId + // << " bigclassid:" << it->class_id << " ltx:" << it->bbox[0] << " lty:" << it->bbox[1] + // << " rbx:" << it->bbox[2] << " rby:" << it->bbox[3]; // 根据配置文件中 设置的识别范围,过滤掉无效数据 if (!(it->bbox[0] >= dataSourceCfg.fIdentifyAreasLTX && it->bbox[1] >= dataSourceCfg.fIdentifyAreasLTY && @@ -322,6 +322,22 @@ void TrainStepOneEngine::FilterInvalidInfo(std::vector &vecRet, std continue; } + if (it->class_id == K_TRAIN_NUM) + { + int iCenterY = pProcessData->iHeight / 2; + int iHeight0 = it->bbox[1] / 2 + it->bbox[3] / 2; + if (iHeight0 > iCenterY) { + LogWarn << "矿车编号大框在画面Y轴中线以下,帧号:" + << pProcessData->iFrameId + << " 画面Y轴中心:" << iCenterY + << " 大框Y轴中心:" << iHeight0 ; + // << "[" << it->bbox[0] << "," << it->bbox[1] << "]" + // << "[" << it->bbox[2] << "," << it->bbox[3] << "]"; + it = vecRet.erase(it); + continue; + } + } + //补连塔的相机比较近,间隔基本在画面底部,因此当间隔比较靠画面上时过滤掉。 if ((it->class_id >= 9 && it->class_id <= 17 && it->class_id != 15) || it->class_id == U_TRAIN_SPACE) { @@ -484,10 +500,10 @@ APP_ERROR TrainStepOneEngine::Process() SetTargetType(postSubData); pPostData->vecPostSubData.emplace_back(postSubData); -// LogDebug << "数据源:" << pProcessData->iDataSource << " 帧:" << pProcessData->iFrameId -// << " --iClassId:" << singledata.iClassId << " iLine:" << singledata.iLine << " confidence=" << singledata.fScore -// << " lx=" << singledata.fLTX << " ly=" << singledata.fLTY << " rx=" << singledata.fRBX << " ry=" << singledata.fRBY -// << " clear:" << singledata.fClear; + LogDebug << "数据源:" << pProcessData->iDataSource << " 帧:" << pProcessData->iFrameId + << " --iClassId:" << singledata.iClassId << " iLine:" << singledata.iLine << " confidence=" << singledata.fScore + << " lx=" << singledata.fLTX << " ly=" << singledata.fLTY << " rx=" << singledata.fRBX << " ry=" << singledata.fRBY + << " clear:" << singledata.fClear; } } } diff --git a/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/TrainStepTwoEngine.cpp b/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/TrainStepTwoEngine.cpp index 97775cc..f04c30e 100644 --- a/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/TrainStepTwoEngine.cpp +++ b/nvidia_ascend_engine/nvidia_engine/TrainStepTwoEngine/TrainStepTwoEngine.cpp @@ -1,246 +1 @@ -#include "TrainStepTwoEngine.h" -#include -#include "myutils.h" -#include "myqueue.h" - -using namespace ai_matrix; - -TrainStepTwoEngine::TrainStepTwoEngine() {} - -TrainStepTwoEngine::~TrainStepTwoEngine() {} - -APP_ERROR TrainStepTwoEngine::Init() -{ - bUseEngine_ = MyUtils::getins()->ChkIsHaveTarget("NUM"); - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - - strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; - modelConfig_ = MyYaml::GetIns()->GetModelConfig("TrainStepTwoEngine"); - - //读取模型信息 - APP_ERROR ret = ReadModelInfo(); - if (ret != APP_ERR_OK) - { - LogError << "Failed to read model info, ret = " << ret; - return ret; - } - ret = InitModel(); - if (ret != APP_ERR_OK) - { - LogError << "Failed to read model info, ret = " << ret; - return ret; - } - - LogInfo << "AclTrainStepTwoEngine Init ok"; - return APP_ERR_OK; -} - -APP_ERROR TrainStepTwoEngine::InitModel() -{ - - modelinfo.yolov5ClearityModelParam.uiClassNum = class_num; - modelinfo.yolov5ClearityModelParam.uiClearNum = clear_num; - modelinfo.yolov5ClearityModelParam.uiDetSize = det_size; - modelinfo.yolov5ClearityModelParam.fScoreThreshold = score_threshold; - modelinfo.yolov5ClearityModelParam.fNmsThreshold = nms_threshold; - - modelinfo.modelCommonInfo.uiModelWidth = model_width; - modelinfo.modelCommonInfo.uiModelHeight = model_height; - modelinfo.modelCommonInfo.uiInputSize = input_size; - modelinfo.modelCommonInfo.uiOutputSize = output_size; - modelinfo.modelCommonInfo.uiChannel = INPUT_CHANNEL; - modelinfo.modelCommonInfo.uiBatchSize = batch_size; - modelinfo.modelCommonInfo.strInputBlobName = INPUT_BLOB_NAME; - modelinfo.modelCommonInfo.strOutputBlobName = OUTPUT_BLOB_NAME; - - string strModelName = ""; - - int nRet = yolov5model.YoloV5ClearityInferenceInit(&modelinfo, strModelName, modelConfig_.strOmPath); - if (nRet != 0) - { - LogInfo << "YoloV5ClassifyInferenceInit nRet:" << nRet; - return APP_ERR_COMM_READ_FAIL; - } - return APP_ERR_OK; -} - -APP_ERROR TrainStepTwoEngine::ReadModelInfo() -{ - char szAbsPath[PATH_MAX]; - // Get the absolute path of model file - if (realpath(modelConfig_.strOmPath.c_str(), szAbsPath) == nullptr) - { - LogError << "Failed to get the real path of " << modelConfig_.strOmPath.c_str(); - return APP_ERR_COMM_NO_EXIST; - } - - // Check the validity of model path - int iFolderExist = access(szAbsPath, R_OK); - if (iFolderExist == -1) - { - LogError << "ModelPath " << szAbsPath << " doesn't exist or read failed!"; - return APP_ERR_COMM_NO_EXIST; - } - - //读取模型参数信息文件 - Json::Value jvModelInfo; - if (!MyUtils::getins()->ReadJsonInfo(jvModelInfo, modelConfig_.strModelInfoPath)) - { - LogError << "ModelInfoPath:" << modelConfig_.strModelInfoPath << " doesn't exist or read failed!"; - return APP_ERR_COMM_NO_EXIST; - } - - model_width = jvModelInfo["model_width"].asInt(); - model_height = jvModelInfo["model_height"].asInt(); - clear_num = jvModelInfo["clear"].isArray() ? jvModelInfo["clear"].size() : 0; - class_num = jvModelInfo["class"].isArray() ? jvModelInfo["class"].size() : 0; - input_size = GET_INPUT_SIZE(model_width, model_height); - output_size = GET_OUTPUT_SIZE(model_width, model_height, clear_num, class_num); - det_size = clear_num + class_num + 5; - score_threshold = modelConfig_.fScoreThreshold; - nms_threshold = modelConfig_.fNMSTreshold; - - return APP_ERR_OK; -} - -APP_ERROR TrainStepTwoEngine::DeInit() -{ - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - - yolov5model.YoloV5ClearityInferenceDeinit(); - LogInfo << "TrainStepTwoEngine DeInit ok"; - return APP_ERR_OK; -} - -/** -* push数据到队列,队列满时则休眠一段时间再push -* inParam : const std::string strPort push的端口 - : const std::shared_ptr &pProcessData push的数据 -* outParam: N/A -* return : N/A -*/ -void TrainStepTwoEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) -{ - while (true) - { - int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); - if (iRet != 0) - { - LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; - if (iRet == 2) - { - usleep(10000); // 10ms - continue; - } - } - break; - } -} - -APP_ERROR TrainStepTwoEngine::Process() -{ - if (!bUseEngine_) - { - LogWarn << "engineId_:" << engineId_ << " not use engine"; - return APP_ERR_OK; - } - int iRet = APP_ERR_OK; - - while (!isStop_) - { - std::shared_ptr pVoidData0 = nullptr; - inputQueMap_[strPort0_]->pop(pVoidData0); - if (nullptr == pVoidData0) - { - usleep(1000); //1ms - continue; - } - - std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); - //组织输出数据 - std::shared_ptr pPostData = std::make_shared(); - pPostData->iModelType = MODELTYPE_NUM; - - //获取图片 - if (pProcessData->iStatus == TRAINSTATUS_RUN || pProcessData->bIsEnd) - { - if (pProcessData->pData != nullptr && pProcessData->iSize != 0) - { - std::shared_ptr ppostbuff = std::static_pointer_cast(pProcessData->pVoidData); - cv::Mat img(pProcessData->iHeight, pProcessData->iWidth, CV_8UC3, static_cast(pProcessData->pData.get())); //RGB - - for(int i = 0; i< ppostbuff->vecPostSubData.size(); i++) - { - PostSubData postsubdata = ppostbuff->vecPostSubData[i]; - if (postsubdata.iTargetType != NUM && postsubdata.iTargetType != PRO && postsubdata.iTargetType != HEAD) - { - continue; - } - - cv::Rect step2_rect(cv::Point(postsubdata.step1Location.fLTX, postsubdata.step1Location.fLTY), cv::Point(postsubdata.step1Location.fRBX, postsubdata.step1Location.fRBY)); - cv::Mat step2_image = img(step2_rect).clone(); - - //进行推理 - std::vector res; - auto start = std::chrono::system_clock::now(); // 计时开始 - yolov5model.YoloV5ClearityInferenceModel(step2_image, res); - auto end = std::chrono::system_clock::now(); -// LogInfo << "nopr2 inference time: " << std::chrono::duration_cast(end - start).count() << "ms"; - - PostSubData postSubDataNew; - postSubDataNew.iTargetType = postsubdata.iTargetType; - postSubDataNew.iBigClassId = postsubdata.iBigClassId; - postSubDataNew.iCarXH = postsubdata.iCarXH; - postSubDataNew.step1Location = postsubdata.step1Location; - //整理推理结果 - //根据非极大值抑制的结果标注相关信息(画框,文字信息等) - //res.size()为每张图片上的识别到的对象数目 - for (size_t j = 0; j < res.size(); j++) - { - SingleData singledata; - singledata.iLine = res[j].clear_id; - // singledata.iLine = -1; - singledata.iClassId = res[j].class_id; - singledata.fScore = res[j].class_conf; - // singledata.iAnchorId = -1; - singledata.fLTX = res[j].bbox[0]; - singledata.fLTY = res[j].bbox[1]; - singledata.fRBX = res[j].bbox[2]; - singledata.fRBY = res[j].bbox[3]; - singledata.fClear = res[j].clear_id; - - MyUtils::getins()->Step2ResetLocation(singledata, 1.0, pProcessData, postSubDataNew.step1Location); - - postSubDataNew.vecSingleData.emplace_back(singledata); - -// LogDebug << "sourceid:" << pProcessData->iDataSource << " step2 after frameId:" << pProcessData->iFrameId -// << " --iClassId:" << singledata.iClassId << " iLine:" << singledata.iLine << " confidence=" << singledata.fScore -// << " lx=" << singledata.fLTX << " ly=" << singledata.fLTY << " rx=" << singledata.fRBX << " ry=" << singledata.fRBY; - } - pPostData->vecPostSubData.emplace_back(postSubDataNew); - } - } - } - - //及时释放内存 - if (pProcessData->pData != nullptr) - { - pProcessData->pData = nullptr; - pProcessData->iSize = 0; - } - - // push端口0,第1步推理 - pProcessData->pVoidData = std::static_pointer_cast(pPostData); - PushData(strPort0_, pProcessData); - } - return APP_ERR_OK; -} - +#include "TrainStepTwoEngine.h" #include #include "myutils.h" #include "myqueue.h" using namespace ai_matrix; TrainStepTwoEngine::TrainStepTwoEngine() {} TrainStepTwoEngine::~TrainStepTwoEngine() {} APP_ERROR TrainStepTwoEngine::Init() { bUseEngine_ = MyUtils::getins()->ChkIsHaveTarget("NUM"); if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0"; modelConfig_ = MyYaml::GetIns()->GetModelConfig("TrainStepTwoEngine"); //读取模型信息 APP_ERROR ret = ReadModelInfo(); if (ret != APP_ERR_OK) { LogError << "Failed to read model info, ret = " << ret; return ret; } ret = InitModel(); if (ret != APP_ERR_OK) { LogError << "Failed to read model info, ret = " << ret; return ret; } LogInfo << "AclTrainStepTwoEngine Init ok"; return APP_ERR_OK; } APP_ERROR TrainStepTwoEngine::InitModel() { modelinfo.yolov5ClearityModelParam.uiClassNum = class_num; modelinfo.yolov5ClearityModelParam.uiClearNum = clear_num; modelinfo.yolov5ClearityModelParam.uiDetSize = det_size; modelinfo.yolov5ClearityModelParam.fScoreThreshold = score_threshold; modelinfo.yolov5ClearityModelParam.fNmsThreshold = nms_threshold; modelinfo.modelCommonInfo.uiModelWidth = model_width; modelinfo.modelCommonInfo.uiModelHeight = model_height; modelinfo.modelCommonInfo.uiInputSize = input_size; modelinfo.modelCommonInfo.uiOutputSize = output_size; modelinfo.modelCommonInfo.uiChannel = INPUT_CHANNEL; modelinfo.modelCommonInfo.uiBatchSize = batch_size; modelinfo.modelCommonInfo.strInputBlobName = INPUT_BLOB_NAME; modelinfo.modelCommonInfo.strOutputBlobName = OUTPUT_BLOB_NAME; string strModelName = ""; int nRet = yolov5model.YoloV5ClearityInferenceInit(&modelinfo, strModelName, modelConfig_.strOmPath); if (nRet != 0) { LogInfo << "YoloV5ClassifyInferenceInit nRet:" << nRet; return APP_ERR_COMM_READ_FAIL; } return APP_ERR_OK; } APP_ERROR TrainStepTwoEngine::ReadModelInfo() { char szAbsPath[PATH_MAX]; // Get the absolute path of model file if (realpath(modelConfig_.strOmPath.c_str(), szAbsPath) == nullptr) { LogError << "Failed to get the real path of " << modelConfig_.strOmPath.c_str(); return APP_ERR_COMM_NO_EXIST; } // Check the validity of model path int iFolderExist = access(szAbsPath, R_OK); if (iFolderExist == -1) { LogError << "ModelPath " << szAbsPath << " doesn't exist or read failed!"; return APP_ERR_COMM_NO_EXIST; } //读取模型参数信息文件 Json::Value jvModelInfo; if (!MyUtils::getins()->ReadJsonInfo(jvModelInfo, modelConfig_.strModelInfoPath)) { LogError << "ModelInfoPath:" << modelConfig_.strModelInfoPath << " doesn't exist or read failed!"; return APP_ERR_COMM_NO_EXIST; } model_width = jvModelInfo["model_width"].asInt(); model_height = jvModelInfo["model_height"].asInt(); clear_num = jvModelInfo["clear"].isArray() ? jvModelInfo["clear"].size() : 0; class_num = jvModelInfo["class"].isArray() ? jvModelInfo["class"].size() : 0; input_size = GET_INPUT_SIZE(model_width, model_height); output_size = GET_OUTPUT_SIZE(model_width, model_height, clear_num, class_num); det_size = clear_num + class_num + 5; score_threshold = modelConfig_.fScoreThreshold; nms_threshold = modelConfig_.fNMSTreshold; return APP_ERR_OK; } APP_ERROR TrainStepTwoEngine::DeInit() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } yolov5model.YoloV5ClearityInferenceDeinit(); LogInfo << "TrainStepTwoEngine DeInit ok"; return APP_ERR_OK; } /** * push数据到队列,队列满时则休眠一段时间再push * inParam : const std::string strPort push的端口 : const std::shared_ptr &pProcessData push的数据 * outParam: N/A * return : N/A */ void TrainStepTwoEngine::PushData(const std::string &strPort, const std::shared_ptr &pProcessData) { while (true) { int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast(pProcessData)); if (iRet != 0) { LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet; if (iRet == 2) { usleep(10000); // 10ms continue; } } break; } } APP_ERROR TrainStepTwoEngine::Process() { if (!bUseEngine_) { LogWarn << "engineId_:" << engineId_ << " not use engine"; return APP_ERR_OK; } int iRet = APP_ERR_OK; while (!isStop_) { std::shared_ptr pVoidData0 = nullptr; inputQueMap_[strPort0_]->pop(pVoidData0); if (nullptr == pVoidData0) { usleep(1000); //1ms continue; } std::shared_ptr pProcessData = std::static_pointer_cast(pVoidData0); //组织输出数据 std::shared_ptr pPostData = std::make_shared(); pPostData->iModelType = MODELTYPE_NUM; //获取图片 if (pProcessData->iStatus == TRAINSTATUS_RUN || pProcessData->bIsEnd) { if (pProcessData->pData != nullptr && pProcessData->iSize != 0) { std::shared_ptr ppostbuff = std::static_pointer_cast(pProcessData->pVoidData); cv::Mat img(pProcessData->iHeight, pProcessData->iWidth, CV_8UC3, static_cast(pProcessData->pData.get())); //RGB for(int i = 0; i< ppostbuff->vecPostSubData.size(); i++) { PostSubData postsubdata = ppostbuff->vecPostSubData[i]; if (postsubdata.iTargetType != NUM && postsubdata.iTargetType != PRO && postsubdata.iTargetType != HEAD) { continue; } cv::Rect step2_rect(cv::Point(postsubdata.step1Location.fLTX, postsubdata.step1Location.fLTY), cv::Point(postsubdata.step1Location.fRBX, postsubdata.step1Location.fRBY)); cv::Mat step2_image = img(step2_rect).clone(); //进行推理 std::vector res; auto start = std::chrono::system_clock::now(); // 计时开始 yolov5model.YoloV5ClearityInferenceModel(step2_image, res); auto end = std::chrono::system_clock::now(); // LogInfo << "nopr2 inference time: " << std::chrono::duration_cast(end - start).count() << "ms"; PostSubData postSubDataNew; postSubDataNew.iTargetType = postsubdata.iTargetType; postSubDataNew.iBigClassId = postsubdata.iBigClassId; postSubDataNew.iCarXH = postsubdata.iCarXH; postSubDataNew.step1Location = postsubdata.step1Location; //整理推理结果 //根据非极大值抑制的结果标注相关信息(画框,文字信息等) //res.size()为每张图片上的识别到的对象数目 for (size_t j = 0; j < res.size(); j++) { SingleData singledata; singledata.iLine = res[j].clear_id; // singledata.iLine = -1; singledata.iClassId = res[j].class_id; singledata.fScore = res[j].class_conf; // singledata.iAnchorId = -1; singledata.fLTX = res[j].bbox[0]; singledata.fLTY = res[j].bbox[1]; singledata.fRBX = res[j].bbox[2]; singledata.fRBY = res[j].bbox[3]; singledata.fClear = res[j].clear_id; MyUtils::getins()->Step2ResetLocation(singledata, 1.0, pProcessData, postSubDataNew.step1Location); postSubDataNew.vecSingleData.emplace_back(singledata); // LogDebug << "sourceid:" << pProcessData->iDataSource << " step2 after frameId:" << pProcessData->iFrameId // << " --iClassId:" << singledata.iClassId << " iLine:" << singledata.iLine << " confidence=" << singledata.fScore // << " lx=" << singledata.fLTX << " ly=" << singledata.fLTY << " rx=" << singledata.fRBX << " ry=" << singledata.fRBY; } pPostData->vecPostSubData.emplace_back(postSubDataNew); } } } //及时释放内存 if (pProcessData->pData != nullptr) { pProcessData->pData = nullptr; pProcessData->iSize = 0; } // push端口0,第1步推理 pProcessData->pVoidData = std::static_pointer_cast(pPostData); PushData(strPort0_, pProcessData); } return APP_ERR_OK; } \ No newline at end of file