PicoDet

[English]

  • 组件注册表: espressif/brookesia_service_picodet

  • 辅助头文件: #include "brookesia/service_helper/media/picodet.hpp"

  • 辅助类: esp_brookesia::service::helper::PicoDet

概述

brookesia_service_picodet 是基于 esp-dl ESPDet-Pico 模型的端侧目标检测服务,提供:

  • 模型生命周期:通过 Open 加载一个模型,复用于后续推理,并通过 Close 释放。

  • 文件推理:通过 Detect 检测 JPEG 或 BMP 图片中的目标。

  • 帧流推理:通过 Attach 订阅调用方指定的帧事件。

  • 检测框显示:在输入帧上绘制缓存的检测框,并通过 Display 服务输出。

功能特性

模型包

模型包是一个文件系统目录,其中包含 ESP-DL 模型和 manifest.json 文件。manifest 控制以下字段:

字段

说明

model_file

模型包目录下 ESP-DL 模型文件的相对路径。

input

模型输入宽度和高度。

preprocess

均值、标准差、通道交换和 letterbox 填充颜色。

postprocess

置信度阈值、NMS 阈值、top-K 限制和 anchor-point strides。

labels

按推理返回的 category 值索引的类别名称。

适配其他兼容的 ESPDet-Pico 模型时,通常只需替换模型包,无需修改服务实现。

模型生命周期与文件推理

文件推理的一般流程如下:

  1. 使用 model_dir 调用 Open;可选的 score_thrnms_thr 会覆盖 manifest 配置。

  2. 使用 .jpg.jpeg.bmp 文件路径调用 Detect

  3. 读取返回的 {category, label, score, box} 对象;box 格式为 [x_min, y_min, x_max, y_max]

  4. 调用 Close 释放检测器和模型内存。

GetInfo 返回模型是否已打开,以及模型输入尺寸和标签。服务同一时间只保持一个模型处于打开状态。

帧流接入

Attach 会按名称动态订阅 frame_source 上的 frame_event。默认值分别为 VideoEncoder0StreamSinkFrameReady。帧源服务仍由调用方管理。

被订阅事件必须包含:

内容

类型

说明

Frame

RawBuffer

可写的 RGB 帧数据。

SinkInfo

Object

{format, width, height};format 支持 RGB565 和 RGB888。

PicoDet 每隔 detect_every_n_frames 帧执行一次推理,缓存最新检测框,并在每次推理后发布 DetectionUpdated。例如,取值为 5 表示每 5 帧推理一次,中间帧继续使用缓存的检测框。

调用 Detach 可断开帧事件并释放 Display 输出绑定。Detach 支持幂等调用。

显示输出

display_output 非空时,PicoDet 会注册 Display source、请求指定输出、原地绘制检测框,并通过 Display::present_frame_sync() 同步提交帧。

输入帧格式必须与所选 Display 输出的像素格式一致。检测、绘制和显示共用同一个帧回调路径,因此推理耗时会影响实际帧流速率。

摄像头接入

使用摄像头输入时:

  • enable_stream_mode: true 打开 VideoEncoder0,使其发布帧缓冲区。

  • 当 PicoDet 负责检测框显示输出时,不要同时启用 Video 服务自身的 Display 预览。

  • 单独启动和停止 Video 服务;Attach 不管理摄像头服务的生命周期。

  • 希望降低推理频率、避免阻塞每一帧时,可增大 detect_every_n_frames

模型部署

PicoDet 只接收文件系统路径,不负责生成、下载或安装模型包。常用部署方式如下:

  • 预置模型:将 model.espdlmanifest.json 添加到 LittleFS 或 SD 卡镜像。

  • 运行时下载:使用 HTTP 服务的 download_path 将两个文件写入存储,再把所在目录传给 Open

服务接口

函数

Open

描述

Load a PicoDet model. Example config: {"model_dir":"/littlefs/models/picodet_cat","score_thr":6E-1,"nms_thr":7E-1}

执行要求
  • 是否需要调度器: 需要

参数
  • Config

    • 类型: Object

    • 是否必填: 必填

    • 描述: Model load configuration. 'model_dir' is required; thresholds are optional overrides.

返回值
  • 类型: Object

  • 描述: Loaded model info. Example: {"opened":true,"width":224,"height":224,"labels":["cat"]}

Schema JSON
展开查看 JSON

{
  "name": "Open",
  "description": "Load a PicoDet model. Example config: {\"model_dir\":\"/littlefs/models/picodet_cat\",\"score_thr\":6E-1,\"nms_thr\":7E-1}",
  "require_scheduler": true,
  "default_timeout_ms": 5000,
  "parameters": [
    {
      "name": "Config",
      "description": "Model load configuration. 'model_dir' is required; thresholds are optional overrides.",
      "type": "Object",
      "required": true,
      "default_value": null
    }
  ],
  "return_value": {
    "type": "Object",
    "description": "Loaded model info. Example: {\"opened\":true,\"width\":224,\"height\":224,\"labels\":[\"cat\"]}"
  }
}
CLI 命令
svc_call PicoDet Open {"Config":null}

