Python 如何在已有背景图像的情况下获取前景遮罩

Python 如何在已有背景图像的情况下获取前景遮罩,python,opencv,background-subtraction,Python,Opencv,Background Subtraction,我知道,使用cv2.createBackgroundSubtractorMOG2()我们可以使用基于每500帧的背景估计方法(默认)减去前景遮罩。但是我已经有了一张背景图片,只想在每一帧中用这张图片减去前景,怎么样?我想说的是: import numpy as np import cv2 video = "xx.avi" cap = cv2.VideoCapture(video) bg = cv2.imread("bg.png") while True: ret, frame = c

我知道,使用
cv2.createBackgroundSubtractorMOG2()
我们可以使用基于每500帧的背景估计方法(默认)减去前景遮罩。但是我已经有了一张背景图片,只想在每一帧中用这张图片减去前景,怎么样?我想说的是:

import numpy as np
import cv2

video = "xx.avi"
cap = cv2.VideoCapture(video)
bg = cv2.imread("bg.png")

while True:
    ret, frame = cap.read()
    original_frame = frame.copy()
    if ret:
        # get foremask?
        fgmask = frame - bg

        # filter kernel for denoising:
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))

        opening = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)

        closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)

        # Dilate to merge adjacent blobs
        dilation = cv2.dilate(closing, kernel, iterations = 2)

        # show fg:dilation
        cv2.imshow('fg mask', dilation)
        cv2.imshow('original', original_frame)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            cap.release()
            cv2.destroyAllWindows()
            break
    else:
        break

然而,在执行
frame=frame-bg
时,我得到了色彩丰富的帧。如何获得正确的前景遮罩?

您得到的是彩色图像,因为您要减去2幅彩色图像,因此每个像素上得到的颜色是两幅图像之间每个通道(B、G和R)上的差异。 如dhanushka所述,为了执行背景减法,最简单的方法是使用MOG2并将其转发到背景图像中约(500)帧,以便它将其作为背景进行学习。MOG2的设计目的是通过高斯模型学习每个像素颜色的可变性,因此,如果您始终输入相同的图像,它将不会学习这一点。不管怎样,我认为它应该对你打算做的事情起作用。 这种方法的好处在于,MOG2将处理更多的事情,如随时间更新模型、处理阴影等

另一个选择是实现您自己的背景减法,就像您尝试做的那样。 所以,如果你想测试它,你需要把你的fgmask彩色图像转换成一些你可以很容易地设置阈值的东西,并决定每个像素是背景还是前景。一个简单的选项是将其转换为灰度,然后应用一个简单的阈值,阈值越低,减法方法越“敏感”(使用阈值),即:


只是个主意。让MOG学习你的
bg
,把它输入BackgroundSubtractorMOG2.apply,然后使用相同的函数来获得蒙版怎么样?你能试着转换成灰度吗(只是一个建议,因为我没有看过视频)?还可以尝试使用
cv2.absdiff()
并更新输出?
...
# get foremask?
    fgmask = frame - bg

    gray_image = cv2.cvtColor(fgmask, cv2.COLOR_BGR2GRAY)
    thresh = 20
    im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]

    # filter kernel for denoising:
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))

    opening = cv2.morphologyEx(im_bw, cv2.MORPH_OPEN, kernel)
...