Python OpenCV纯白背景

5
我有一个DIY家庭照片工作室,想要拍摄的照片背景是纯白色(#FFFFFF),并且尽量减少用户交互。
这是我原始的图片(没有进行任何处理,只是从相机中获取的原始JPG格式图片): original image 我使用opencv和Tkinter UI实现了一个简单的python程序。
1) 获取包含对象的矩形区域(ROI)
我决定通过UI选择ROI,也许以后我会编写代码来自动识别照片上的对象。 select ROI 2) 使用cv2.grabCut函数尝试从这个矩形中裁剪背景 grab cut with rect
cv2.grabCut(image, self.mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_RECT)

3) 如果需要,我会创建自定义蒙版用于 GrabCut,以提供更准确的对象提取。

带有蒙版的 GrabCut

cv2.grabCut(image, self.mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_MASK)

4)在这一步之后,我可以创建包含我的对象的遮罩。我还将遮罩大小调整了30像素。

mask = cv2.resize(mask, ( crop_img.shape[1] + 30,  crop_img.shape[0] + 30))
mask = mask[30 : crop_img.shape[0], 30 : crop_img.shape[1]]

所以这个掩码具有更大的宽度和高度。

目标掩码

5) 我将使用这个掩码来进行seamlessClone方法

src_bg = 255 * np.ones(self.src.shape, self.src.dtype)

width, height, channels = src_bg.shape
center = (int(height / 2), int((width / 2)))
output = cv2.seamlessClone(crop_img, src_bg, mask, center, cv2.MIXED_CLONE)

并获得这样的结果: output 看起来不错,除了对象右侧的一些伪影。这似乎是我的掩码不够好。这不是真正的问题。真正的问题是:无缝克隆给我的背景并不是真正的白色。看一下级别: levels 一些奇怪的渐变和底部右侧的背景不是真正的白色。我尝试了很多图片,通常会出现这种情况。
我的问题是:有什么正确的方法可以做到我想要的吗?我的方法可用于此任务吗?如何使真正的白色(#FFFFFF)背景没有这样的渐变。谢谢

1
拍照时可以多使用一些灯光。 - furas
2个回答

2

不确定你是否愿意考虑另一个工具,但如果你使用Linux,ImageMagick可能已经安装了,可以轻松地完成这项任务,无需编写任何代码。它也适用于OS X和Windows。

因此,如果我们从这张图片开始:

enter image description here

假设红线的坐标对应于一个550像素宽、480像素高且偏移量为250,200的图像。然后,在终端中只需运行以下命令:

convert photo.jpg -crop 550x480+250+200 \
   -fuzz 25% -fill white -draw 'color 0,0 floodfill' -trim result.jpg

给你这个命令行:

enter image description here

这个命令的含义是..."打开 photo.jpg 并裁剪掉红色部分。允许从左上角像素开始颜色有 25% 的变化,并用纯白色填充图像,然后对其进行修整。保存为 result.jpg"

您可以将fuzz百分比设置得更高以获得更硬的边缘。


ImageMagick添加了奇怪的边缘。 - striker

1
如果您在分割掩模之前增加对比度,您可能可以在不使用额外灯光或手动初始化的情况下消除阴影。
对于这样一个干净的背景,您可以尝试另一种分割方法,例如Watershed。它也使用标记,但速度稍快。
你可以通过 距离变换 + 阈值 获取内部标记,通过阈值 + 膨胀 获取外部标记,如果需要,可以使用 Hough 变换活动轮廓 从边缘获取线条。
我认为你的 seamlessClone 导致了渐变。 "无缝" 部分是由于混合而产生的。只需将黑色遮罩乘以图像以去除背景,然后将结果添加到白色图像中即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接