如何让 MediaPipe FaceDetector 检测摄像头中的人脸?
数据小许
代码打开了摄像头并显示画面,但没有将视频帧传给 FaceDetector。在 LIVE_STREAM 模式下,每读取一帧都要调用 detector.detect_async()。调用前还要将 OpenCV 的 BGR 图像转换为 RGB,并封装成 mp.Image。
修改摄像头循环
下面的示例沿用 LIVE_STREAM 和 result_callback。请确认 model_asset_path 指向实际存在的 .tflite 模型文件。
import time
import cv2 as cv
import mediapipe as mp
BaseOptions = mp.tasks.BaseOptions
FaceDetector = mp.tasks.vision.FaceDetector
FaceDetectorOptions = mp.tasks.vision.FaceDetectorOptions
FaceDetectorResult = mp.tasks.vision.FaceDetectorResult
VisionRunningMode = mp.tasks.vision.RunningMode
def print_result(
result: FaceDetectorResult,
output_image: mp.Image,
timestamp_ms: int,
):
print(f"face detector result: {result}")
options = FaceDetectorOptions(
base_options=BaseOptions(
model_asset_path=r"C:\Users\hugop\Documents\python\face_project\blaze_face_short_range.tflite"
),
running_mode=VisionRunningMode.LIVE_STREAM,
result_callback=print_result,
)
cap = cv.VideoCapture(0)
if not cap.isOpened():
raise RuntimeError("无法打开摄像头")
try:
with FaceDetector.create_from_options(options) as detector:
while True:
ret, frame = cap.read()
if not ret:
print("无法读取视频帧,退出。")
break
# OpenCV 读取的是 BGR;MediaPipe 图像使用 RGB。
rgb_frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
mp_image = mp.Image(
image_format=mp.ImageFormat.SRGB,
data=rgb_frame,
)
# LIVE_STREAM 要求时间戳以毫秒为单位,并随帧递增。
timestamp_ms = time.monotonic_ns() // 1_000_000
detector.detect_async(mp_image, timestamp_ms)
cv.imshow("Camera", frame)
if cv.waitKey(1) == ord("q"):
break
finally:
cap.release()
cv.destroyAllWindows()
原代码为何没有检测结果
原代码创建了 FaceDetector,也读取并显示了摄像头画面,但循环中没有调用检测方法。因此,result_callback 没有收到检测结果。detect_async() 会将每帧提交给异步检测流程,检测完成后再调用 print_result。
传给检测器的图像也要符合 MediaPipe 的格式要求。OpenCV 通常使用 BGR 通道顺序,所以示例先用 cv.cvtColor 将图像转为 RGB,再通过 mp.ImageFormat.SRGB 创建 mp.Image。异步调用还需要毫秒时间戳。示例使用单调时钟生成递增时间戳,避免系统时钟调整导致时间戳倒退。
检查事项
- 确认模型文件路径有效,且当前 Python 进程有权限读取该文件。
- 确认摄像头索引
0对应预期设备。设备不可用时,可尝试系统提供的其他摄像头索引。 - 检测结果通过回调异步返回,提交帧后不一定会立即打印。画面能显示只说明视频流读取成功,不能证明检测器已处理图像。
- 如果安装的 MediaPipe 版本不支持示例中的 Tasks API 或参数形式,请参考该版本对应的 API。
备注:内容仅供参考。
