首页
商城
  • English
  • 简体中文
首页
商城
  • English
  • 简体中文
  • 产品系列

    • FPGA+ARM

      • GM-3568JHF

        • 一、简介

          • GM-3568JHF 简介
        • 二、快速开始

          • 00 前言
          • 01 环境搭建
          • 02 编译说明
          • 03 烧录指南
          • 04 调试工具
          • 05 软件更新
          • 06 查看信息
          • 07 测试命令
          • 08 应用编译
          • 09 源码获取
        • 三、外设与接口

          • 01 USB
          • 02 显示与触摸
          • 03 以太网
          • 04 WIFI
          • 05 蓝牙
          • 06 TF-Card
          • 07 音频
          • 08 串口
          • 09 CAN
          • 10 RTC
        • 四、应用开发

          • 01 UART读写案例
          • 02 按键检测案例
          • 03 LED灯闪烁案例
          • 04 MIPI屏幕检测案例
          • 05 读取 USB 设备信息案例
          • 06 FAN 检测案例
          • 07 FPGA FSPI 通信案例
          • 08 FPGA DMA 读写案例
          • 09 GPS调试案例
          • 10 以太网测试案例
          • 11 RS485读写案例
          • 12 FPGA IIC 读写案例
          • 13 PN532 NFC读卡案例
          • 14 TF卡读写案例
        • 五、QT开发

          • 01 ARM64交叉编译器环境搭建
          • 02 QT 程序加入开机自启服务
        • 六、RKNN_NPU开发

          • 01 RK3568 NPU 概述
          • 02 开发环境搭建
          • 运行官方 YOLOv5 示例
        • 七、FPGA开发

          • ARM与FPGA通讯
          • FPGA开发手册
        • 八、其他

          • 01 根目录文件系统的修改
          • 02 系统自启服务
        • 九、资料下载

          • 资料下载
    • ShimetaPi

      • M4-R1

        • 一、简介

          • M4-R1简介
        • 二、快速上手

          • 01 OpenHarmony概述
          • 02 镜像烧录
          • 03 应用开发快速上手
          • 04 设备开发快速上手
        • 三、应用开发

          • 01 ArkUI

            • 1 ArkTS语言简介
            • 2 UI 组件-Row 容器介绍
            • 3 UI 组件-Column 容器介绍
            • 4 UI 组件-Text 组件
            • 5 UI 组件-Toggle 组件
            • 6 UI 组件-Slider 组件
            • 7 UI 组件-Animation 组件&Transition 组件
          • 02 资料获取

            • 1 OpenHarmony 官方资料
          • 03 开发须知

            • 1 Full-SDK替换教程
            • 2 引入和使用三方库
            • 3 HDC调试
            • 4 命令行恢复出厂模式
            • 5 升级App为system权限
          • 04 构建第一个应用

            • 1 构建第一个ArkTs应用-HelloWorld
          • 05 案例

            • 01 串口调试助手应用案例
            • 02 手写板应用案例
            • 03 数字时钟应用案例
            • 04 WIFI 信息获取应用案例
        • 四、设备开发

          • 1 Ubuntu环境开发

            • 01 环境搭建
            • 02 下载源码
            • 03 编译源码
          • 2 使用DevEco Device Tool 工具

            • 01 工具简介
            • 02 开发环境的搭建
            • 03 导入SDK
            • 04 HUAWEI DevEco Tool 功能介绍
        • 五、内核外设与接口

          • 01 指南
          • 02 设备树介绍
          • 03 NAPI 入门
          • 04 ArkTS入门
          • 05 NAPI开发实战演示
          • 06 GPIO介绍
          • 07 I2C通讯
          • 08 SPI通信
          • 09 PWM 控制
          • 10 串口通讯
          • 11 TF卡
          • 12 屏幕
          • 13 触摸
          • 14 Ethernet(以太网)
          • 15 M.2 硬盘
          • 16 音频
          • 17 WIFI & BT
          • 18 摄像头
        • 六、资料下载

          • 资料下载
      • M5-R1

        • 一、简介

          • M5-R1 开发文档
        • 二、快速上手

          • 镜像烧录
          • 环境搭建
          • 下载源码
        • 三、外设与接口

          • 树莓派接口
          • GPIO 接口
          • I2C 接口
          • SPI通信
          • PWM控制
          • 串口通讯
          • TF Card
          • 屏幕
          • 触摸
          • 音频
          • RTC
          • Ethernet
          • M.2
          • MINI-PCIE
          • Camera
          • WIFI&BT
        • 四、资料下载

          • 资料下载
      • Pico-G1

        • 一、产品概述

          • 01 芯片与硬件平台介绍
          • 02 SDK版本说明
        • 二、快速入门

          • 01 开发环境搭建
          • 02 镜像编译
          • 03 镜像烧录
          • 04 系统登录
          • 05 网络配置
          • 06 文件传输
          • 07 SDK目录结构
          • 08 部署第一个应用程序
          • 09 部署第一个驱动程序
          • 10 SD卡挂载
        • 三、外设与接口

          • 01 GPIO控制
          • 02 UART串口通信
          • 03 I2C 通信
          • 04 SPI 通信
        • 四、MPP媒体开发

          • 01 MPP媒体处理软件
          • 02 图像处理链路
          • 03 视频输入
          • 04 图像编码
        • 五、NPU与AI

          • 01 NPU驱动与运行库架构
          • 02 .xmm 模型加载
          • 03 SVP视频处理
          • 04 AI降噪 (AI_NR)
        • 六、应用程序示例

          • 01 区域运动检测应用
          • 02 MTCNN 人脸检测应用
    • 开源鸿蒙

      • SC-3568HA

        • 一、简介

          • SC-3568HA简介
        • 二、快速上手

          • OpenHarmony概述
          • 镜像烧录
          • 开发环境准备
          • Hello World应用以及部署
        • 三、应用开发

          • ArkUI

            • 第一章 ArkTS语言简介
            • 第二章 UI组件介绍和实际应用(上)
            • 第三章 UI组件介绍和实际应用(中)
            • 第四章 UI组件介绍和实际应用(下)
          • 拓展

            • 第一章 入门指引
            • 第二章 三方库的引用和使用
            • 第三章 应用编译以及部署
            • 第四章 命令行恢复出厂设置
            • 第五章 系统调试--HDC调试
            • 第六章 APP 稳定性测试
            • 第七章 应用测试
        • 四、设备开发

          • 第一章 环境搭建
          • 第二章 下载源码
          • 第三章 编译源码
        • 五、内核的外设与接口

          • 树莓派接口
          • GPIO 接口
          • I2C 接口
          • SPI通信
          • PWM控制
          • 串口通讯
          • TF Card
          • 屏幕
          • 触摸
          • 音频
          • RTC
          • Ethernet
          • M.2
          • MINI-PCIE
          • Camera
          • WIFI&BT
          • 树莓派拓展板
        • 六、资料下载

          • 资料下载
      • M-K1HSE

        • 一、简介

          • M-K1HSE 简介
        • 二、快速开始

          • 开发环境搭建
          • 源码获取
          • 编译说明
          • 烧录指南
        • 三、应用开发

          • 00 应用开发环境搭建
          • 01 第一个应用-Hello World
        • 四、外设与接口

          • 01 Audio
          • 02 RS485
          • 03 Display
        • 五、系统定制开发

          • 系统移植
          • 系统定制
          • 驱动开发
          • 系统调试
          • OTA升级
        • 六、资料下载

          • 资料下载
    • EVS相机

      • CF-NRS1

        • 一、简介

          • 01-产品介绍
          • 02-相关概念
          • 03-MultiVision Studio 介绍
        • 二、开发

          • 01-ShiMetaPi Hybrid vision SDK 介绍
          • 02-Hybrid_vision_toolkit
          • 03-Hybrid_vision_toolkit API (C++)
          • 04 Hybrid Vision algo
          • 05 Hybrid vision algo API
          • 06 EVS Network Server
          • 07 EVS Time Sync
          • 08 Web Window
        • 三、资料下载

          • 资料下载
        • 四、常见问题

          • 常见问题解决指南
      • CF-CRA2

        • 一、简介

          • CF-NRS2 简介
        • 二、资料下载

          • 资料下载
      • EVS模块

        • 一、相关概念
        • 二、硬件准备与环境配置
        • 三、示例程序使用指南
        • 资料下载
    • AI硬件

      • 1684XB-32T

        • 一、简介

          • AIBOX-1684XB-32简介
        • 二、快速上手

          • 初次使用
          • 网络配置
          • 磁盘使用
          • 内存分配
          • 风扇策略
          • 固件升级
          • 交叉编译
          • 模型量化
        • 三、应用开发

          • 开发简介

            • Sophgo SDK开发
            • SOPHON-DEMO简介
          • 大语言模型

            • 部署Llama3示例
            • Sophon LLM_api_server开发
            • 部署MiniCPM-V-2_6
            • Qwen-2-5-VL图片视频识别DEMO
            • Qwen3-chat-DEMO
            • Qwen3-Qwen Agent-MCP开发
            • Qwen3-langchain-AI Agent
          • 深度学习

            • ResNet(图像分类)
            • LPRNet(车牌识别)
            • SAM(通用图像分割基础模型)
            • YOLOv5(目标检测)
            • OpenPose(人体关键点检测)
            • PP-OCR(光学字符识别)
        • 四、资料下载

          • 资料下载
      • 1684X-416T

        • 简介

          • AIBOX-1684X-416简介
        • Demo简单操作指引

          • shimeta智慧监控demo的简单使用说明
      • RDK-X5

        • 简介

          • RDK-X5 硬件简介
        • 快速开始

          • RDK-X5 快速开始
        • 应用开发

          • AI在线模型开发

            • 实验01-接入火山引擎豆包 AI
            • 实验02-图片分析
            • 实验03-多模态视觉分析定位
            • 实验04-多模态图文比较分析
            • 实验05-多模态文档表格分析
            • 实验06-摄像头运用-AI视觉分析
          • 大语言模型

            • 实验01-语音识别
            • 实验02-语音对话
            • 实验03-多模态图片分析-语音对话
            • 实验04-多模态图片比较-语音对话
            • 实验05-多模态文档分析-语音对话
            • 实验06-多模态视觉运用-语音对话
          • ROS2基础开发

            • 实验01-搭建环境
            • 实验02-工作包的创建及编译
            • 实验03-运行 ROS2 话题通信节点
            • 实验04-ROS2 相机应用
          • 40pin-IO开发

            • 实验01-GPIO 输出(LED闪烁)
            • 实验02-GPIO 输入
            • 实验03-按键控制 LED
            • 实验04-PWM 输出
            • 实验05-串口输出
            • 实验06-IIC 实验
            • 实验07-SPI 实验
          • USB模块开发使用

            • 实验01-USB 语音模块使用
            • 实验02-声源定位模块使用
          • 机器视觉技术实战

            • 实验01-打开 USB 摄像头
            • 实验02-颜色识别检测
            • 实验03-手势识别体验
            • 实验04-YOLOv5物体检测
      • RDK-S100

        • 简介

          • RDK-S100 硬件简介
        • 快速开始

          • RDK-S100 硬件简介
        • 应用开发

          • AI在线模型开发

            • 实验01-接入火山引擎豆包 AI
            • 实验02-图片分析
            • 实验03-多模态视觉分析定位
            • 实验04-多模态图文比较分析
            • 实验05-多模态文档表格分析
            • 实验06-摄像头运用-AI视觉分析
          • 大语言模型

            • 实验01-语音识别
            • 实验02-语音对话
            • 实验03-多模态图片分析-语音对话
            • 实验04-多模态图片比较-语音对话
            • 实验05-多模态文档分析-语音对话
            • 实验06-多模态视觉运用-语音对话
          • ROS2基础开发

            • 实验01-搭建环境
            • 实验02-工作包的创建及编译
            • 实验03-运行 ROS2 话题通信节点
            • 实验04-ROS2 相机应用
          • 40pin-IO开发

            • 实验01-GPIO 输出(LED闪烁)
            • 实验02-GPIO 输入
            • 实验03-按键控制 LED
            • 实验04-PWM 输出
            • 实验05-串口输出
            • 实验06-IIC 实验
            • 实验07-SPI 实验
          • USB模块开发使用

            • 实验01-USB 语音模块使用
            • 实验02-声源定位模块使用
          • 机器视觉技术实战

            • 实验01-打开 USB 摄像头
            • 实验02-图像处理基础
            • 实验03-目标检测
            • 实验04-图像分割
    • 核心板

      • C-3568BQ

        • 简介

          • C-3568BQ 简介
      • C-3588LQ

        • 简介

          • C-3588LQ 简介
      • GC-3568JBAF

        • 简介

          • GC-3568JBAF 简介
      • C-K1BA

        • 简介

          • C-K1BA 简介