Detect

描述

Run detection on one image file and return the detected boxes.

执行要求
  • 是否需要调度器: 需要

参数
  • ImagePath

    • 类型: String

    • 是否必填: 必填

    • 描述: Filesystem path to a .jpg/.jpeg or .bmp image.

返回值
  • 类型: Array

  • 描述: Array of boxes. Example: {"category":0,"label":"cat","score":8.7E-1,"box":[12,34,120,210]}

Schema JSON
展开查看 JSON

{
  "name": "Detect",
  "description": "Run detection on one image file and return the detected boxes.",
  "require_scheduler": true,
  "default_timeout_ms": 5000,
  "parameters": [
    {
      "name": "ImagePath",
      "description": "Filesystem path to a .jpg/.jpeg or .bmp image.",
      "type": "String",
      "required": true,
      "default_value": null
    }
  ],
  "return_value": {
    "type": "Array",
    "description": "Array of boxes. Example: {\"category\":0,\"label\":\"cat\",\"score\":8.7E-1,\"box\":[12,34,120,210]}"
  }
}
CLI 命令
svc_call PicoDet Detect {"ImagePath":null}

Close

描述

Unload the model and reclaim memory.

执行要求
  • 是否需要调度器: 需要

参数
  • 无。

Schema JSON
展开查看 JSON

{
  "name": "Close",
  "description": "Unload the model and reclaim memory.",
  "require_scheduler": true,
  "default_timeout_ms": null,
  "parameters": [],
  "return_value": null
}
CLI 命令
svc_call PicoDet Close

GetInfo

描述

Query loaded state, model input size and labels.

执行要求
  • 是否需要调度器: 不需要

参数
  • 无。

返回值
  • 类型: Object

  • 描述: Loaded model info. Example: {"opened":true,"width":224,"height":224,"labels":["cat"]}

Schema JSON
展开查看 JSON

{
  "name": "GetInfo",
  "description": "Query loaded state, model input size and labels.",
  "require_scheduler": false,
  "default_timeout_ms": null,
  "parameters": [],
  "return_value": {
    "type": "Object",
    "description": "Loaded model info. Example: {\"opened\":true,\"width\":224,\"height\":224,\"labels\":[\"cat\"]}"
  }
}
CLI 命令
svc_call PicoDet GetInfo

Attach

描述

Wire the detector into the pipeline: subscribe to 'frame_event' on the 'frame_source' service (the caller owns that service's lifecycle) and run inference every N frames, publishing DetectionUpdated. When 'display_output' is set, also draw the boxes onto each frame and present it to that display output. Requires Open first. Example config: {"frame_source":"VideoEncoder0","frame_event":"StreamSinkFrameReady","display_output":"Output0","detect_every_n_frames":5}

执行要求
  • 是否需要调度器: 需要

参数
  • Config

    • 类型: Object

    • 是否必填: 可选

    • 默认值: {}

    • 描述: Attach configuration; all fields are optional.

Schema JSON
展开查看 JSON

{
  "name": "Attach",
  "description": "Wire the detector into the pipeline: subscribe to 'frame_event' on the 'frame_source' service (the caller owns that service's lifecycle) and run inference every N frames, publishing DetectionUpdated. When 'display_output' is set, also draw the boxes onto each frame and present it to that display output. Requires Open first. Example config: {\"frame_source\":\"VideoEncoder0\",\"frame_event\":\"StreamSinkFrameReady\",\"display_output\":\"Output0\",\"detect_every_n_frames\":5}",
  "require_scheduler": true,
  "default_timeout_ms": 5000,
  "parameters": [
    {
      "name": "Config",
      "description": "Attach configuration; all fields are optional.",
      "type": "Object",
      "required": false,
      "default_value": {}
    }
  ],
  "return_value": null
}
CLI 命令
svc_call PicoDet Attach {"Config":null}

Detach

描述

Unwire the detector from the frame source and release the display output.

执行要求
  • 是否需要调度器: 需要

参数
  • 无。

Schema JSON
展开查看 JSON

{
  "name": "Detach",
  "description": "Unwire the detector from the frame source and release the display output.",
  "require_scheduler": true,
  "default_timeout_ms": 5000,
  "parameters": [],
  "return_value": null
}
CLI 命令
svc_call PicoDet Detach

事件

DetectionUpdated

描述

Published after each inference while attached, with the fresh detection boxes.

执行要求
  • 是否需要调度器: 需要

参数
  • Boxes

    • 类型: Array

    • 描述: Array of boxes. Example item: {"category":0,"label":"cat","score":8.7E-1,"box":[12,34,120,210]}

Schema JSON
展开查看 JSON

{
  "name": "DetectionUpdated",
  "description": "Published after each inference while attached, with the fresh detection boxes.",
  "require_scheduler": true,
  "items": [
    {
      "name": "Boxes",
      "description": "Array of boxes. Example item: {\"category\":0,\"label\":\"cat\",\"score\":8.7E-1,\"box\":[12,34,120,210]}",
      "type": "Array"
    }
  ]
}
CLI 命令
svc_subscribe PicoDet DetectionUpdated