Search code examples
imageimage-processingwolfram-mathematicamasking

Remove White Background from an Image and Make It Transparent


We're trying to do the following in Mathematica - RMagick remove white background from image and make it transparent.

But with actual photos it ends up looking lousy (like having a halo around the image).

Here's what we've tried so far:

unground0[img_] := With[{mask = ChanVeseBinarize[img, TargetColor->{1.,1.,1.}]},
  Rasterize[SetAlphaChannel[img, ImageApply[1-#&, mask]], Background->None]]]

Here's an example of what that does.

Original image:

original image

Image with the white background replaced with no background (or, for demonstration purposes here, a pink background):

image with transparent background -- actually a pink background here, to make the halo problem obvious

Any ideas for getting rid of that halo? Tweaking things like LevelPenalty, I can only get the halo to go away at the expense of losing some of the image.

EDIT: So I can compare solutions for the bounty, please structure your solution like above, namely a self-contained function named unground-something that takes an image and returns an image with transparent background.


Solution

  • Perhaps, depending on the edge quality you need:

    img = Import@"https://i.sstatic.net/k7E1F.png";
    mask = ChanVeseBinarize[img, TargetColor -> {1., 1., 1.}, "LengthPenalty" -> 10]
    mask1 = Blur[Erosion[ColorNegate[mask], 2], 5]
    Rasterize[SetAlphaChannel[img, mask1], Background -> None]
    

    enter image description here

    Edit

    Stealing a bit from @Szabolcs

    img2 = Import@"https://i.sstatic.net/k7E1F.png";
    (*key point:scale up image to smooth the edges*)
    img = ImageResize[img2, 4 ImageDimensions[img2]];
    mask = ChanVeseBinarize[img, TargetColor -> {1., 1., 1.}, "LengthPenalty" -> 10];
    mask1 = Blur[Erosion[ColorNegate[mask], 8], 10];
    f[col_] := Rasterize[SetAlphaChannel[img, mask1], Background -> col, 
                         ImageSize -> ImageDimensions@img2]
    GraphicsGrid[{{f@Red, f@Blue, f@Green}}]
    

    enter image description here

    Click to enlarge

    Edit 2

    Just to get an idea of the extent of the halo and background imperfections in the image:

    img = Import@"https://i.sstatic.net/k7E1F.png";
    Join[{img}, MapThread[Binarize, {ColorSeparate[img, "HSB"], {.01, .01, .99}}]]
    

    enter image description here

    ColorNegate@ImageAdd[EntropyFilter[img, 1] // ImageAdjust, ColorNegate@img]
    

    enter image description here