OpenCV+Python视频ROI运动追踪报absdiff尺寸不匹配错误
问题根因
你遇到的尺寸不匹配错误根源是帧更新逻辑存在漏洞:
- 你仅在进入检测循环前,对初始获取的两帧做了ROI区域裁剪
- 循环运行时,末尾执行
frame1 = frame2后,通过cap.read()新读取的frame2是摄像头输出的完整全尺寸帧,没有做对应ROI裁剪 - 下一轮循环调用
cv2.absdiff()时,传入的一个是裁剪后的小尺寸ROI帧,一个是全尺寸原始帧,两者尺寸、通道数不匹配,直接触发OpenCV的运算报错。
额外隐藏风险:现有代码没有判断cap.read()的读帧返回状态,如果摄像头临时断连、读帧失败返回None,后续的裁剪、运算操作也会直接抛出异常。
修复方法
每次读取新的摄像头帧后,都按照选定的ROI坐标做相同规则的裁剪,同时增加读帧有效性判断即可。
修复后的可运行代码如下:
import cv2 cap = cv2.VideoCapture(0) # 读取初始两帧 ret, frame1 = cap.read() if not ret: raise RuntimeError("无法读取摄像头帧,请检查设备连接") ret, frame2 = cap.read() if not ret: raise RuntimeError("无法读取摄像头帧,请检查设备连接") # 选定ROI区域 r = cv2.selectROI(frame1) x, y, w, h = int(r[0]), int(r[1]), int(r[2]), int(r[3]) # 对初始两帧做ROI裁剪 frame1 = frame1[y:y+h, x:x+w] frame2 = frame2[y:y+h, x:x+w] while cap.isOpened(): # 帧差运算 diff = cv2.absdiff(frame1, frame2) gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) _, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY) dilated = cv2.dilate(thresh, None, iterations=3) contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: (cx, cy, cw, ch) = cv2.boundingRect(contour) if cv2.contourArea(contour) < 1000: continue cv2.rectangle(frame1, (cx, cy), (cx+cw, cy+ch), (0, 255, 0), 2) cv2.putText(frame1, "Status: {}".format("Motion detected!"), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3, cv2.LINE_AA) print('Motion Detection. Object area - ', cv2.contourArea(contour)) cv2.imshow("ROI Motion Detection", frame1) # 更新帧:新读的帧必须做相同ROI裁剪 frame1 = frame2 ret, frame2 = cap.read() # 增加读帧判断 if not ret: break frame2 = frame2[y:y+h, x:x+w] if cv2.waitKey(1) == 27: break cap.release() cv2.destroyAllWindows()
额外说明
- 原代码里导入了
imutils但全程没有使用,修复时直接移除了冗余导入 - 原代码里的轮廓变量
сontours首字符是西里尔字母с,不是标准英文字母c,部分编码环境下可能触发变量名识别错误,修复时统一换成了标准英文字母命名的变量 - 原代码里绘制矩形、文字的坐标都是基于ROI裁剪后的局部坐标系,不需要额外做坐标转换,完全可以正常在ROI窗口里标注运动目标。
内容的提问来源于stack exchange,提问作者Mikhail
相关产品推荐
相关产品推荐

