实时视频人眼检测项目首次检测到人眼后自动设置ROI问题咨询
人眼检测ROI锁定实现方案
方案一:自动锁定首次检测到的眼睛ROI
实现逻辑
- 新增两个状态变量:
roi_locked(布尔值,初始为False,标识是否已锁定ROI)、eye_roi_coord(存储ROI在原图的左上角、宽高坐标,初始为None) - 未锁定ROI时,保留原有的「人脸检测→人眼检测」逻辑
- 首次成功检测到有效眼睛时,将所有眼睛的外接区域合并为一个大ROI,记录坐标并锁定ROI
- 锁定后跳过人脸检测步骤,直接裁剪对应ROI区域执行人眼检测
- 可新增容错:连续10帧在ROI内未检测到眼睛时自动解锁,重新走全图检测流程,适配人员小范围移动的场景
方案二:手动选择指定ROI
实现逻辑
- 程序启动后先读取第一帧画面,调用OpenCV原生的
cv2.selectROI接口,用户直接用鼠标框选需要检测的眼睛区域即可 - 后续所有帧都只在框选的固定区域内执行人眼检测,完全跳过人脸检测步骤,适配固定机位、人员位置相对固定的场景
示例代码
import cv2 import time # 配置开关:True为自动锁定ROI,False为手动选择ROI AUTO_ROI = True # 状态变量 roi_locked = False eye_roi = None # 存储格式:(x, y, w, h) miss_count = 0 MISS_THRESHOLD = 10 # 连续10帧检测不到就自动重置ROI def nothing(x): pass # 此处保留你原有的detect_faces、detect_eyes、cut_eyebrows、blob_process函数 # 以下是修改后的main函数 def main(): global roi_locked, eye_roi, miss_count cap = cv2.VideoCapture(0) time.sleep(1.000) cv2.namedWindow('image') cv2.createTrackbar('threshold', 'image', 0, 255, nothing) # 手动选择ROI逻辑 if not AUTO_ROI: _, frame = cap.read() # 调用selectROI接口,用户框选后按空格/回车确认 eye_roi = cv2.selectROI('image', frame, showCrosshair=True, fromCenter=False) cv2.destroyWindow('image') cv2.namedWindow('image') roi_locked = True while True: _, frame = cap.read() threshold = cv2.getTrackbarPos('threshold', 'image') if not roi_locked: # 未锁定ROI时走原有人脸检测逻辑 face_frame = detect_faces(frame, face_cascade) if face_frame is not None: eyes = detect_eyes(face_frame, eye_cascade) valid_eyes = [e for e in eyes if e is not None] if len(valid_eyes) >= 1: # 首次检测到有效眼睛,锁定ROI x_min = min([e[0] for e in valid_eyes]) y_min = min([e[1] for e in valid_eyes]) x_max = max([e[0] + e[2] for e in valid_eyes]) y_max = max([e[1] + e[3] for e in valid_eyes]) # 给ROI加20像素边距,避免边缘丢失目标 pad = 20 eye_roi = ( max(0, x_min - pad), max(0, y_min - pad), x_max - x_min + 2*pad, y_max - y_min + 2*pad ) roi_locked = True # 处理当前帧的眼睛 for eye in valid_eyes: eye = cut_eyebrows(eye) keypoints = blob_process(eye, threshold, detector) eye = cv2.drawKeypoints(eye, keypoints, eye, (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) else: # 已锁定ROI,直接裁剪区域检测 x, y, w, h = eye_roi roi_area = frame[y:y+h, x:x+w] # 直接在ROI区域做人眼检测,不需要先检测人脸 eyes = detect_eyes(roi_area, eye_cascade) valid_eyes = [e for e in eyes if e is not None] if len(valid_eyes) == 0: miss_count += 1 # 连续丢失超过阈值,自动解锁ROI if miss_count >= MISS_THRESHOLD and AUTO_ROI: roi_locked = False miss_count = 0 eye_roi = None else: miss_count = 0 for eye in valid_eyes: eye = cut_eyebrows(eye) keypoints = blob_process(eye, threshold, detector) # 坐标映射回原图绘制 eye_x = x + eye[0] eye_y = y + eye[1] cv2.drawKeypoints(frame[eye_y:eye_y+eye[3], eye_x:eye_x+eye[2]], keypoints, frame[eye_y:eye_y+eye[3], eye_x:eye_x+eye[2]], (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 可选:在原图绘制ROI边界,方便调试 cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) cv2.imshow('image', frame) # 按r键手动重置ROI key = cv2.waitKey(1) & 0xFF if key == ord('q'): break elif key == ord('r'): roi_locked = False miss_count = 0 eye_roi = None cap.release() cv2.destroyAllWindows()
注意事项
- 自动ROI方案适合人员位置相对固定、不会大幅移动的场景,如果人员会大范围移动,可以搭配轻量的目标跟踪算法(比如CSRT、KCF)实时更新ROI坐标,稳定性会更高
- 手动ROI方案适合固定机位的工业场景,不需要依赖人脸检测,运行效率更高
内容的提问来源于stack exchange,提问作者SmashAI
相关产品推荐
相关产品推荐

