我有两张图片,一张只有背景,另一张有背景+可检测物体(在我的例子中是一辆车)。下面是图片
我正在尝试删除背景,以便在生成的图像中只有汽车。以下是我试图获得所需结果的代码
import numpy as np
import cv2
original_image = cv2.imread('IMG1.jpg', cv2.IMREAD_COLOR)
gray_original = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
background_image = cv2.imread('IMG2.jpg', cv2.IMREAD_COLOR)
gray_background = cv2.cvtColor(background_image, cv2.COLOR_BGR2GRAY)
foreground = np.absolute(gray_original - gray_background)
foreground[foreground > 0] = 255
cv2.imshow('Original Image', foreground)
cv2.waitKey(0)
通过减去两个图像得到的图像是
这就是问题所在。预期的结果图像应该只是一辆汽车。此外,如果你仔细观察这两张图片,你会发现它们并不完全相同,即相机移动了一点,所以背景被扰乱了一点。我的问题是,对于这两张图片,我该如何减去背景。我现在不想使用 grabCut 或 backgroundSubtractorMOG 算法,因为我现在不知道这些算法内部发生了什么。
另外,如果可能的话,请指导我做这件事的一般方法,而不仅仅是在这种特定情况下,也就是说,我在一张图片中有背景,在第二张图片中有背景+对象。这样做的最好方法是什么。很抱歉问了这么长的问题。
原文由 muazfaiz 发布,翻译遵循 CC BY-SA 4.0 许可协议
我使用 OpenCV 的 分水岭 算法解决了你的问题。您可以在 此处 找到分水岭的理论和示例。
首先,我选择了几个点(标记)来指示我要保留的对象在哪里,以及背景在哪里。此步骤是手动的,并且可能因图像而异。此外,它需要一些重复,直到你得到想要的结果。我建议使用工具来获取像素坐标。然后我创建了一个由零组成的空整数数组,其大小与汽车图像的大小相同。然后我将一些值(1:背景,[255,192,128,64]:car_parts)分配给标记位置的像素。
注意: 当我下载你的图片时,我不得不裁剪它以获得与汽车相匹配的图片。裁剪后,图像的大小为 400x601。这可能不是您拥有的图像的大小,因此标记将关闭。
之后我使用了分水岭算法。第一个输入是您的图像,第二个输入是标记图像(除了标记位置以外的所有地方都为零)。结果如下图所示。
我将所有值大于 1 的像素设置为 255(汽车),其余像素(背景)设置为零。然后我用 3x3 的内核对获得的图像进行了放大,以避免丢失有关汽车轮廓的信息。最后,我使用 cv2.bitwise_and() 函数将膨胀图像用作原始图像的遮罩,结果如下图所示:
这是我的代码:
如果你有很多图像,你可能需要创建一个工具来以图形方式注释标记,甚至需要一个算法来自动查找标记。