简介
● VideoPipe 这是一个用于视频分析和结构化的框架,采用 C++ 编写、依赖少、易上手。它就像一个管道每个节点相互独立可自行搭配,用来构建不同类型的视频分析管道,适用于视频结构化、图片搜索、人脸识别、安防领域的行为分析(如交通事件检测)等场景。
● VideoPipe和Deepstream类似
● VideoPipe 框架将视频分析/处理的步骤,抽象成了一个管道(pipe),每一步的处理都是管道中的一个节点(Node),处理流程如下:
a. 视频读取 Node:完成读取视频和解码的工作
b. 模型推理 Node:分为人脸检测和人脸识别两个模型
c. OSD Node:将模型输出的处理结果绘制到帧上
d. 构建管道:将上述节点依次连接,并将结果分成屏幕输出和推流输出,
e. 启动:启动程序,并展示管道的运行情况
环境依赖
平台
● Ubuntu 18.04 x86_64 NVIDIA rtx/tesla GPUs
● Ubuntu 18.04 aarch64 NVIDIA jetson serials device,tx2 tested
● Ubuntu 18.04 x86_64 Cambrian MLU serials device, MLU 370 tested (code not provided)
● Ubuntu 18.04 aarch64 Rockchip RK35** serials device, RK3588 tested (code not provided)
● windows x86_64
基础
● C++ 17
● OpenCV >= 4.6
● GStreamer 1.14.5 (Required by OpenCV)
● GCC >= 7.5
自选推理后端
● CUDA
● TensorRT
● Paddle Inference
● ONNX Runtime
原理
视频结构化应用的核心环节
● 视频结构化是将非结构化数据(视频/图片)转换为结构化数据的过程。非结构化数据通常包括:视频、图像、⾳频、⾃然语⾔文本,⽽结构化数据主要包括诸如 JSON、XML 或数据库中的数据表等,这些数据可以直接由机器(程序)处理。具体到视频(含图片,下同)结构化的过程,主要涉及以下核⼼部分:
○ 读取流:从⽹络或本地机器获取视频流。
○ 解码:将字节流解码为帧,因为算法只能作⽤于图像。
○ 推理:对图像进⾏深度学习推理,如检测、分类或特征提取。
○ 跟踪:跟踪视频中的⽬标。
○ ⾏为分析/逻辑处理:分析⽬标的轨迹、属性。
○ OSD:在图像上显⽰结果,⽤于调试或得到直观效果。
○ 消息代理:将结构化数据推送到外部,供业务平台使⽤。
○ 编码:对包含结果的帧进⾏编码,以便传输、存储。
○ 推送流:将字节流推送到外部或直接保存
● 上述每个环节对应 VideoPipe 中的⼀种插件类型,又可成为元素,即代码中的 Node 对象。下面我们将逐一讲解 VideoPipe 的 Node、数据流、钩子的技术细节和实现。和deepstream一样,通过管道的方式连接每个Node。
Node
● VideoPipe 中的每个 Node 负责⼀种任务(严格遵循单⼀职责原则),例如解码或推理。我们可以将许多节点串在⼀起构建成管道,并让视频数据流经整个管道。每个 Node 内部都有两个队列,⼀个⽤于缓存上游节点推送的数据(ds中为动态pad),另⼀个⽤于缓存等待被推送到下游节点的数据(ds中为静态pad)。我们可以在两个队列之间编写逻辑代码,这是典型的生产者-消费者模式。
● VideoPipe 中有三种类型的节点,分别是:
a. SRC节点:源节点,数据被创建的地⽅(内部只有⼀个队列,⽤于缓存被推送到下游节点的数据)。
b. MID节点:中间节点,数据将在此处理。
c. DES节点:⽬标节点,数据消失的地⽅(内部只有⼀个队列,⽤于缓存来⾃上游节点的数据)。
● 每个节点本⾝具有合并多个上游节点和拆分成多个下游节点的能⼒。注意,默认情况下节点在将数据从⼀个节点传输到另⼀个节点时使⽤浅拷⻉和等值拷⻉。如果您需要深拷⻉或希望按通道索引传输数据(希望数据不混淆),则在中间节点后添加⼀个 vp_split_node 类型节点。
数据流
● 视频是一种重量级数据,因此频繁进行深拷贝会降低管道的性能。实际上,VideoPipe 中两个节点之间传递的数据默认使用智能指针,一旦数据由源节点创建,数据内容在整个管道中大多数时间不会被复制。但如果需要,我们可以指定深度拷贝模式,使用 vp_split_node 类型节点。
● 视频由连续的帧组成,因此 VideoPipe 逐帧处理这些帧,所以帧元数据中的帧索引也会连续增加。
钩子
● 钩子是一种机制,让主体在发生某些事件时通知检测者,VideoPipe 也支持钩子。管道触发回调函数 std::function 与外部代码通信,例如实时推送管道自身的 fps、延迟和其他状态信息。我们在编写回调函数内部代码时,不允许有阻塞出现,否则影响整个管道性能。
● 钩子有助于调试我们的应用程序,并快速找出整个管道中的瓶颈,VideoPipe 框架中自带的可视化工具 vp_analysis_board 就是依赖于钩子机制实现的。
如何实现新的 Node 类型
● 首先 vp_node 是 VideoPipe 中所有节点的基类,我们可以定义一个从 vp_node 派生的新节点类,并重写一些虚函数:
● handle_frame_meta:处理流经当前节点的帧数据。
● handle_control_meta:处理流经当前节点的控制指令数据。
● 帧数据指的是 VideoPipe 中的 vp_frame_meta,其中包含与帧相关的数据,如帧索引、数据缓冲区、原始宽度等等。控制指令数据指的是 VideoPipe 中的 vp_control_meta,其中包含与事件命令相关的数据,例如记录视频、记录图像等。并非所有流经当前节点的数据都应该被处理,只需要处理我们感兴趣的内容。
docker安装
环境准备
c++17
● GCC 9.1 及更新的版本对 C++17 标准有最完整的支持
g++ --version
sudo apt-get update
sudo apt-get install gcc-9 g++-9 cmake
安装 GStreamer 1.16.3
● 最新版本是1.16.3
● 需要安装 libgstrtspserver-1.0-dev
sudo apt-get update
sudo apt-get install \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-doc \
gstreamer1.0-tools \
gstreamer1.0-x \
gstreamer1.0-alsa \
gstreamer1.0-gl \
gstreamer1.0-gtk3 \
gstreamer1.0-qt5 \
gstreamer1.0-pulseaudio
gst-launch-1.0 --version
sudo apt-get install libgstrtspserver-1.0-dev
#------------ 源代码编译安装 GStreamer 1.14.5 ------------#
wget https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.14.5.tar.xz
tar xf gstreamer-1.14.5.tar.xz
cd gstreamer-1.14.5
./configure
make
sudo make install
gst-launch-1.0 --version
安装opencv
● 最低4.6
● 本例装4.7
● 先安装gstreamer
# 安装依赖
sudo apt-get install cmake pkg-config libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev libjpeg-dev libpng-dev libtiff-dev libatlas-base-dev gfortran
# 查看是否安装 OpenCV4
pkg-config --modversion opencv4
# 安装
# sudo apt-get install libopencv-dev
# 拉取第三方插件
git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout 4.7.0
cd ..
# 源码编译安装opencv
git clone https://github.com/opencv/opencv.git -b 4.7.0
cd opencv
git checkout 4.7.0
mkdir build
mkdir install
cd build
# a30算力8.0 安装在自己的路径下
# 网络不稳定时, 编译会出现各种报错, 需要反复编译
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/home/projects/VideoPipe/opencv/install \
-D WITH_TBB=ON \
-D ENABLE_FAST_MATH=1 \
-D CUDA_FAST_MATH=1 \
-D WITH_CUBLAS=1 \
-D WITH_CUDA=ON \
-D BUILD_opencv_cudacodec=OFF \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D CUDA_ARCH_BIN=8.0 \
-D WITH_V4L=ON \
-D WITH_QT=OFF \
-D WITH_OPENGL=ON \
-D WITH_GSTREAMER=ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D OPENCV_PC_FILE_NAME=opencv4.pc \
-D OPENCV_ENABLE_NONFREE=ON \
-D OPENCV_EXTRA_MODULES_PATH=/home/projects/VideoPipe/opencv_contrib/modules \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D INSTALL_C_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF ..
make -j10
make install
# 添加环境变量
echo 'export PKG_CONFIG_PATH=/home/projects/VideoPipe/opencv/install/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc
source ~/.bashrc
# 检验安装
pkg-config --modversion opencv4
pkg-config --libs opencv4
安装videopipe
mkdir build
cd build
cmake -DOpenCV_DIR="/home/projects/VideoPipe/opencv/install" ..
make -j8
cd ..
报错解决方案
freetype模块
● Opencv contrib库中的freetype模块在配置阶段被忽略了,忽略的原因是缺少依赖库
● apt-get install libharfbuzz-dev libfreetype-dev libgtk2.0-dev pkg-config
rtsp推流方式
● 外部构建流媒体服务器
● 参考rtmp代码修改
跑样例
● 下载模型和测试文件vd_data
● build/bin 目录下