OpenCV Python cv2.BackgroundSubtractor参数

Seb*_*rez 7 python parameters opencv background-subtraction

摘要

似乎更改BackgroundSubtractorMOG的参数不会影响算法的结果.

我使用的是Python:2.7.6 | Anaconda 2.1.0(64位)
OpenCV:'2.4.10'OS
:Windows 7 x64

算法的默认参数是:

history=200, nmixtures=5, backgroundRatio=0.7
Run Code Online (Sandbox Code Playgroud)

因此,创建具有不同参数的背景减法器应该给出不同的结果.但我总是使用默认参数和自定义参数获得相同的结果(前景蒙版).


再现问题

首先,使用不同的参数创建两个背景减法器对象:

bg1 = cv2.BackgroundSubtractorMOG()
bg2 = cv2.BackgroundSubtractorMOG(history=3, nmixtures=5, backgroundRatio=0.0001)
Run Code Online (Sandbox Code Playgroud)

创建2个"VideoCaptrue"对象:

cap = cv2.VideoCapture('video.mp4')
cap2 = cv2.VideoCapture('different_video.mp4')
Run Code Online (Sandbox Code Playgroud)

测试结果:

# Get a frame from the first capturing object:
frame = cap.read()[1]

# Get the foreground mask from both background subtractors:
fg1 = bg1.apply(frame)
fg2 = bg2.apply(frame)

# Show both results and the difference between them:
cv2.imshow('Window name', np.hstack((fg1, fg2, fg1 - fg2)))
cv2.waitKey(30)
Run Code Online (Sandbox Code Playgroud)

在为某些帧运行该代码块之后,该窗口显示来自第一个背景减法器的结果,来自第二个的结果以及两者的差异.

因为两个掩码是相同的,它们的差异(第三个窗格)的结果是一个完整的黑色框架:

2 BackgroundSubtractorMOG和差异

然后,突然改变视频源(第二个VideoCapture对象):

# Get a frame from the second capturing object:
frame = cap2.read()[1]

# Get the foreground mask from both background subtractors:
fg1 = bg1.apply(frame)
fg2 = bg2.apply(frame)

# Show both results and the difference between them:
cv2.imshow('Window name', np.hstack((fg1, fg2, fg1 - fg2)))
cv2.waitKey(30)
Run Code Online (Sandbox Code Playgroud)

在为某些帧运行该代码块之后,您将获得:

2 BackgroundSubtractorMOG与新视频的区别

两个前景蒙版看起来相同,这就是第三个窗格是全黑框架的原因.

但是在运行最后一段代码超过3帧后,第二个窗格的结果应该再次变黑(因为history=3在创建bg2对象时).但是两个背景减法器都会得到相同的结果(如第三个完整的黑色窗格所示).


备择方案

我也试过修改他们的参数:

bg2.setInt('history')
Run Code Online (Sandbox Code Playgroud)

但我得到了相同的结果.

而且我总是得到我做"设定"的参数(例如):

>>>bg2.getInt('history')
3
Run Code Online (Sandbox Code Playgroud)

有什么我想念的吗?

Seb*_*rez 5

我发现(因为某些版本的OpenCV)当我applyBackgroundSubtractorMOG对象调用方法时,它使用默认learningRate参数设置0.0,因此BackgroundSubtractor不是"学习"新帧,它只是坚持使用的第一帧.

为了避免这种情况,我必须apply使用显式的learningRate参数调用该方法,然后它就像以前一样工作.

所以在启动代码后:

bg1 = cv2.BackgroundSubtractorMOG()
cap = cv2.VideoCapture('video.mp4')
frame = cap.read()[1]
Run Code Online (Sandbox Code Playgroud)

......而不是做:

fg1 = bg1.apply(frame)
Run Code Online (Sandbox Code Playgroud)

我应该做:

fg1 = bg1.apply(frame, learningRate=0.001)
Run Code Online (Sandbox Code Playgroud)