【Milk-V Duo S 开发板免费体验】测试实时人脸检测与 RTSP 推流应用

引言

今天继续测试一下Milk-V DuoS开发板。这个开发板有一个sample_vi_fd示例。这个程序是一个基于嵌入式视频处理平台的实时人脸检测与 RTSP 推流应用,主要功能是从视频输入设备获取图像,通过深度学习模型检测人脸,在图像上绘制人脸框,并将处理后的图像通过 RTSP 协议实时推流。

程序原理

程序源码可以从下面地址下载:duo-tdl-examples/sample_vi_fd/sample_vi_fd.c at master · milkv-duo/duo-tdl-examples · GitHub

程序整体功能概述

程序通过多线程协作完成以下流程:

  1. 视频输入(VI):从摄像头传感器获取原始图像。
  2. 视频处理(VPSS):对原始图像进行预处理(如缩放),并分发到两个通道。
  3. 人脸检测(TDL):一个线程从 VPSS 通道获取图像,通过 RetinaFace 模型检测人脸,保存人脸信息。
  4. 图像绘制与推流:另一个线程从 VPSS 另一通道获取图像,叠加人脸框后,通过 RTSP 协议推流,供客户端查看。
  5. 线程同步:通过互斥锁实现人脸检测结果在两个线程间的安全传递。
  6. 资源管理:初始化 / 销毁视频处理组件、深度学习模型,处理信号以优雅退出。

核心组件与变量解析

1. 宏定义与头文件

  • #define LOG_TAG "SampleFD":定义日志标签,用于区分不同模块的日志输出。
  • #define LOG_LEVEL LOG_LEVEL_INFO:定义日志级别(INFO 级),控制日志输出的详细程度。
  • 头文件:包含平台相关的多媒体处理库(middleware_utils.hvi_vo_utils.h)、视频编码 / RTSP 库(rtsp.hsample_comm.h)、深度学习库(cvi_tdl.h)等,均为芯片厂商提供的底层接口。

2. 全局变量与同步机制

  • static volatile bool bExit:线程退出标志(volatile确保多线程下可见性),用于控制所有线程的循环退出。
  • static cvtdl_face_t g_stFaceMeta:存储人脸检测结果(如人脸坐标、数量等),供两个线程共享。
  • static uint32_t g_size:记录当前检测到的人脸数量,用于打印数量变化。
  • MUTEXAUTOLOCK_INIT(ResultMutex):初始化互斥锁ResultMutex,用于保护g_stFaceMeta的读写(避免线程安全问题)。

3. 数据结构

  • SAMPLE_TDL_VENC_THREAD_ARG_S:编码器线程的参数结构体,包含中间件上下文(pstMWContext)和 TDL 服务句柄(stServiceHandle),用于线程间传递必要的资源句柄。

核心线程功能解析

1. 编码器线程(run_venc函数)

功能:从 VPSS 通道获取图像,叠加人脸框后通过 RTSP 推流。
流程

  • 循环直到bExittrue
    1. 调用CVI_VPSS_GetChnFrame(0, 0, &stFrame, 2000)从 VPSS 组 0 的通道 0 获取图像帧(超时 2000ms)。
    2. 加锁(MutexAutoLock):从全局变量g_stFaceMeta复制人脸信息到本地stFaceMeta,并释放g_stFaceMeta的资源。
    3. 调用CVI_TDL_Service_FaceDrawRect:在图像帧上绘制人脸矩形框(基于stFaceMeta的信息)。
    4. 调用SAMPLE_TDL_Send_Frame_RTSP:将绘制后的图像通过 RTSP 协议推流。
    5. 释放图像帧和人脸元数据资源,若出错则设置bExittrue,退出循环。

2. TDL 线程(run_tdl_thread函数)

功能:从 VPSS 通道获取图像,执行人脸检测,更新全局人脸信息。
流程

  • 循环直到bExittrue
    1. 调用CVI_VPSS_GetChnFrame(0, 1, &stFrame, 2000)从 VPSS 组 0 的通道 1 获取图像帧。
    2. 调用CVI_TDL_ScrFDFace(pstTDLHandle, &stFrame, &stFaceMeta):使用 RetinaFace 模型检测人脸,结果存入stFaceMeta
    3. 若人脸数量(stFaceMeta.size)变化,打印最新数量。
    4. 加锁:将本地stFaceMeta复制到全局g_stFaceMeta(供编码器线程使用)。
    5. 释放图像帧和人脸元数据资源,若出错则设置bExittrue,退出循环。

信号处理(SampleHandleSig函数)

  • 作用:捕获SIGINT(Ctrl+C)和SIGTERM(终止信号),设置bExit = true,触发所有线程退出循环,实现程序优雅终止。

主函数(main函数)

