# Another difficult background subtraction

I'm trying to remove the background but it is removing part of the bag in the foreground (because it is white too):

Here's what I've tried:

img = Import["https://i.imgur.com/PHY5rwj.jpg"];
fg = RemoveBackground[img, {"Background", White}];
RemoveAlphaChannel[fg, LightBlue]


I have thousands of these types of images so it isn't possible for me to add a mask for each one. Ideally, I would be able to remove the person as well and just have the bag left, although I don't think that is possible.

CloudGet@CloudObject["https://www.wolframcloud.com/objects/78a79bbb-16b6-424b-8436-4e2e24f7d228"]


• Do you have higher-resolution images, or is the image in your question the highest resolution you have? – Carl Lange Mar 19 at 15:28
• Furthermore, it would be useful to add more than a single (extremely low-resolution) image to your post so that people can see if their solution works across multiple examples. – Carl Lange Mar 19 at 15:36
• @CarlLange The hyperlinked image is {545, 545}, if that's not enough I could try to make them bigger. – M.R. Mar 19 at 17:18
• Ah, sorry, I actually just used the image you embedded, which is 100*100. Would still recommend adding a few images to the post, not just one. – Carl Lange Mar 19 at 17:39
• Actually that’s the max size that I have. – M.R. Mar 19 at 18:00

This solution more-or-less works for this particular case, but it's not going to be a general solution. However, as you only have the one image in your question this is all I have to go on for now:

SetAlphaChannel[i,
ColorNegate@
DeleteSmallComponents@FillingTransform@MorphologicalPerimeter[i, 8]]


As you can see, this works for the general background and does not remove the bag - however, it also doesn't remove the background around the handle of the bag or at the bottom left of the image. It also has clear issues around the hair and borders, and the zip has some slight removal.

The main parameter here is the one for MorphologicalPerimeter, but FillingTransform and DeleteSmallComponents also have parameters currently set to Automatic.

It may be possible to use a neural network to semantically segment the image and remove the backgrounds that way. I answered this question with an example of how to train one of these networks from scratch, or you could adapt something like this network to do this, though neither is a straightforward, 100% accuracy approach.

• Thanks, Did you see the other examples I just added them – M.R. Mar 19 at 19:16
• It doesn't do that badly on the additional examples. – M.R. Mar 19 at 19:50
• @M.R. Yes, I agree, it does OK on the additional examples but it's still not that great. If the ~75% accuracy works for you, that's great, but otherwise I think a neural network approach is good (especially if you want to also remove the human). Unfortunately I don't have the time to spare to do that :) – Carl Lange Mar 19 at 20:13
• Time and data!! – M.R. Mar 19 at 20:28
• How would you generate training data? – M.R. Mar 19 at 20:38

How about something like this, estimating the background from the median pixel value. It works (more or less) when the background value is the most abundant pixel value. Obviously (as seen in the last image), if fails when the object takes up most of the image and there are not enough background pixels.

img =

imgsub = {};
Do[{
m = Median[Flatten[ImageData[i]]];
a1 = ColorNegate[Binarize[i, Min[m + .015, .99]]];
AppendTo[imgsub, RemoveAlphaChannel[SetAlphaChannel[i, a1], Blue]];
}, {i, img}];


Randomly selecting some pixels, I noted that for RGB values, the white background has RGB colors of around (250,250,250) up to (255,255,255), while the purse has a whitish color of around (240,240,240) to about (245,245,245). Just select pixels with value R+G+B >=750 and that should get most of the background. I'd use a neural net for more intermediate colors, but mostly black and mostly white are the simplest colors to select. No MMA with me right now, but coding should be straight forward.