如何在Python中去除图像的白色模糊

3

我正在尝试将产品图像的背景去除,将它们保存为透明的PNG格式,并且遇到了一个问题:无法弄清楚为什么在产品周围会出现白色线条,就像一种模糊效果(请参见第二张图片),不知道这种效果的真正名称。同时,我也失去了白色的Nike标志 :(

input output

from PIL import Image

img = Image.open('test.jpg')
img = img.convert("RGBA")
datas = img.getdata()


newData = []


for item in datas:
    if item[0] > 247 and item[1] > 247 and item[2] > 247:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)

img.putdata(newData)
img.save("test.png", "PNG")

你有什么想法可以解决这个问题,使得我的选择和边缘更加清晰?

1个回答

7

复制一份你的图像并使用PIL / Pillow的ImageDraw.floodfill()函数,从左上角开始使用合理的容差进行填充 - 这样你只会填充到衬衫的边缘并避免涉及Nike标志。

然后将背景轮廓变为白色,其他全部变成黑色,并尝试应用一些形态学(可能来自scikit-image)来扩张白色区域以隐藏锯齿。

最后,使用putalpha()将新生成的图层放入图像中。


时间真的很紧,但这就是大致的方法。请注意,需要在开始时复制原始图像,并在最后使用putalpha()将新的Alpha层叠加回去 ...

from PIL import Image, ImageDraw
import numpy as np
import skimage.morphology

# Open the shirt
im = Image.open('shirt.jpg')

# Make all background pixels (not including Nike logo) into magenta (255,0,255)
ImageDraw.floodfill(im,xy=(0,0),value=(255,0,255),thresh=10)

# DEBUG
im.show()

在这里尝试更改阈值 (thresh)。如果将其设置为50,则效果更干净,可能已足够停止。

enter image description here

# Make into Numpy array
n = np.array(im)

# Mask of magenta background pixels
bgMask =(n[:, :, 0:3] == [255,0,255]).all(2)

# DEBUG
Image.fromarray((bgMask*255).astype(np.uint8)).show()

enter image description here

# Make a disk-shaped structuring element
strel = skimage.morphology.disk(13)

# Perform a morphological closing with structuring element
closed = skimage.morphology.binary_closing(bgMask,selem=strel)

# DEBUG
Image.fromarray((closed*255).astype(np.uint8)).show()

图片描述在此处输入

如果您对形态学不熟悉,可以阅读Anthony Thyssen的一些很好的笔记 这里

顺便说一下,您还可以使用potrace来稍微平滑轮廓线。


今天我有更多时间,因此提供了一个更完整的版本。您可以根据您的图像来实验形态学盘大小和洪水填充阈值,直到找到适合您需求的东西:

#!/bin/env python3

from PIL import Image, ImageDraw
import numpy as np
import skimage.morphology

# Open the shirt and make a clean copy before we dink with it too much
im = Image.open('shirt.jpg')
orig = im.copy()

# Make all background pixels (not including Nike logo) into magenta (255,0,255)
ImageDraw.floodfill(im,xy=(0,0),value=(255,0,255),thresh=50)

# DEBUG
im.show()

# Make into Numpy array
n = np.array(im)

# Mask of magenta background pixels
bgMask =(n[:, :, 0:3] == [255,0,255]).all(2)

# DEBUG
Image.fromarray((bgMask*255).astype(np.uint8)).show()

# Make a disk-shaped structuring element
strel = skimage.morphology.disk(13)

# Perform a morphological closing with structuring element to remove blobs
newalpha = skimage.morphology.binary_closing(bgMask,selem=strel)

# Perform a morphological dilation to expand mask right to edges of shirt
newalpha = skimage.morphology.binary_dilation(newalpha, selem=strel)

# Make a PIL representation of newalpha, converting from True/False to 0/255
newalphaPIL = (newalpha*255).astype(np.uint8)
newalphaPIL = Image.fromarray(255-newalphaPIL, mode='L')

# DEBUG
newalphaPIL.show()

# Put new, cleaned up image into alpha layer of original image
orig.putalpha(newalphaPIL)
orig.save('result.png')

在此输入图像描述


关于使用 potrace 平滑轮廓线,你需要将 new alphaPIL 保存为 PGM 格式的图像,因为这是 potrace 所需的输入格式。因此代码如下:

newalphaPIL.save('newalpha.pgm')

现在你可以玩耍,哎呀,我是说“谨慎实验”使用potrace平滑α轮廓。基本命令如下:
potrace -b pgm newalpha.pgm -o smoothalpha.pgm

接着,您可以重新加载图像smoothalpha.pgm 到Python中,并在 putalpha()调用的最后一行使用它。以下是原始未平滑化阿尔法和平滑化后的差异动画:

enter image description here

仔细观察边缘以查看差异。您可能希望在平滑之前将Alpha大小调整为两倍或一半,以查看其效果。


1
我已经添加了一些代码让你开始。请注意,丑陋的结果来自使用JPEG存储图像。 - Mark Setchell
1
@VasuDeo.S 对不起!我总是尽力包含我的**导入(import)**,但有时会错过一些,因为我在IPython中交互测试我的代码,而且在最终确定答案时有时会漏掉一些步骤。我已经添加了import skimage.morphology - Mark Setchell
1
我已经在我的答案中添加了更多的注释和参考资料,以帮助你理解,因为这对你来说都是新的。 - Mark Setchell
1
我有更多时间,所以在我的答案结尾添加了一些内容 - 请再看一下。 - Mark Setchell
1
我添加了一些关于potrace的内容,不确定是否值得这样做。如果您喜欢,还有一个Python版本... https://pypi.org/project/pypotrace/ - Mark Setchell
显示剩余8条评论

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