功能:初始化系统资源、创建线程、协调程序生命周期。
关键步骤

  1. 参数检查:要求输入 RetinaFace 模型路径(argv[1]),否则打印用法并退出。
  2. 信号注册:绑定SIGINTSIGTERMSampleHandleSig
  3. 配置初始化
    • 获取视频输入(VI)配置(从sensor_cfg.ini读取传感器信息)。
    • 配置 VPSS(视频处理子系统):创建 2 个通道,分别用于推流(通道 0)和人脸检测(通道 1),设置图像尺寸为 1280x720。
    • 配置 VBPool(视频缓冲区):3 个缓冲区分别用于 VPSS 通道 0、通道 1 和 TDL 预处理。
    • 配置 VENC(视频编码器)和 RTSP 参数。
  4. 中间件初始化:调用SAMPLE_TDL_Init_WM初始化视频中间件(整合 VI、VPSS、VENC、RTSP 等组件)。
  5. TDL 初始化
    • 创建 TDL(深度学习)句柄,绑定 VPSS 资源。
    • 加载 RetinaFace 模型(CVI_TDL_OpenModel)。
  6. 线程创建
    • 启动编码器线程(run_venc)和 TDL 线程(run_tdl_thread)。
    • 调用pthread_join等待线程结束。
  7. 资源释放:销毁 TDL 句柄、服务句柄和中间件资源,程序退出。

关键技术点

  1. 多线程协作:两个线程分别负责 “人脸检测” 和 “图像绘制 + 推流”,通过互斥锁(ResultMutex)同步人脸数据,避免竞态条件。
  2. 视频处理流水线:VI(输入)→ VPSS(预处理 + 分发)→ TDL(人脸检测)/VENC(编码)→ RTSP(推流),各组件通过句柄和 API 交互。
  3. 资源管理:严格的资源释放逻辑(如CVI_VPSS_ReleaseChnFrame释放图像帧、CVI_TDL_Free释放人脸元数据),避免内存泄漏。
  4. 实时性保障:通过超时机制(CVI_VPSS_GetChnFrame的 2000ms 超时)和轻量化处理,确保视频流实时性。

小结

该程序是一个典型的嵌入式实时视频分析应用,基于专用视频处理芯片的 API,实现了 “人脸检测 + RTSP 推流” 的端到端功能,可用于安防监控、人脸门禁等场景。其核心设计在于通过多线程和同步机制,高效协调视频采集、AI 推理和网络推流的流程。

编译测试

代码下载

代码网站地址:GitHub - milkv-duo/duo-tdl-examples: Duo TDL-SDK samples for SDK V2

编译这个例子不需要下载完整的SDK。这个例子中的代码已经足够了。

进入代码目录:

cd duo-tdl-examples

加载编译环境:

source envsetup.sh

第一次加载会自动下载所需的编译工具链,下载后的目录名为host-tools,下次再加载编译环境时,会检测该目录,如果已存在则不会再次下载。前面已经编译过SDK,所以不需要再下载host-tools。可以直接编辑envsetuo.sh修改host-tools路径。

加载编译环境时需要按提示输入所需编译目标:

Select Product:
1. Duo (CV1800B)
2. Duo256M (SG2002) or DuoS (SG2000)

目标板是  DuoS 选择 2。由于 Duo256M 和 DuoS 支持 RISCV 和 ARM 两种架构,还需要按提示继续选择:

Select Arch:
1. ARM64
2. RISCV64
Which would you like:

我们是 RISCV 系统则选择 2

同一个终端中,只需要加载一次编译环境即可。

人脸检测的示例程序为 sample_vi_fd,进入到 sample_vi_fd 目录:

cd sample_vi_fd

使用 make 命令编译:

make

将当前目录中生成的 sample_vi_fd 程序通过 scp 或者其他方式上传到 Duo 系列开发板中进行测试。如需清除编译生成的程序,可以执行 make clean 清除。

通过网络直接上传到 Duo  S开发板中的程序,可能没有执行权限,需要先在开发板的系统里通过 chmod 命令添加可执行权限:

chmod +x sample_vi_fd

下载 scrfd_det_face_432_768_INT8_cv181x.cvimodel 模型并上传至板端。

在开发板中测试该人脸检测示例的命令为 sample_vi_fd + 人脸检测模型文件注意 Duo 和 Duo256M/DuoS 中使用的模型是不同的

  • Duo (CV180X)

    ./sample_vi_fd /mnt/cvimodel/scrfd_320_256_ir_0x.cvimodel
    
  • Duo256M/DuoS (SG200X)

    ./sample_vi_fd /mnt/cvimodel/scrfd_768_432_int8_1x.cvimodel
    

此时将摄像头对准人脸,终端日志中会打印当前检测到人脸的数量。

结束语

至此验证了程序的正确性,但是这个程序有个问题,就是它的RTSP地址永远是eth0的IP地址,没法修改,而我们在测试中使用的wlan。要想改变地址,似乎只有自己写rtsp程序部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神一样的老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值