01 区域运动检测应用

本章节介绍一个基于 GK7206 的区域运动检测应用示例 —— rpi-detector。该应用通过板端 MPP 视频管线采集摄像头画面,以 MJPEG 流推送至浏览器,并在浏览器端实现可交互的 ROI(Region of Interest,感兴趣区域)运动检测——用户可拖拽、缩放检测区域,实时监控画面变化。同时板端也基于帧大小变化进行辅助运动检测。

应用源码位于 SDK 目录 app_sample/rpi-detector/,涵盖了视频采集、双通道编码(JPEG 快照 + MJPEG 流)、按需启停的视频管线、以及浏览器端像素级运动检测的完整链路,是一个不依赖 NPU 的纯软件视觉应用参考模板。

1 应用概述

1.1 功能特性

  • 实时 MJPEG 视频流:浏览器直接查看摄像头实时画面
  • 浏览器端 ROI 运动检测:用户可拖拽、缩放检测区域(绿色矩形框),实时对比帧间像素变化
  • 板端辅助运动检测:基于 MJPEG 帧大小变化的服务端运动事件检测,带动态基线校准
  • JPEG 快照捕获:实时缓存最新帧,支持通过 API 或 URL 获取当前画面快照
  • 可调检测阈值:通过 Web UI 滑块实时调整运动检测灵敏度(1%~80%)
  • 按需启停管线:视频管线仅在浏览器连接时启动,断开后自动释放硬件资源
  • Sensor GPIO 控制:启动时自动配置 Sensor 供电 GPIO

