从补充图像中分离背景

Background isolation from complementing images

我正在尝试从多个图像中分离背景,这些图像彼此之间存在差异,即与背景重叠。 我的图片在这里单独列出:https://imgur.com/a/Htno7lm 但是这里有所有 6 个组合的预览:

我想在一系列图像中执行此操作,因为我正在阅读一些视频提要,并且通过获取最后几帧来处理它们以隔离背景,如下所示:

import os
import cv2

first = True
bwand = None
for filename in os.listdir('images'):
    curImage = cv2.imread('images/%s' % filename)
    if(first):
        first = False
        bwand = curImage
        continue
    bwand = cv2.bitwise_and(bwand,curImage)
cv2.imwrite("and.png",bwand)

从这段代码中,我总是通过按位运算递增我的缓冲区,但我得到的结果并不是我想要的: 按位与:

并发添加到缓冲区的方式在视频过滤和性能方面对我来说是最好的方法,但如果我把它当作一个列表,我可以像这样寻找中值:

import os
import cv2
import numpy as np

sequence = []
for filename in os.listdir('images'):
    curImage = cv2.imread('images/%s' % filename)
    sequence.append(curImage)
imgs = np.asarray(sequence)
median = np.median(imgs, axis=0)
cv2.imwrite("res.png",median)

结果是我:

这仍然不完美,因为我正在寻找中值,如果我寻找模式值,性能会显着下降。

是否有一种方法可以像第一个替代方法一样作为缓冲区来获得结果,但会以良好的性能输出给我最好的结果?

--编辑 正如@Christoph Rackwitz 所建议的,我使用了 OpenCV 背景减法器,它作为请求的功能之一工作,它是一个缓冲区,但结果并不是最令人愉快的:

代码:

import os
import cv2

mog = cv2.createBackgroundSubtractorMOG2()
for filename in os.listdir('images'):
    curImage = cv2.imread('images/%s' % filename)
    mog.apply(curImage)
x = mog.getBackgroundImage()
cv2.imwrite("res.png",x)

因为 scipy.stats.mode 需要很长时间才能完成它的工作,所以我手动做了同样的事情:

  • 计算直方图(针对每个图像的每一行的每个像素的每个通道)
  • argmax 获取模式
  • 重塑和铸造

仍然不是视频速度,但是很好。 numba 可能会加快速度。

filenames = ...
assert len(filenames) < 256, "need larger dtype for histogram"
stack = np.array([cv.imread(fname) for fname in filenames])
sheet = stack[0]

hist = np.zeros((sheet.size, 256), dtype=np.uint8)
index = np.arange(sheet.size)

for sheet in stack:
    hist[index, sheet.flat] += 1

result = np.argmax(hist, axis=1).astype(np.uint8).reshape(sheet.shape)
del hist # because it's huge

cv.imshow("result", result); cv.waitKey()

如果我不使用直方图和大量内存,而是使用固定数量的工作表和缓存友好的数据访问,它可能会更快。