如何使用Python与OpenCV检测图像/视频帧中的鼠标光标位置
最优实现方案:模板匹配
录屏场景下鼠标指针样式固定,模板匹配是精度最高、速度最快、代码量最少的方案,完全不需要复杂的形状特征计算:
- 先从示例截图里单独截取一张仅包含鼠标指针的小图作为模板即可
- 逐帧对视频帧做模板匹配,直接定位指针坐标,如果需要获取指针尖的坐标,只要提前测量模板内指针尖相对左上角的偏移量,加上固定偏移值即可
import cv2 import numpy as np # 读取提前准备好的鼠标指针模板图 template = cv2.imread('cursor_template.png', cv2.IMREAD_COLOR) h, w = template.shape[:2] # 读取录屏文件,也可替换为实时录屏流输入 cap = cv2.VideoCapture('your_screen_recording.mp4') match_threshold = 0.8 # 匹配阈值,可根据实际识别效果微调 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 执行模板匹配 res = cv2.matchTemplate(frame, template, cv2.TM_CCOEFF_NORMED) loc = np.where(res >= match_threshold) for pt in zip(*loc[::-1]): # pt为鼠标指针左上角坐标,如需指针尖坐标,加上提前测量的固定偏移量即可 cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) print(f"鼠标指针坐标:{pt}") cv2.imshow('识别结果', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
备选方案:优化的颜色+形状检测
如果场景会切换鼠标样式,无法提前制作模板,可使用优化后的颜色+形状检测方案,解决之前测试失效的问题:
之前方案失效的核心原因:
- 白色HSV阈值范围设置错误,纯白色的HSV特征为饱和度低、明度高,不是H和S值均为0
- 没有增加面积、宽高比等基础筛选条件,单纯判断顶点数会误判大量无关区域
import cv2 import numpy as np cap = cv2.VideoCapture('your_screen_recording.mp4') while cap.isOpened(): ret, frame = cap.read() if not ret: break hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 正确的白色阈值范围 lower_white = np.array([0, 0, 220], dtype=np.uint8) upper_white = np.array([180, 30, 255], dtype=np.uint8) mask = cv2.inRange(hsv, lower_white, upper_white) # 形态学操作去除噪点 kernel = np.ones((2,2), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: # 先筛选面积,可根据录屏分辨率调整区间范围 area = cv2.contourArea(cnt) if area < 50 or area > 1500: continue # 筛选宽高比 x,y,w,h = cv2.boundingRect(cnt) aspect_ratio = float(w)/h if aspect_ratio < 0.5 or aspect_ratio > 2: continue # 形状拟合,带黑边的白色箭头拟合后顶点数一般在3~5之间 approx = cv2.approxPolyDP(cnt, 0.05*cv2.arcLength(cnt, True), True) if len(approx) >=3 and len(approx) <=5: # 指针尖通常为轮廓最小y值对应的点 tip_y = y tip_x = x + w//2 cv2.drawContours(frame, [cnt], -1, (0,255,0), 2) print(f"鼠标指针坐标:({tip_x}, {tip_y})") cv2.imshow('识别结果', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者BeginnersMindTruly
相关产品推荐
相关产品推荐

