视频目标分割
更新时间:2026-09-14
简介
文本引导的视频目标分割算子:首帧用 YOLOE 按文本类别做开集检测,检测框作为提示交给 SAM2.1 在整段视频里传播,得到逐帧逐目标的分割掩码。掩码以 RLE 形式输出。
功能描述
- 首帧检测:
YOLOE.set_classes(class_names, get_text_pe(class_names))后predict(conf=yoloe_conf),输出框(xyxy 取整)、类别 id、置信度 - 加载 YOLOE 文本提示编码前会临时
chdir到权重所在目录:ultralytics 按相对路径找mobileclip_blt.pt - 整段传播:
Sam2VideoProcessor.init_video_session+add_inputs_to_inference_session(首帧、全部框),先显式对首帧推理一次,再走propagate_in_video_iterator逐帧取掩码 - 目标 id 以
session.obj_ids为准(add_inputs_to_inference_session会消费掉传入的obj_ids列表) - 掩码后处理
binarize=False,算子自己按binarize_threshold二值化(logit > 阈值为前景),再压成 RLE:rle_counts是交替的 0/1 段长、约定从 0 段开始,首段为前景时补一个长度 0 的 0 段;段长之和等于shape的元素总数 - 掩码按 RLE 存储而不是把每帧每目标的位图全量入内存,避免长视频 OOM
- 算子内不做网络请求与安装,
transformers版本不足时只在 import 失败时报错要求升级镜像 - 权重全部从本地预置目录加载,不联网下载;SAM2 目录或 YOLOE 权重缺失时
__init__直接失败 max_frames截断:SAM2 会把帧全部载入内存,超过上限只处理前 N 帧- 类别列为空时回落
default_class_names;两者都为空该行按错误处理 - 首帧检不到目标时返回空
segment_data,status为success: no object detected,cls_id_dict仍带出 YOLOE 的类别表 - 单行异常只记日志并写
status为error: <信息>,不影响同批其它行 - CPU 环境下推理精度强制为 float32(
dtype只在 GPU 生效)
算子参数
输入
| 输入 | 含义 |
|---|---|
| videos | 视频路径数组,支持本地路径与 BOS 路径(远端路径先下载到临时目录) |
| class_names | 目标类别名数组(list |
输出
输出为一个 struct 列,字段如下:
| 输出 | 含义 |
|---|---|
| segment_data | list |
| cls_id_dict | list |
| object_cls_list | list |
| yoloe_conf_list | list |
| frame_count | int32,实际处理的帧数(已按 max_frames 截断) |
| status | string,success / success: no object detected / error: no frames / error: <信息> |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| sam2_model_name | str | "facebook/sam2.1-hiera-tiny" | 相对 model_path 的 SAM2 权重子目录 |
| yoloe_model_name | str | "yoloe/yoloe-11l-seg.pt" | 相对 model_path 的 YOLOE 权重文件,同目录需有 mobileclip_blt.pt |
| default_class_names | list[str] 或 None | None | 输入类别列为空时使用的兜底类别名 |
| yoloe_conf | float | 0.5 | YOLOE 检测置信度阈值 |
| dtype | str | "bfloat16" | SAM2 推理精度,可选 bfloat16 / float16 / float32;CPU 上强制 float32 |
| max_frames | int 或 None | 300 | 单视频最多处理帧数,None 表示不截断 |
| binarize_threshold | float | 0.0 | 掩码二值化阈值,logit 大于该值视为前景 |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:<rank % 可见卡数> |
注意事项
- 掩码是 RLE,不是位图:按
shapereshape 前先把rle_counts展开成 0/1 序列(首段是背景段,长度可能为 0)。校验方式是段长之和等于shape各维乘积。 segment_data的第一项来自对首帧的显式推理,其后各项来自propagate_in_video_iterator的产出,frame_index取的是迭代序号而非 SAM2 返回的帧号。transformers必须 >= 4.56(Sam2VideoModel/Sam2VideoProcessor自该版本起是正式 API)。算子不会在运行时安装依赖,版本不足只报错。- YOLOE 的文本提示依赖
mobileclip_blt.pt与权重同目录,缺失时只打 warning,实际会在get_text_pe阶段失败。 - 长视频显存/内存占用由
max_frames决定,SAM2 的 session 会持有全部帧,调大要同步评估显存。 - 是否用 GPU 由
aihc_udf的num_gpus推导(基类按num_gpus > 0置use_gpu),rank只用于多卡取模选卡。
调用示例
Python
1from __future__ import annotations
2
3import os
4
5import daft
6from daft import col
7
8from daft.aihc.common.udf import aihc_udf
9from daft.aihc.functions.video.video_object_segment import VideoObjectSegment
10
11os.environ.setdefault("BOS_ENDPOINT", "http://bj.bcebos.com")
12os.environ.setdefault("BOS_REGION", "bj")
13
14if __name__ == "__main__":
15 if os.getenv("DAFT_RUNNER", "native") == "ray":
16 import ray
17 ray.init(dashboard_host="0.0.0.0", ignore_reinit_error=True)
18 daft.set_runner_ray()
19 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
20
21ds = daft.from_pydict(
22 {
23 "video": ["bos://your-bucket/sample.mp4"],
24 "classes": [["person", "cat", "dog", "car"]],
25 }
26 )
27 ds = ds.with_column(
28 "segment",
29 aihc_udf(
30 VideoObjectSegment,
31 construct_args={
32 "model_path": "/path/to/models",
33 "sam2_model_name": "facebook/sam2.1-hiera-tiny",
34 "yoloe_model_name": "yoloe/yoloe-11l-seg.pt",
35 "yoloe_conf": 0.25,
36 "max_frames": 30,
37 },
38 num_cpus=1,
39 num_gpus=1,
40 concurrency=1,
41 batch_size=1,
42 )(col("video"), col("classes")),
43 )
44 ds = ds.with_column("status", col("segment")["status"])
45 ds = ds.with_column("frame_count", col("segment")["frame_count"])
46 ds.show()
评价此篇文章
