我知道使用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
时,我得到了色彩鲜艳的帧。如何获得正确的前景遮罩?
答案 0 :(得分:1)
您得到的是彩色图像,因为您要减去2幅彩色图像,所以每个像素获得的颜色就是两个图像之间每个通道(B,G和R)的差异。 为了进行背景减法,如dhanushka所评论的那样,最简单的选择是使用MOG2并将其背景图像转发一些(500)帧,以便它将其作为背景学习。 MOG2旨在通过高斯模型来学习每种像素颜色的可变性,因此,如果您始终喂入相同的图像,它将不会学到。无论如何,我认为它应该可以满足您的意图。 这种方法的好处是,MOG2会处理很多其他事情,例如随着时间的推移更新模型,处理阴影等。
另一个选择是实现您尝试做的自己的背景扣除方法。 因此,如果要对其进行测试,则需要将fgmask彩色图像转换为可以轻松阈值并确定每个像素是背景还是前景的图像。一个简单的选择是将其转换为灰度,然后应用一个简单的阈值,阈值越低,减法就越“敏感”(使用阈值),即:
...
# 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)
...