1.2 技术参数

参数值
传感器分辨率根据实际 Sensor 型号(如 2560 × 1440)
MJPEG 流分辨率640 × 480
JPEG 快照分辨率与传感器原始分辨率相同
视频帧率30 FPS(由 Sensor 决定)
Web 服务端口80
检测采样分辨率160 × 120(浏览器端降采样)
默认检测阈值20%(可调 1%~80%)
ROI 默认区域画面中心 50% × 50%
NPU 使用不使用(纯软件方案)

1.3 目录结构

app_sample/rpi-detector/
├── Makefile                      # 构建脚本
├── src/
│   ├── main.c                   # 主程序(Web 路由处理、GPIO 初始化)
│   └── rpi_detector_mjpeg.c     # 视频管线管理、MJPEG 流推送、运动检测
└── web/
    ├── index.html                # Web 前端页面
    ├── app.js                    # 前端逻辑(ROI 控制、像素级运动检测)
    └── style.css                 # 页面样式

1.4 与人脸检测应用的区别

特性rpi-detectorface_recognize
AI/NPU 推理不使用使用 MTCNN 三阶段网络
运动检测方式帧间像素差异 + 帧大小变化NPU 人脸检测
VENC 通道2 个(JPEG 快照 + MJPEG 流)1 个(MJPEG 流)
检测位置浏览器端(Canvas 像素对比)板端(NPU 推理线程)
管线生命周期按需启停(跟随浏览器连接)启动时创建、退出时销毁
适用场景入侵检测、安防监控、画面变化告警人脸检测、关键点定位

