Python OpenCV背景减除

3
我需要做的事情非常简单:
  1. 加载一个5帧视频文件
  2. 检测背景
  3. 在每个帧上,逐一执行以下步骤:
    1. 减去背景(创建前景掩码)
    2. 对前景掩码进行一些计算
    3. 保存原始帧和前景掩码
只需查看5个帧和5个相应的前景掩码:
import numpy as np
import cv2  
cap = cv2.VideoCapture('test.avi')
fgbg = cv2.BackgroundSubtractorMOG()

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    fgmask = fgbg.apply(frame)
    # Display the fgmask frame
    cv2.imshow('fgmask',fgmask)
    # Display original frame
    cv2.imshow('img', frame)

    k = cv2.waitKey(0) & 0xff
    if k == 5:
        break

cap.release()
cv2.destroyAllWindows()

每一帧都能正确打开和显示,但显示的fgmask与显示的原始帧不对应。在某个过程中,fgmasks的顺序被混淆了。
背景确实被正确地减去了,但我没有得到5个预期的fgmasks。
我错过了什么?我觉得这应该很简单:while循环运行视频的5帧,fgbg.apply将背景减法函数应用于每一帧。
我使用的OpenCV版本是opencv-2.4.9-3

仅使用5帧可能不足以为BackgroundSubtractorMOG、BackgroundSubtractorMOG2等构建良好的背景模型。 - berak
也许吧...但是既然减法“有效”了(我得到了背景减去后的移动物体白色),我认为在只使用5帧的情况下也可以使用它。 - Chargaff
3
由于您只有5帧,可以采用假定第一帧为背景或运行平均方法来实现背景减除。此外,如@berak所述,MOG通常需要几帧才能给出正确的结果。 - bikz05
1个回答

3

正如bikz05所建议的,对于我的5个图像集,运行平均方法效果非常好。感谢这个提示!

import cv2
import numpy as np

c = cv2.VideoCapture('test.avi')
_,f = c.read()

avg1 = np.float32(f)
avg2 = np.float32(f)

# loop over images and estimate background 
for x in range(0,4):
    _,f = c.read()

    cv2.accumulateWeighted(f,avg1,1)
    cv2.accumulateWeighted(f,avg2,0.01)

    res1 = cv2.convertScaleAbs(avg1)
    res2 = cv2.convertScaleAbs(avg2)

    cv2.imshow('img',f)
    cv2.imshow('avg1',res1)
    cv2.imshow('avg2',res2)
    k = cv2.waitKey(0) & 0xff
    if k == 5:
        break

你的“avg2”是多少呢?目前上面的代码说“avg2 = np.float32(”。 - James Owers
@kungfujam 我认为它与 avg1 相同。看起来他只是在测试具有不同权重的平均值的结果。 - Hugo
是的,avg2只是使用不同权重的结果。我已经更正了打字错误。 - Chargaff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接