如何用 supervision 对视频帧中的面部做模糊处理保护隐私
【免费下载链接】supervisionWe write your reusable computer vision tools. 💜项目地址: https://gitcode.com/GitHub_Trending/su/supervision
当一段视频帧里出现了可识别的人脸,而你希望把这段画面用于示例、测试或对外分享时,人脸区域需要先做模糊处理。supervision 的官方 cookbook blurring_faces 给出的做法是:用 Roboflow Inference 接口调用托管的人脸检测模型拿到检测框,再用 supervision 的BlurAnnotator把检测区域模糊掉。整条路径是:下载含人物的示例视频 → 取一帧 → 人脸检测 → 模糊 → 目视确认。人脸检测依赖托管接口,因此前提是需要一个 Roboflow API key;模糊本身在本地完成。
安装依赖与准备 API key
在能访问 PyPI 的 Python 环境中安装依赖。tqdm用于显示进度条,cookbook 注明它在生产代码中是可选的:
pip3 install -q supervision inference tqdm "Pillow<12"人脸模型face-detection-mik1i/18托管在 Roboflow Universe 上,按 cookbook 说明,这类模型需要一个 Roboflow API key。注册(可免费注册)后,在 Settings > Workspaces > Roboflow API 下找到 key,然后设置为环境变量ROBOFLOW_API_KEY。cookbook 中的检查方式如下,key 缺失时会直接中断:
import os try: from google.colab import userdata ROBOFLOW_API_KEY = userdata.get("ROBOFLOW_API_KEY") or "" except ImportError: ROBOFLOW_API_KEY = os.environ.get("ROBOFLOW_API_KEY", "") assert ROBOFLOW_API_KEY, "Set ROBOFLOW_API_KEY in Colab secrets or as env var"如果你在 Colab 里运行,也可以把 key 存进 Colab secrets(secrets 机制见 cookbook 原注记),代码里google.colab.userdata分支就是为此准备的。
下载示例视频并定位含人脸的帧
supervision 自带 assets 下载工具(见 docs/assets.md),VideoAssets枚举里提供了若干示例视频,其中GROCERY_STORE是一段超市场景视频(grocery-store.mp4)。cookbook 里作者反复尝试后选定第 800 帧作为测试帧,因为该帧中顾客正对镜头。get_video_frames_generator的start参数可以直接从指定位置开始产出帧(docs/utils/video.md):
import supervision as sv video = sv.download_assets(sv.VideoAssets.GROCERY_STORE) # cookbook 中的说明:直接用 start 参数定位到第 800 帧 frame = next(sv.get_video_frames_generator(video, start=800)) sv.plot_image(frame)download_assets返回视频文件路径,后续VideoInfo和帧生成器都用这个变量。如果你的帧来自自己的视频文件,把video换成文件路径即可;选帧位置也要按你自己视频里人脸出现的帧号来定,800 只对这段示例视频成立。用sv.plot_image(frame)先确认这一帧里确实有人脸,再进入检测步骤。
调用 Roboflow 推理接口检测人脸
用inference_sdk的InferenceHTTPClient指向https://detect.roboflow.com,对帧做一次推理:
from inference_sdk import InferenceHTTPClient client = InferenceHTTPClient( api_url="https://detect.roboflow.com", api_key=ROBOFLOW_API_KEY ) results = client.infer(frame, model_id="face-detection-mik1i/18") print(f"Detected {len(results['predictions'])} face(s)")打印的Detected N face(s)是这一步的核对点:它反映接口返回的预测数量(results['predictions']的长度)。如果数字为 0 或明显偏少,问题在检测环节——先确认这一帧是否真的有人脸、key 与model_id是否填对,而不是去改模糊参数。cookbook 里还直接print(results)查看完整返回,排查时可以保留。
用 BlurAnnotator 生成模糊后的帧
检测拿到后,模糊是三步:把推理结果转成sv.Detections,构造BlurAnnotator,调用annotate:
blur = sv.BlurAnnotator(kernel_size=100) detections = sv.Detections.from_inference(results) annotated_frame = blur.annotate(scene=frame.copy(), detections=detections) sv.plot_image(annotated_frame)kernel_size的含义以 BlurAnnotator 的 docstring 为准:它是用于模糊的平均池化核尺寸;不设置时按检测框较短边的三分之一动态计算,显式提供时必须>= 1。cookbook 在超市视频这类较远的景别下用了100,作为示例值保留即可,是否合适以sv.plot_image的目视结果判断。scene传frame.copy()是避免在原帧上修改,原始帧保留下来方便对比。
同一分类下还有像素化的替代方案(docs/detection/annotators.md 的 Transformative 小节):
pixelate_annotator = sv.PixelateAnnotator() annotated_frame = pixelate_annotator.annotate( scene=image.copy(), detections=detections, )调用方式与BlurAnnotator一致,按你对遮挡风格的取舍选用其一即可。
确认模糊效果
验证方式是视觉核对:对同一帧先后sv.plot_image(frame)与sv.plot_image(annotated_frame),模糊后的帧里应满足两点——
- 检测框对应的人脸区域不可辨认;
- 框外画面与原帧一致。
BlurAnnotator.annotate的 docstring 写明它"基于提供的检测结果模糊图像中的区域",也就是说模糊范围严格由检测框决定:没检出的人脸不会被模糊。因此前面Detected N face(s)的核对结果决定了模糊覆盖范围,两步要放在一起看。
逐帧处理整段视频(可选)
cookbook 只处理单帧。如果要输出整段脱敏视频,docs/detection/annotators.md 中的视频标注示例给出了通用模式:VideoInfo.from_video_path读取视频元信息,get_video_frames_generator逐帧产出,VideoSink写入输出文件。把"推理 → 转换 → 模糊"套在每帧上:
video_info = sv.VideoInfo.from_video_path(video_path=video) frames_generator = sv.get_video_frames_generator(video) with sv.VideoSink(target_path="blurred_video.mp4", video_info=video_info) as sink: for frame in frames_generator: results = client.infer(frame, model_id="face-detection-mik1i/18") detections = sv.Detections.from_inference(results) annotated_frame = blur.annotate(scene=frame.copy(), detections=detections) sink.write_frame(frame=annotated_frame)target_path是你要写出的输出视频路径,按需替换;这里的blur和client沿用前文已构造的对象。注意这一写法中每一帧都会发起一次client.infer调用,处理时长由视频帧数与接口响应共同决定。
常见错误与限制
- key 缺失:会命中上文 assert,报错
Set ROBOFLOW_API_KEY in Colab secrets or as env var。 - kernel_size 非法:传入小于 1 的值时
BlurAnnotator抛出ValueError: kernel_size must be >= 1, got {value}(见 源码)。 - 视频设了 start 后无法打开:
get_video_frames_generator提供iterative_seek=True作为 workaround,通过逐帧抓取来定位到start,代价是更慢(见 源码 docstring)。 - 传入 PIL 图像不会模糊:
annotate的实现中,scene不是numpy.ndarray时直接原样返回(源码)。模糊必须作用在 numpy 帧上,这也是上面代码统一用sv.get_video_frames_generator取 numpy 帧、再frame.copy()传入的原因。
下一步如果要把这套流程接到真实业务视频,替换点只有两处:video换成你自己的视频路径、帧循环里按实际场景选择是否每帧都调用检测接口,其余代码(检测结果转换、模糊、写盘)保持不变。
【免费下载链接】supervisionWe write your reusable computer vision tools. 💜项目地址: https://gitcode.com/GitHub_Trending/su/supervision
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考