3

I am trying to remove the white background of few images programmatically and make it transparent. The format of the image is simple, it has a white background and a single object mainly positioned in the middle.

I want to replicate the functionality of the https://remove.bg website which makes the background of the image transparent.

I have tried using sharp or imageMagick software to make the background transparent. But it makes some of the pixels inside the main object become transparent too. Which I definitely don't want.

Was using the below code in imageMagik to convert the white background to transparent

convert brownie.jpg -transparent white brownie.png

convert cakebig.jpg -fuzz 1% -transparent white cakebig.png

Didn't seem to work perfectly.

After running the commands, the images did become transparent but few of the pixels inside the main object got affected too.

Input Image Input

Output from ImageMagik (See how some of the pixels inside main object got transparent) Image magik

Expected Output from https://remove.bg (See no effect on the main object) Expected Output

It seems like an image processing problem and seems like OpenCV is the best solution for this. I don't know much about the library so it's a little tricky. Was checking out some code and came across grab cut and graph cut algorithm which can be used for image segmentation. But I am not totally sure about it. Please help in the proper solution to this in OpenCV.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Abhishek Rastogi
  • 189
  • 1
  • 10
  • see https://stackoverflow.com/questions/765736/using-pil-to-make-all-white-pixels-transparent – Reiner Czerwinski Sep 11 '19 at 09:36
  • @ReinerCzerwinski I don't want to make all the white pixels transparent. Just the ones which constitute the background. Not the white pixels which are there in the foreground – Abhishek Rastogi Sep 11 '19 at 09:47
  • 1
    Inverse threshold to mask the main blob in the center, fill possible holes (coming from white-ish pixels), use this mask as alpha channel, maybe some Gaussian blurring on the mask to smooth the contour. – HansHirse Sep 11 '19 at 10:00
  • 3
    As you have found, `-transparent` affects **all** pixels in the image, even inside the ice cream. Instead use a flood fill that starts at the top-left and stops when it meets pixels that are not white - so it only affects white pixels **connected by other white pixels to the top-left**... `convert dessert.png -fill none -fuzz 2% -draw 'alpha 0,0 floodfill' result.png` You may need to change `magick` to `convert` and/or `alpha` to `matte`. – Mark Setchell Sep 11 '19 at 10:46
  • Thanks so much @MarkSetchell That worked :) – Abhishek Rastogi Sep 13 '19 at 01:24

1 Answers1

5

I will add a little more to Mark Setchell's excellent ImageMagick answer about using a fuzzy flood fill by adding some antialiasing via blurring the alpha channel a little and then zeroing blurred values below mid-gray. This will smooth the jagged edges left from the fuzzy flood fill. Note too large a fuzz value will cause leakage into your ice cream, because the color of the ice cream is similar to that of the background. Too little fuzz value will not adequately remove the background. So the fuzz value tolerance in this image is tight.

Input:

enter image description here

For ImageMagick 6:

convert img.png -fuzz 2% -fill none -draw "matte 0,0 floodfill" -channel alpha -blur 0x2 -level 50x100% +channel result.png


For Imagemagick 7:

magick img.png -fuzz 2% -fill none -draw "alpha 0,0 floodfill" -channel alpha -blur 0x2 -level 50x100% +channel result.png


enter image description here

You will need to download the result to see that the background is transparent and the outline is smooth.

fmw42
  • 46,825
  • 10
  • 62
  • 80
  • Using ImageMagick 7.0.8-68 on macOS I get "convert: non-conforming drawing primitive definition `0' @ error/draw.c/RenderMVGContent/4406". Any ideas? – rynop Nov 06 '19 at 03:33
  • ImageMagick 7 uses magick, not convert. Simply change convert to magick and try the command again. If the fuzz value is too large, then it can make the whole image transparent. So be sure not to make it too large. Also change matte to alpha. `magick img.png -fuzz 2% -fill none -draw "alpha 0,0 floodfill" -channel alpha -blur 0x2 -level 50x100% +channel result.png` – fmw42 Nov 06 '19 at 04:02
  • Thanks for the quick response. Unfortunately same error. See full error and version output @ https://gist.github.com/rynop/f8fce887780e5ac1d05a4027922fc74d – rynop Nov 06 '19 at 04:04
  • 1
    Sorry, I was editing my command while you posted. See my last comments. Try this: `magick img.png -fuzz 2% -fill none -draw "alpha 0,0 floodfill" -channel alpha -blur 0x2 -level 50x100% +channel result.png` – fmw42 Nov 06 '19 at 04:05
  • Worked - thanks! The output is still not as good as www.remove.bg (edges are torn/"rough"). `fuzz` is the one to tweak to get better result correct? Any idea how remove.bg does such a good job without any configuration? – rynop Nov 06 '19 at 04:09
  • remove.bg is using deep learning (AI) and lots of training as I understand it. I have no further understanding of what they do. But simple image processing will not come close. Adjust the blur and/or the fuzz value. Post your image and I can take a look. If the background is not nearly constant, the flood fill will not work adequately. So it really depends upon the background. – fmw42 Nov 06 '19 at 04:11
  • Thx for the explanation, makes sense. I've taken enough of your time already, so I'll just play around. Your answer gets me close enough. Much appreciated!! – rynop Nov 06 '19 at 04:15
  • No problem. I am willing to take a look. But do as you please. – fmw42 Nov 06 '19 at 04:17
  • Just realized who you were, and figured you might like a challenge :) I've just sent you an email with the image. – rynop Nov 06 '19 at 04:31