2 编译与部署

2.1 前置条件

在编译本应用之前,请确保已完成以下准备工作:

  1. SDK 环境已搭建:参照 SDK 编译 完成交叉编译工具链和 SDK 配置
  2. SDK 已完整编译一次:应用依赖 SDK 的公共库和头文件,需先执行完整编译生成 out/ 目录

2.2 编译应用

进入应用目录,使用 SDK 构建系统编译:

# 进入应用目录
cd <SDK_PATH>/app_sample/rpi-detector

# 编译(SDK Makefile 会自动使用交叉编译工具链)
make clean && make

编译原理

Makefile 通过 include $(SDK_DIR)/build/base.mk 和 include $(SAMPLE_DIR)/sample_base.mk 引入 SDK 的编译规则,自动配置交叉编译器、头文件路径和链接库。无需手动设置编译工具链。

编译成功后,在当前目录下生成可执行文件 project_02_rpi_detector。

2.3 部署到板端

相关信息

由于应用程序体积较大,需挂载 SD 卡后运行。

mkdir -p /sd_card
mount /dev/mmcblk1p1 /sd_card

使用 SCP 将以下文件传输到开发板:

# 在开发主机上执行

# 1. 传输可执行文件
scp project_02_rpi_detector root@<板端IP>:/sd_card/

