简体   繁体   中英

How to remove white fuzziness from image in python

I'm trying to remove the background from product images, save them as transparent png's and got to a point where I can't figure out how and why I get the white line around the products like a fuzziness(see second image) don't know the real word for the effect. Also I'm losing the Nike swoosh which is white too :(

输入 产量

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")

Any ideas how I can fix this so I get clean selections, edges ?

Take a copy of your image and use PIL/Pillow's ImageDraw.floodfill() to flood fill from the top-left corner using a reasonable tolerance - that way you will only fill to the edges of the shirt and avoid the Nike logo.

Then take the background outline and make it white and everything else black and try applying some morphology (from scikit-image maybe) to dilate the white a little larger to hide the jaggies.

Finally, put the resulting new layer into the image with putalpha() .


I am really pushed for time, but here are the bones of it. Just missing the copy of the original image at the start and the putalpha() of the new alpha layer back at the end...

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()

在此输入图像描述

Experiment with the threshold ( thresh ) here. If you make it 50, it works much more cleanly and may be good enough to stop.

# 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
closed = skimage.morphology.binary_closing(bgMask,selem=strel)

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

在此输入图像描述

If you are unfamiliar with morphology, Anthony Thyssen has some excellent noes worth reading here .

By the way, you could also use potrace to smooth the outline somewhat.


I had a bit more time today so here is a more complete version. You can experiment with the morphology disk sizes and floodfill thresholds according to your images till you find something tailored for your needs:

#!/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')

在此输入图像描述


As regards using potrace to smooth the outline, you would save new alphaPIL as a PGM format image because that is what potrace likes as input. So that would be:

newalphaPIL.save('newalpha.pgm')

Now you can play around, oops I meant "experiment carefully" with potrace to smooth the alpha outline. The basic command is:

potrace -b pgm newalpha.pgm -o smoothalpha.pgm

You can then re-load the image smoothalpha.pgm back into your Python and use it on the last line in the putalpha() call. Here is an animation of the difference between the original unsmoothed alpha and the smoothed one:

在此输入图像描述

Look carefully at the edges to see the difference. You may want to experiment with resizing the alpha either to twice the size or half the size before smoothing to see what effect that has.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM