图像人脸数量
更新时间:2026-09-14
简介
图像人脸数量算子:用 OpenCV Haar 正脸级联检测图像中的人脸并计数,逐行输出人脸数量,过滤交给 pipeline。
功能描述
- 检测器:
cv2.CascadeClassifier+ OpenCV 自带的haarcascade_frontalface_alt.xml(cv2.data.haarcascades目录下),随 opencv 包安装,不需要纳管权重 - 纯 CPU,不用 GPU、不用 torch 推理
scale_factor/min_neighbors/min_size/max_size直接透传detectMultiScale;min_size、max_size为 None 时不传该参数(cv2 不接受 None)- 灰度化:
convert("RGB")后走COLOR_RGB2GRAY - 只计数,不做检测框的边界裁剪(
min(w, width - x))——裁剪不影响数量 - 级联 xml 加载失败(
CascadeClassifier.empty())在初始化阶段抛 FileNotFoundError,整个 UDF 起不来,而不是逐行报错 - 单行失败(读不到文件、非图像数据、输入类型与
image_src_type不匹配)打 exception 日志后该行填 None,不中断整批 - 一行一张图,逐行产出该图的人脸数
算子参数
输入
| 输入 | 含义 |
|---|---|
| images | 图像输入列,内容形式由 image_src_type 决定(路径/URL 字符串、base64 字符串、bytes) |
输出
| 输出 | 含义 |
|---|---|
| face_count | int32,检出人脸数(无脸为 0)。该行处理失败时为 None |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| image_src_type | str | "image_url" | 输入图像编码形式:image_url / image_base64 / image_binary |
| cv_classifier | str | "" | Haar 级联 xml 路径,空字符串用 OpenCV 自带的 haarcascade_frontalface_alt.xml |
| scale_factor | float | 1.1 | detectMultiScale 的 scaleFactor |
| min_neighbors | int | 3 | detectMultiScale 的 minNeighbors |
| min_size | tuple[int,int] 或 None | None | 最小人脸尺寸,None 表示不限制(不传 minSize) |
| max_size | tuple[int,int] 或 None | None | 最大人脸尺寸,None 表示不限制(不传 maxSize) |
注意事项
- 本算子只产出统计字段,不做过滤。例如「只留恰好一张脸的样本」这类条件(
face_count == 1)要自己在 pipeline 里写。 - Haar 正脸级联的精度就是本算子的上限:侧脸、遮挡、远处小脸会漏检,纹理密集区域(布面印花、格栅、卡通图案)会误检。想要更准的人脸框,用存量的
daft.aihc.functions.image.image_face_detect.ImageFaceDetect(insightface,可用 GPU),本算子的定位是轻量 CPU 统计。 - 调大
min_size能压掉一部分小尺寸误检,但同时会丢掉远处的真脸,改之前先在自己的数据上比对。
调用示例
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.image.image_face_count import ImageFaceCount
10
11if __name__ == "__main__":
12 if os.getenv("DAFT_RUNNER", "native") == "ray":
13 import ray
14 ray.init(dashboard_host="0.0.0.0", ignore_reinit_error=True)
15 daft.set_runner_ray()
16 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
17
18samples = {"image": ["bos://your-bucket/sample.jpg"]}
19 ds = daft.from_pydict(samples)
20 ds = ds.with_column(
21 "face_count",
22 aihc_udf(
23 ImageFaceCount,
24 construct_args={
25 "image_src_type": "image_url",
26 "scale_factor": 1.1,
27 "min_neighbors": 3,
28 },
29 num_cpus=1,
30 concurrency=4,
31 batch_size=32,
32 )(col("image")),
33 )
34 ds = ds.where(col("face_count") == 1)
35 ds.show()
评价此篇文章