# 2. 传输 Web 前端文件
scp web/* root@<板端IP>:/www/

前端文件部署

Web 前端文件需放置在板端 Web 服务器的静态文件根目录中(默认为 /www/)。可通过以下命令部署:

ssh root@<板端IP> "mkdir -p /www"
scp web/* root@<板端IP>:/www/

2.4 运行应用

通过 SSH 登录开发板,执行以下命令:

# 登录开发板
ssh root@<板端IP>

# 进入应用目录
cd /sd_card/

# 添加执行权限(首次)
chmod +x project_02_rpi_detector

# 运行(默认阈值 20)
./project_02_rpi_detector

# 或指定初始运动检测阈值(1~80)
./project_02_rpi_detector 30

启动后,终端会输出以下日志信息:

=== rpi-detector: Motion Detector for GK7206 ===
Web UI available at http://<board-ip>/
Motion threshold: 20
Starting web server... Camera pipeline will start when browser opens /mjpeg.

2.5 浏览器访问

在电脑浏览器中打开 http://<板端IP>/,即可看到运动检测界面:

  • 左侧:摄像头实时预览画面(MJPEG 流),覆盖一个绿色矩形 ROI 检测框
  • ROI 框操作:
    • 拖拽框体中心区域 → 移动检测区域
    • 拖拽四角圆形手柄 → 缩放检测区域
    • 点击「重置检测框」按钮 → 恢复默认位置和大小
  • 右侧控制面板:
    • 阈值滑块(1%~80%):调整运动检测灵敏度
    • 当前变化百分比:实时显示 ROI 区域内像素变化率
    • 触发次数:累计运动告警次数
    • 最近告警:显示告警历史
  • 检测触发:当 ROI 区域内像素变化超过阈值时,检测框会短暂闪红,并记录一次告警

2.6 停止应用

在终端按 Ctrl+C 发送 SIGINT 信号即可正常退出。应用会等待所有 MJPEG 流连接关闭后释放视频管线资源。

3 系统架构

3.1 整体数据流

应用的整体架构遵循「视频采集 → 双通道编码 → Web 展示 + 浏览器端运动检测」的管线:

整体数据流

3.2 双层运动检测机制

本应用采用 板端 + 浏览器端 的双层运动检测架构:

层级位置检测方法特点
板端检测MJPEG 流推送循环帧大小变化 + 动态基线校准粗粒度,抗 JPEG 编码抖动,需连续 3 帧异常
浏览器端检测Canvas 像素比较ROI 区域逐像素 RGB 差异细粒度,用户可自定义 ROI 区域,250ms 采样周期

这种设计的优势是:无人查看时零资源占用,有人连接时即时启动。

4 内部执行逻辑详解

4.1 启动流程

main() 函数的启动流程分为 4 个阶段:

// 阶段 1:配置 Sensor 供电 GPIO
enable_sensor_gpio();     // xmmm 配置寄存器 + GPIO46 导出、设为输出、拉高

// 阶段 2:设置运动检测阈值(可从命令行参数获取)
detector_set_motion_threshold(initial_threshold);

// 阶段 3:注册 MJPEG 处理器
web_server_set_mjpeg_handler(rpi_detector_mjpeg_send_stream,
                              rpi_detector_mjpeg_request_stop);

// 阶段 4:启动 Web 服务器(阻塞,等待浏览器连接)
web_server_run(rpi_detector_route_get);

// 退出时清理
rpi_detector_mjpeg_shutdown();  // 等待所有连接关闭,释放管线

Sensor GPIO 初始化

应用通过 enable_sensor_gpio() 函数完成两步操作:

  1. 使用 xmmm 工具配置 Sensor 电源管理寄存器(0x100C0044 = 0x00001000)
  2. 通过 sysfs 导出 GPIO46,设为输出模式并拉高电平,为 Sensor 供电

4.2 视频管线初始化

当首个浏览器请求 /mjpeg 时,rpi_detector_mjpeg_init_pipeline() 按以下顺序初始化管线:

  1. 系统初始化:配置 VB 内存池

    • Pool 0:VI 采集缓冲区(传感器原始分辨率)
    • Pool 1:VPSS 全分辨率 / VENC 编码缓冲区
    • Pool 2:VPSS 子码流缓冲区(640 × 480)
  2. 模块初始化:依次初始化 VI、VPSS、VENC 模块

  3. ISP 初始化:配置图像信号处理参数

  4. VI + ISP 启动:启动视频输入

  5. VPSS 配置:配置两个输出通道

    • ochn0:原始分辨率 → JPEG 快照编码
    • ochn1:缩放到 640 × 480 → MJPEG 流编码
  6. VENC 配置:双通道编码

    • chn0:JPEG 模式(全分辨率,用于快照)
    • chn1:MJPEG CBR 模式(640 × 480,用于流推送)
  7. 绑定关系:

VI(pipe=0, chn=0) ──bind──→ VPSS(pipe=0, ichn=0)
                              ├→ ochn0 ──bind──→ VENC chn0 (JPEG 快照)
                              └→ ochn1 ──bind──→ VENC chn1 (MJPEG 流)

4.3 MJPEG 流推送

rpi_detector_mjpeg_send_stream() 是 MJPEG 流推送的核心函数,在浏览器请求 /mjpeg 时被调用:

void rpi_detector_mjpeg_send_stream(int client_fd)
{
    // 1. 按需初始化管线(首个连接时启动)
    rpi_detector_mjpeg_init_pipeline();
    g_stream_ref_count++;

    // 2. 发送 MJPEG multipart 头
    send("HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n...");

    // 3. 循环获取 VENC 帧
    while (!g_stream_stop_requested) {
        // 3.1 等待 VENC 编码完成
        xmedia_venc_select(venc_mask, &timeout);
        xmedia_venc_query_status(g_venc_chn, &stat);
        xmedia_venc_get_stream(g_venc_chn, &stream, -1);

        // 3.2 板端运动检测(帧大小变化分析)
        update_motion_stats(&stream, frame_len);

        // 3.3 更新快照缓存
        update_snapshot_cache(&stream, frame_len);

        // 3.4 推送 JPEG 帧到浏览器
        send("--frame\r\nContent-Type: image/jpeg\r\nContent-Length: ...\r\n\r\n");
        send(jpeg_data);
        send("\r\n");

        // 3.5 释放帧
        xmedia_venc_release_stream(g_venc_chn, &stream);
    }

    // 4. 引用计数 -1,最后一个连接退出时销毁管线
    g_stream_ref_count--;
    if (g_stream_ref_count == 0) rpi_detector_mjpeg_deinit_pipeline();
}

4.4 板端运动检测算法

板端的运动检测在 MJPEG 流推送循环中执行(update_motion_stats()),基于帧大小变化进行分析:

设计要点:

  • 帧大小作为运动信号:MJPEG 编码下,画面内容变化会导致压缩后帧大小显著改变,这是一个无需解码的轻量级检测方法
  • 双条件过滤:同时要求帧大小偏离基线 且 相邻帧间有跳变,避免渐变场景的误触发
  • 连续帧确认:需连续 3 帧异常才触发告警,避免偶发噪声
  • 动态基线:基线通过 EMA 持续缓慢更新,适应光照渐变等缓慢场景变化

4.5 浏览器端 ROI 运动检测

浏览器端的运动检测在 app.js 中实现,使用 Canvas 对 MJPEG 流进行降采样后逐像素比较:

function detectMotionFrame() {
    // 1. 将 MJPEG 图像绘制到 160×120 Canvas(降采样)
    ctx.drawImage(img, 0, 0, 160, 120);
    const frame = ctx.getImageData(0, 0, 160, 120).data;

    // 2. 获取 ROI 区域在降采样坐标中的位置
    const sampleRoi = getRoiSampleRect(img);

    // 3. 逐像素比较 ROI 区域内的 RGB 差异
    for (y, x in ROI) {
        dr = |frame[i].R - prev[i].R|
        dg = |frame[i].G - prev[i].G|
        db = |frame[i].B - prev[i].B|
        if ((dr + dg + db) / 3 > 42)  // 单像素变化阈值
            changed++
    }

    // 4. 计算变化率
    ratio = (changed / total_pixels) * 100

    // 5. 与用户阈值比较,超过则上报
    if (ratio >= motionThreshold)
        reportMotion(ratio)  // POST /api/motion/trigger
}

关键参数:

参数值说明
SAMPLE_WIDTH × SAMPLE_HEIGHT160 × 120降采样分辨率,平衡精度与性能
PIXEL_DIFF_THRESHOLD42单像素 RGB 平均差异阈值
DETECTION_INTERVAL_MS250检测周期(毫秒)
TRIGGER_COOLDOWN_MS1200触发冷却时间,防止重复告警
DEFAULT_ROI中心 50% × 50%默认检测区域

4.6 ROI 交互控制

浏览器端的 ROI 检测框支持以下交互操作:

  • 整体拖拽:按住框体中心区域拖动,移动检测区域位置
  • 四角缩放:拖拽四角的圆形手柄(nw/ne/sw/se),调整检测区域大小
  • 位置持久化:ROI 位置和大小自动保存到 localStorage,刷新页面后恢复
  • 最小尺寸限制:ROI 最小为 8% × 8%,防止误操作缩放到不可见

4.7 快照功能

应用持续缓存最新一帧 JPEG 图像到内存中,通过以下 URL 获取:

/api/snapshot      → 返回当前缓存的 JPEG 快照
/snapshot.jpg      → 同上(别名)
/api/frame.jpg     → 同上(别名)

快照缓存使用互斥锁保护(g_snapshot_lock),确保读写安全。

4.8 Web API 接口

应用通过 rpi_detector_route_get() 注册了以下自定义 API 路由:

路由方法功能参数
/api/statusGET获取当前状态(运行状态、帧率、阈值、告警次数等)—
/api/motion/threshold?val=NGET设置运动检测阈值val: 1~80
/api/motion/trigger?ratio=NGET手动记录一次浏览器端运动告警ratio: 变化率
/api/motion/resetGET重置告警计数—
/api/alertsGET获取告警列表摘要—
/api/snapshotGET获取当前 JPEG 快照—
/snapshot.jpgGET快照别名—

/api/status 返回的 JSON 格式:

{
  "running": true,
  "fps": 30,
  "motion_threshold": 20,
  "motion_count": 5,
  "last_motion_time": "2026-06-08 14:30:25",
  "last_frame_time": "2026-06-08 14:31:02",
  "stream_url": "/mjpeg",
  "has_frame": true,
  "frame_size": 15384,
  "frame_mtime": 1749354662
}

5 如何编写类似应用

本节以 rpi-detector 为参考模板,讲解如何开发一个基于 GK7206 的视频采集 + Web 展示应用(不使用 NPU)。

5.1 开发步骤总览

步骤 1: 创建工程 → 复制 Makefile 模板 → 编写源码
步骤 2: GPIO/硬件初始化 → Sensor 供电、引脚配置
步骤 3: 初始化视频管线 → VI + VPSS + VENC 配置
步骤 4: 实现 MJPEG 流推送 → VENC 获取帧 → HTTP 分段推送
步骤 5: 实现业务逻辑 → 运动检测、快照缓存等
步骤 6: Web 前端 → HTML/JS/CSS 界面

5.2 步骤 1:创建工程

参照 rpi-detector 的目录结构创建新工程:

mkdir -p my_app/src my_app/web

编写 Makefile(可直接复制并修改):

ifeq ($(CFG_SDK_EXPORT_FLAG),)
        SDK_DIR := $(shell cd $(CURDIR)/../.. && /bin/pwd)
endif

include $(SDK_DIR)/build/base.mk
include $(SAMPLE_DIR)/sample_base.mk

TARGET := my_app                    # 修改为你的应用名

# 根据需要选择链接库:
# - 视频采集: 不需要额外库 (SAMPLE_LIBS 已包含)
# - IVE/MD:  -lxmedia_ive -lxmedia_md (硬件运动检测/图像处理)
# - NPU:     -lxmedia_svp -lxmedia_npu
LIBS := $(SAMPLE_LIBS) $(SAMPLE_COMMON_LIB) -lpthread

INCLUDES := $(SAMPLE_INCLUDES)
INCLUDES += -I$(SDK_DIR)/project/common    # 如果使用 web_server.c

CFLAGS := $(SAMPLE_CFLAGS) $(LIBS) $(INCLUDES)

SRCS := $(wildcard src/*.c) $(SDK_DIR)/project/common/web_server.c
OBJS := $(patsubst %.c, %.o, $(SRCS))

.PHONY: all clean

all: $(OBJS)
	$(AT)$(CC) -o $(TARGET) $^ $(CFLAGS)

%.o : %.c
	$(AT)$(CC) -c -o $@ $< $(CFLAGS)

clean:
	$(AT)rm -rf $(OBJS) $(TARGET)

5.3 步骤 2:视频管线配置要点

参照 rpi_detector_mjpeg_init_pipeline() 的初始化流程,关键配置项:

// 1. 视频参数
video_param.pixel_fmt = XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_420;  // NV21
video_param.data_width = XMEDIA_VIDEO_DATA_WIDTH_8;                  // 8-bit

// 2. 工作模式(全离线模式,最稳定)
sys_config.sys_conf.pipe_mode[0].vicap_viproc_mode = XMEDIA_WORK_MODE_OFFLINE;
sys_config.sys_conf.pipe_mode[0].viproc_vpss_mode = XMEDIA_WORK_MODE_OFFLINE;
sys_config.sys_conf.pipe_mode[0].gdc_vpss_mode = XMEDIA_WORK_MODE_OFFLINE;

// 3. VPSS 输出通道(根据需要配置 1~N 个)
// ochn0: 全分辨率 → JPEG 快照
// ochn1: 缩放分辨率 → MJPEG 流

// 4. VENC 通道配置
// JPEG 模式(快照):
g_venc_cfg.chn_info[0].payload_type = PT_JPEG;
g_venc_cfg.chn_info[0].support_dcf = XMEDIA_TRUE;  // 支持 EXIF

// MJPEG 模式(流):
g_venc_cfg.chn_info[1].payload_type = PT_MJPEG;
g_venc_cfg.chn_info[1].rc_mode = VENC_RC_MODE_MJPEGCBR;  // 恒定码率

5.4 步骤 3:实现按需管线管理

rpi-detector 的按需启停模式是一个实用的设计模式,核心逻辑:

static volatile int g_stream_ref_count = 0;
static pthread_mutex_t g_stream_lock = PTHREAD_MUTEX_INITIALIZER;

// 客户端连接时调用
void mjpeg_send_stream(int client_fd) {
    pthread_mutex_lock(&g_stream_lock);

    if (g_stream_ref_count == 0) {
        // 首个连接 → 初始化管线
        init_pipeline();
    }
    g_stream_ref_count++;
    pthread_mutex_unlock(&g_stream_lock);

    // ... MJPEG 流推送循环 ...

    pthread_mutex_lock(&g_stream_lock);
    g_stream_ref_count--;
    if (g_stream_ref_count == 0) {
        // 最后一个连接断开 → 释放管线
        deinit_pipeline();
    }
    pthread_mutex_unlock(&g_stream_lock);
}

5.5 步骤 4:MJPEG 流推送模板

MJPEG 流推送的标准模式(HTTP multipart/x-mixed-replace):

// 1. 发送 HTTP 响应头
send(client_fd,
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n"
    "Cache-Control: no-store\r\n"
    "Connection: close\r\n\r\n");

// 2. 循环获取编码帧并推送
while (!stop_requested) {
    // 等待 VENC 编码完成
    xmedia_venc_select(venc_mask, &timeout);
    xmedia_venc_query_status(venc_chn, &stat);
    xmedia_venc_get_stream(venc_chn, &stream, -1);

    // 计算帧总长度
    size_t frame_len = 0;
    for (i = 0; i < stream.pack_count; i++)
        frame_len += stream.pack[i].len - stream.pack[i].offset;

    // 发送帧头
    char header[256];
    snprintf(header, sizeof(header),
        "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: %zu\r\n\r\n",
        frame_len);
    send(client_fd, header, strlen(header), 0);

    // 发送帧数据
    for (i = 0; i < stream.pack_count; i++)
        send(client_fd, stream.pack[i].vir_addr + stream.pack[i].offset,
             stream.pack[i].len - stream.pack[i].offset, 0);

    send(client_fd, "\r\n", 2, 0);

    // 释放帧
    xmedia_venc_release_stream(venc_chn, &stream);
    free(stream.pack);
}

5.6 步骤 5:自定义 API 路由

通过 web_server_run() 注册自定义路由处理函数:

static int my_route_handler(int client_fd, const char *path)
{
    char json_buf[512];

    if (strcmp(path, "/api/my-endpoint") == 0) {
        snprintf(json_buf, sizeof(json_buf),
            "{\"status\":\"ok\",\"data\":%d}\n", my_data);
        web_send_json_ok(client_fd, json_buf);
        return 0;  // 已处理
    }

    return -1;  // 未处理,交给默认静态文件服务
}

5.7 关键编程要点

互斥锁保护共享状态

多个 MJPEG 客户端可能并发访问共享数据,需要互斥锁保护:

// 管线启停锁
pthread_mutex_lock(&g_mjpeg_lock);
// 操作 g_stream_ref_count、g_inited 等
pthread_mutex_unlock(&g_mjpeg_lock);

// 快照缓存锁
pthread_mutex_lock(&g_snapshot_lock);
// 读写 g_snapshot_buf、g_snapshot_size
pthread_mutex_unlock(&g_snapshot_lock);

帧大小运动检测的局限性

本应用采用帧大小变化作为板端运动检测信号,这是一种轻量但粗粒度的方法。开发者应注意:

  • 优势:无需解码 JPEG、无需额外内存、计算量极小
  • 局限:无法定位运动区域、对缓慢光照变化敏感、JPEG 编码参数波动可能导致误触发
  • 改进方向:如需更精确的板端运动检测,可使用 SDK 提供的 MD(Motion Detect)模块(-lxmedia_md)或 IVE 模块(-lxmedia_ive)进行硬件加速的帧差分析

错误处理与资源释放

管线初始化使用 goto 链式错误处理,确保任何步骤失败都能正确释放已分配的资源:

ret = sample_comm_isp_init(...);    if (ret) goto exit0;
ret = sample_comm_vi_start(...);    if (ret) goto exit1;
ret = sample_comm_vpss_start(...);  if (ret) goto exit2;
ret = sample_comm_venc_start(...);  if (ret) goto exit3;
// ...
return XMEDIA_SUCCESS;

exit3: sample_comm_vpss_stop(...);
exit2: sample_comm_vi_stop(...);
exit1: sample_comm_isp_stop(...);
exit0: sample_comm_isp_exit(...);
       rpi_detector_mjpeg_sys_exit();
       return ret;

5.8 常见问题排查

问题可能原因解决方案
浏览器画面黑屏Sensor GPIO 未正确初始化检查 enable_sensor_gpio() 返回值,确认 GPIO46 可用
MJPEG 流连接后断开VENC 编码失败或超时检查 VENC 配置参数、VB Pool 大小和数量是否足够
快照返回 404首个 MJPEG 连接前无快照先访问 /mjpeg 启动管线,等待几帧后再请求快照
运动检测误触发频繁JPEG 编码抖动导致帧大小波动增大阈值(如 30~50),或修改 trigger_delta 最小值
运动检测不触发阈值过高或 ROI 区域过小降低阈值、扩大 ROI 区域、检查画面是否在变化
多个浏览器连接时管线异常并发访问管线状态未加锁参照 g_mjpeg_lock 和 g_stream_ref_count 的互斥保护
管线初始化失败(返回非零错误码)VB 内存不足或模块冲突检查是否有其他程序占用 VI/VPSS/VENC 资源
浏览器端 ROI 检测框无法拖拽CSS 层级冲突或 JS 未加载检查浏览器控制台错误,确认 app.js 正常加载

6 参考链接

  • MPP 媒体处理平台
  • 图像处理链路
  • 视频输入
  • 图像编码
  • SDK 编译指南
  • 文件传输
  • MTCNN 人脸检测应用
在 GitHub 上编辑此页
上次更新:
贡献者: ljh
Next
02 MTCNN 人脸检测应用