使用BackgroundSubtractorMOG2背景减法后,如何获取目标原始颜色?
获取BackgroundSubtractorMOG2掩码对应的原始目标颜色
要从MOG2输出的二值掩码里拿到运动目标的原始颜色,其实很简单——核心就是用掩码和原始帧做按位与操作,让掩码中白色(代表前景目标)的区域保留原始帧的像素,黑色区域则置黑,这样就能精准提取出带原始色彩的目标了。
关键步骤说明
- 首先确保你的掩码是单通道二值图(MOG2输出的
fgmask本身就是单通道灰度图,满足要求) - 由于原始帧是三通道的BGR图像,需要先把单通道掩码转换成三通道格式,保证和原始帧通道数一致
- 用
cv2.bitwise_and将原始帧和转换后的掩码做运算,得到仅保留前景目标原始颜色的图像
修改后的完整代码(结合你的原有逻辑)
我已经把提取彩色目标的逻辑整合到你的代码里,还修正了原代码里的小笔误,调整了噪声过滤的阈值:
import cv2 import numpy as np cap = cv2.VideoCapture("people.mkv") kernel_dil = np.ones((10,10), np.uint8) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)) fgbg = cv2.createBackgroundSubtractorMOG2(history=0, varThreshold=444, detectShadows=False) while True: ret, frame1 = cap.read() if not ret: # 新增帧读取检查,避免视频结束后报错 break frame = cv2.resize(frame1,(1364,700),fx=0,fy=0, interpolation = cv2.INTER_CUBIC) # 构建ROI掩码(保留你的原有逻辑) mask = np.zeros(frame.shape, dtype=np.uint8) mask.fill(255) roi_corners = np.array([[(11,652), (1353,652), (940,84), (424,84)]], dtype=np.int32) cv2.fillPoly(mask, roi_corners, 0) masking = cv2.bitwise_or(frame, mask) # 生成前景掩码(保留你的原有逻辑) fgmask = fgbg.apply(masking,mask) fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel) # 修正原代码的笔误:fgmask2改为fgmask dilation = cv2.dilate(fgmask, kernel_dil, iterations = 1) # --------------------- 核心:提取原始颜色的前景目标 --------------------- # 将单通道掩码转换为三通道,和原始帧通道数匹配 fgmask_3ch = cv2.cvtColor(fgmask, cv2.COLOR_GRAY2BGR) # 按位与操作,仅保留掩码白色区域的原始像素 colored_foreground = cv2.bitwise_and(frame, fgmask_3ch) # 可选:如果想基于膨胀后的掩码提取更大范围的目标,用下面两行替换上面的 # dilation_3ch = cv2.cvtColor(dilation, cv2.COLOR_GRAY2BGR) # colored_foreground = cv2.bitwise_and(frame, dilation_3ch) # ---------------------------------------------------------------------- # 轮廓检测与绘制(调整面积阈值,过滤小噪声) (contours,hierarchy) = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for pic, contour in enumerate(contours): area = cv2.contourArea(contour) x,y,w,h = cv2.boundingRect(contour) if area > 100: # 原0.001阈值太小,改为实际有效的数值,避免检测到噪声 cv2.rectangle(frame, (x,y), (x+w,y+h), (0,0,255), 2) cv2.putText(frame, 'People', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2, cv2.LINE_AA) # 新增显示彩色前景的窗口 cv2.imshow("Colored Foreground", colored_foreground) cv2.imshow("FullScreen", frame) cv2.imshow("FGMask1", fgmask) cv2.imshow("FGMask2", dilation) key = cv2.waitKey(12) if key == ord("q"): break # 释放资源(原代码遗漏,新增) cap.release() cv2.destroyAllWindows()
额外说明
- 转换三通道掩码的原因:
cv2.bitwise_and要求输入的两个图像必须通道数一致,原始帧是3通道BGR,所以需要把单通道灰度掩码转成3通道格式(每个通道的像素值和原灰度掩码一致)。 - 面积阈值调整:原代码里的
area>0.001几乎会把所有微小噪声都当成目标,实际使用时建议根据你的视频分辨率调整合适的阈值(比如100、200等)。
内容的提问来源于stack exchange,提问作者Syamim Amiruddin
相关产品推荐
相关产品推荐

