我正在尝试去除图像的背景。我使用这里描述的方法运气不佳(从Canny边缘获取边界并去除图像的背景),但是当图像的背景是白色或浅色时,我已经能够成功地去除背景(“123456789.jpg”)。问题是当背景颜色为黑色或深色时,此方法无法删除图像的背景(“12345678.jpg”)。以下是我运行的代码:
123456789.jpg123456789success.jpg12345678.jpg12345678fail.jpg
import cv2
import numpy as np
image = cv2.imread("123456789.jpg")
original = image.copy()
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
break
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=4)
close = cv2.cvtColor(close, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original, original, mask=close)
result[close==0] = (0,0,0)
cv2.imshow('result', result)
cv2.waitKey()
因此,我想改进我的方法,使我可以去除图像的黑色背景,以获得感兴趣区域。
2条答案
按热度按时间sz81bmfz1#
在代码中,您使用大津(
cv2.THRESH_OTSU
)自动确定阈值,并执行更多的形态学操作。您还选择最大的轮廓作为遮罩,如果前景中有复杂的形状,并希望确保保留最大的部分,这可能是有益的。但在您的示例中并非如此。更新代码:
在这段代码中,我使用一个较低的阈值(在本例中为40)来创建一个二进制掩码,将暗背景与前景分开。然后,我在二进制掩码中找到轮廓,创建一个掩码来存储前景区域,并在此掩码上绘制轮廓。然后,我使用逐位AND操作从使用掩码的原始图像中提取前景。
这段代码为您的图像提供了所需的图像,并且也更简单。
请注意,您应该根据需要调整阈值(本例中为
40
),以获得特定图像的最佳效果。此方法适用于深色背景的图像。此外,如果你是open-cv的新手或者想大规模地这样做,你也可以看看一些可以进行智能裁剪的AI工具,比如Smart Image Crop API或Cloudinary's Imagga crop插件。
希望这对你有帮助。
xpszyzbs2#
在Python/OpenCV中处理图像的一种方法是在饱和度通道上转换为HSV和阈值等,因为您的背景似乎是灰度的,而中心对象是彩色的。
输入1(浅色背景):
结果一:
输入2(暗背景):
结果二: