从补充图像中分离背景
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()
如果我不使用直方图和大量内存,而是使用固定数量的工作表和缓存友好的数据访问,它可能会更快。
我正在尝试从多个图像中分离背景,这些图像彼此之间存在差异,即与背景重叠。
我的图片在这里单独列出: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()
如果我不使用直方图和大量内存,而是使用固定数量的工作表和缓存友好的数据访问,它可能会更快。