You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用OpenCV检测静止人脸并在其静止5秒后输出提示

人脸静止5秒触发提示的实现方案

核心逻辑

  • 每帧同步校验两个状态:是否检测到人脸、是否存在有效运动
  • 仅当「人脸存在 + 无运动」两个条件同时满足时累计时长,任一条件不满足直接重置计时
  • 新增打印标记位,避免满足条件后重复输出提示

代码修改步骤

1. 新增全局状态变量

在while循环外原有代码下方添加三个状态变量:

# 原有起始时间变量
t1 = time.time()
# 新增静止计时相关变量
last_still_start = None
motion_detected = False
has_printed = False

2. 统一判断人脸是否存在

在四个ROI的人脸检测代码执行完成后,添加人脸存在判断:

# 原有人脸检测、画框逻辑不变,之后新增
face_exist = any([len(faces_rect1), len(faces_rect2), len(faces_rect3), len(faces_rect4)])

3. 运动检测新增状态标记

在运动检测的轮廓遍历逻辑中,检测到有效运动时标记状态:

# 每次检测运动前先重置标记
motion_detected = False
for contour in contours:
    (x, y, w, h) = cv.boundingRect(contour)
    if cv.contourArea(contour) < 1000:
        continue
    # 新增状态标记
    motion_detected = True
    # 原有绘图、文字输出逻辑不变
    cv.rectangle(frame1, (x, y), (x+w, y+h), (0,255,0), thickness=2)
    cv.putText(frame1, 'Status: {}'.format('Movement'), (10,20), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), thickness=3)

4. 新增静止时长校验逻辑

在运动检测代码结束后、按键退出判断前添加计时校验:

current_ts = time.time()
if face_exist and not motion_detected:
    # 第一次进入静止状态,初始化计时起点
    if last_still_start is None:
        last_still_start = current_ts
        has_printed = False
    else:
        # 静止时长满5秒且未打印过,输出提示
        if current_ts - last_still_start >= 5 and not has_printed:
            print("检测到人脸静止满5秒")
            has_printed = True
else:
    # 状态不满足,重置所有标记
    last_still_start = None
    has_printed = False

修改后完整代码

import cv2 as cv
import time

# 打开摄像头
cap = cv.VideoCapture(0)

# 人脸检测用haar级联分类器
haar_cascade = cv.CascadeClassifier('haar_face.xml')

# 校验摄像头是否正常打开
if not cap.isOpened():
    raise IOError("Cannot open webcam")

# 起始时间
t1 = time.time()
# 新增静止计时相关变量
last_still_start = None
motion_detected = False
has_printed = False

# 摄像头开启时执行以下逻辑
while True:
    ret, frame = cap.read()
    ret, frame1 = cap.read()
    ret, frame2 = cap.read()
    
    frame = cv.resize(frame, None, fx=1, fy=1, interpolation=cv.INTER_AREA)

    # 划分帧为感兴趣区域(ROI)
    ROI1 = frame[0:180, 0:320]
    ROI2 = frame[0:180, 320:640]
    ROI3 = frame[180:360, 0:320]
    ROI4 = frame[180:360, 320:640]

    # 检测每个ROI中的人脸
    faces_rect1 = haar_cascade.detectMultiScale(ROI1, scaleFactor=1.1, minNeighbors=5)
    faces_rect2 = haar_cascade.detectMultiScale(ROI2, scaleFactor=1.1, minNeighbors=5)
    faces_rect3 = haar_cascade.detectMultiScale(ROI3, scaleFactor=1.1, minNeighbors=5)
    faces_rect4 = haar_cascade.detectMultiScale(ROI4, scaleFactor=1.1, minNeighbors=5)
    
    # 在检测到的人脸周围绘制矩形
    for (x, y, w, h) in faces_rect1:
        cv.rectangle(ROI1, (x, y), (x+w,y+h), (0,255,0), thickness=2)
        t2 = time.time()
        if (t2 - t1) > 1:
            print('I SEE YOU IN 1')
            t1 = time.time() # 重置起始时间
    
    for (x, y, w, h) in faces_rect2:
        cv.rectangle(ROI2, (x, y), (x+w,y+h), (0,255,0), thickness=2)
        t2 = time.time()
        if (t2 - t1) > 1:
            print('I SEE YOU IN 2')
            t1 = time.time() # 重置起始时间
        
    for (x, y, w, h) in faces_rect3:
        cv.rectangle(ROI3, (x, y), (x+w,y+h), (0,255,0), thickness=2)
        t2 = time.time()
        if (t2 - t1) > 1:
            print('I SEE YOU IN 3')
            t1 = time.time() # 重置起始时间
        
    for (x, y, w, h) in faces_rect4:
        cv.rectangle(ROI4, (x, y), (x+w,y+h), (0,255,0), thickness=2)
        t2 = time.time()
        if (t2 - t1) > 1:
            print('I SEE YOU IN 4')
            t1 = time.time() # 重置起始时间
        
    # 统一判断是否存在人脸
    face_exist = any([len(faces_rect1), len(faces_rect2), len(faces_rect3), len(faces_rect4)])

    # 展示所有视频流
    cv.imshow('ROI1', ROI1)
    cv.imshow('ROI2', ROI2)
    cv.imshow('ROI3', ROI3)
    cv.imshow('ROI4', ROI4)

    # 检测运动
    # 预处理帧以检测轮廓
    diff = cv.absdiff(frame1, frame2)
    gray = cv.cvtColor(diff, cv.COLOR_BGR2GRAY)
    blur = cv.GaussianBlur(gray, (5,5), 0)
    _, thresh = cv.threshold(blur, 20, 255, cv.THRESH_BINARY)
    dilated = cv.dilate(thresh, None, iterations=3)
    # 查找轮廓
    contours, _ = cv.findContours(dilated, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

    # 每次检测运动前重置标记
    motion_detected = False
    # 在检测到的轮廓周围绘制矩形
    for contour in contours:
        (x, y, w, h) = cv.boundingRect(contour)
        if cv.contourArea(contour) < 1000:
            continue
        motion_detected = True
        cv.rectangle(frame1, (x, y), (x+w, y+h), (0,255,0), thickness=2)
        cv.putText(frame1, 'Status: {}'.format('Movement'), (10,20), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), thickness=3)

    # 展示运动检测流
    cv.imshow('Motion Feed', frame1)

    # 静止时长校验逻辑
    current_ts = time.time()
    if face_exist and not motion_detected:
        if last_still_start is None:
            last_still_start = current_ts
            has_printed = False
        else:
            if current_ts - last_still_start >= 5 and not has_printed:
                print("检测到人脸静止满5秒")
                has_printed = True
    else:
        last_still_start = None
        has_printed = False
  
    # 按ESC键退出
    c = cv.waitKey(1)
    if c == 27:
        break

cap.release()
cv.destroyAllWindows()

内容的提问来源于stack exchange,提问作者Ryan Ponsell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 00:57:03