OpenCV Python cv2.BackgroundSubtractor 参数

7 投票
1 回答
11364 浏览
提问于 2025-05-01 14:40

总结

看起来,调整BackgroundSubtractorMOG的参数并没有改变算法的结果。

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

这个算法的默认参数是:

history=200, nmixtures=5, backgroundRatio=0.7

所以,用不同的参数创建背景减除器应该会得到不同的结果。但是我无论使用默认参数还是自定义参数,得到的结果(前景掩码)总是一样。


重现问题

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

bg1 = cv2.BackgroundSubtractorMOG()
bg2 = cv2.BackgroundSubtractorMOG(history=3, nmixtures=5, backgroundRatio=0.0001)

然后,创建两个“VideoCapture”对象:

cap = cv2.VideoCapture('video.mp4')
cap2 = cv2.VideoCapture('different_video.mp4')

测试结果:

# 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)

运行这段代码一段时间后,窗口会显示第一个背景减除器的结果、第二个的结果以及它们之间的差异。

因为两个掩码是一样的,所以它们的差异(第三个窗口)就是一整张黑色的画面:

2 BackgroundSubtractorMOG and difference

然后,突然改变视频源(第二个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)

再运行这段代码一段时间后,你会看到:

2 BackgroundSubtractorMOG and difference with new video

两个前景掩码看起来是一样的,这就是为什么第三个窗口是整张黑色的画面。

但是在运行最后一段代码超过3帧后,第二个窗口的结果应该会变得更黑(因为在创建bg2对象时设置了history=3)。但两个背景减除器的结果依然是一样的(第三个窗口依然是整张黑色的画面)。


替代方案

我也尝试过用以下方式修改它们的参数:

bg2.setInt('history')

但是结果还是一样。

而且我总是能看到我设置的参数(例如):

>>>bg2.getInt('history')
3

我是不是漏掉了什么?

暂无标签

1 个回答

5

我发现,从某个版本的OpenCV开始,当我调用BackgroundSubtractorMOG对象的apply方法时,它默认使用的learningRate参数是0.0。这就导致背景减除器没有“学习”新的画面,而是一直停留在第一次使用的画面上。

为了避免这个问题,我需要在调用apply方法时,明确指定一个learningRate参数,这样它就能像以前那样正常工作了。

所以在启动代码后:

bg1 = cv2.BackgroundSubtractorMOG()
cap = cv2.VideoCapture('video.mp4')
frame = cap.read()[1]

...而不是这样做:

fg1 = bg1.apply(frame)

我应该这样做:

fg1 = bg1.apply(frame, learningRate=0.001)

撰写回答