VideoPipe視覺化視訊結構化框架開源了!

2022-10-08 12:07:10

完成多路視訊並行接入、解碼、多級推理、結構化資料分析、上報、編碼推流等過程,外掛式/pipe式程式設計風格,功能上類似英偉達的deepstream和華為的mxvision,但底層核心不依賴複雜難懂的gstreamer框架(少部分地方需要),框架主幹部分主要使用原生C++ STL實現,目標是平臺高可移植性。框架可用於:視訊結構化、以圖搜圖、目標行為分析等應用領域。

 

原始碼地址:https://github.com/sherlockchou86/video_pipe_c

主要功能

  • 視訊接入,支援file/rtsp/udp/rtmp等主流視訊流協定;
  • 多級推理,自帶檢測/分類/特徵提取等推理外掛。預設使用opencv.dnn實現,可基於其他類似tensorrt、甚至原生的pytorch/tensorflow擴充套件新的推理外掛;
  • 目標跟蹤,自帶基於iou的跟蹤外掛,可基於其他演演算法擴充套件新的跟蹤外掛;
  • 行為分析,自帶若干行為分析外掛,比如目標跨線、擁堵/目標聚集判斷;
  • 影象疊加,結構化資料和視訊融合顯示;
  • 訊息推播,自帶基於kafka的訊息推播外掛,可基於其他訊息中介軟體擴充套件新的外掛;
  • 錄影/截圖,自帶截圖/錄影外掛;
  • 編碼輸出,支援file/screen/rtmp/rtsp等主流方式輸出編碼結果;

主要特點

  • 視覺化偵錯,自帶pipe視覺化功能,可在介面實時顯示pipe的執行狀態,如pipe中各個環節的fps/快取佇列大小,以及計算pipe起/止外掛之間的時間延時,幫助程式設計師快速定位效能瓶頸位置;
  • 外掛與外掛之間預設採用「smart pointer」傳遞資料,資料從頭到尾,只需建立一次,不存在拷貝操作。當然,可根據需要設定「深拷貝」方式在外掛之間傳遞資料;
  • pipe中各通道視訊的fps、解析度、編碼方式、來源均可不同,並且可單獨暫停某一通道;
  • pipe中可傳遞的資料只有兩種,一種frame_meta資料、一種control_meta資料,結構清晰明瞭;
  • 外掛組合方式自由,在滿足客觀邏輯的前提下,可合併、可拆分,根據需要設計不同的pipe結構。同時自帶pipe結構檢查功能,識別出不合規的pipe結構;
  • pipe支援各種hook,外部通過hook可以實時獲取pipe的執行情況(第1點就是基於該特性實現);
  • 支援一個Pipe處理多路視訊(多路共用一個推理模型,Pipe分支涉及到merge和split操作),批次處理提速;也支援一個Pipe只處理一路視訊(各路使用自己的推理模型,Pipe呈直線狀、多個Pipe並存),基於不同視訊做不同的推理任務;
  • 基於指定基礎類別,所有自帶外掛全部可自定義重新實現;
  • 框架主幹程式碼完全基於原生C++ STL實現,跨平臺編譯部署簡單。

目前進度

開發環境:vs code/ubuntu 18.04/C++17/opencv 4.6/ffmpeg 3.4.8/gstreamer 1.20。之前使用wsl1/2+ubuntu22.04,但是wsl坑太多,後放棄。

  • 2022/9/30:完成基於tensorrt的檢測外掛(一級推理和二級推理),非預設的opencv::dnn。原始碼上線
  • 2022/9/15:完成基於paddle的ocr文字識別相關外掛,基於paddle推理庫(非預設的opencv::dnn)
  • 2022/9/1:完成基於yunet/sface的人臉檢測、識別以及顯示相關外掛開發,實現多pipe並行執行的機制,多個pipe可載入不同模型、基於不同視訊完成不同的推理任務。(單個pipe接入多路視訊、共用相同的模型之前已實現)
  • 2022/8/15:完成openpose肢體檢測器相關外掛開發,完成影象二級分類外掛開發。
  • 2022/8/5:完成infer相關基礎類別、yolo檢測器派生類的實現,走通整個一級推理流程,rtmp/screen 2種輸出。
  • 2022/7/22:已完成主幹框架開發,預估佔總體進度的1/3。等基本完成後開源,有興趣的朋友可以關注。

 

如何使用

#include "VP.h"

#include "../nodes/vp_file_src_node.h"
#include "../nodes/infers/vp_trt_vehicle_detector.h"
#include "../nodes/infers/vp_trt_vehicle_plate_detector.h"
#include "../nodes/osd/vp_osd_node_v2.h"
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_rtmp_des_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"

#if MAIN
int main() {
    // create nodes
    auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, "./test_video/13.mp4");
    auto trt_vehicle_detector = std::make_shared<vp_nodes::vp_trt_vehicle_detector>("vehicle_detector", "./vehicle.trt");
    auto trt_vehicle_plate_detector = std::make_shared<vp_nodes::vp_trt_vehicle_plate_detector>("vehicle_plate_detector", "./det.trt", "./rec.trt");
    auto osd_0 = std::make_shared<vp_nodes::vp_osd_node_v2>("osd_0", "./font/NotoSansCJKsc-Medium.otf");
    auto screen_des_0 = std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_0", 0, true, vp_objects::vp_size{640, 360});
    auto rtmp_des_0 = std::make_shared<vp_nodes::vp_rtmp_des_node>("rtmp_des_0", 0, "rtmp://192.168.77.105/live/10000", vp_objects::vp_size{1280, 720});

    // construct pipeline
    trt_vehicle_detector->attach_to({file_src_0});
    trt_vehicle_plate_detector->attach_to({trt_vehicle_detector});
    osd_0->attach_to({trt_vehicle_plate_detector});

    // split into 2 sub branches automatically
    screen_des_0->attach_to({osd_0});
    rtmp_des_0->attach_to({osd_0});

    // start pipeline
    file_src_0->start();

    // visualize pipeline for debug
    vp_utils::vp_analysis_board board({file_src_0});
    board.display();
}
#endif

 

上面程式碼可以生成3個畫面:

  • pipeline執行圖(window顯示)
  • 螢幕顯示結果(window顯示)
  • rtmp顯示結果(video player播放)