0

I'm trying to subtract the background of an image with two images. Image A is the background and image B is an image with things over the background. enter image description here

I'm normalizing the images but I don't get the expected result. Here's the code:

a = rgb2gray(im);
b = rgb2gray(im2);
resA = ((a - min(a(:)))./(max(a(:))-min(a(:))));
resB = ((b - min(b(:)))./(max(b(:))-min(b(:))));
resAbs = abs(resB-resA);
imshow(resAbs);

The resulting image is a completely dark image. Thanks to the answer of the user saeed masoomi, I realized that was because of the data type, so now, I have the following code:

a = rgb2gray(im);
b = rgb2gray(im2);
resA = im2double(a);
resB = im2double(b);
resAbs = imsubtract(resB,resA);
imshow(resAbs,[]);

The resulting image is not well filtered and there are parts of image B that don't appear but they should.

enter image description here

If I try doing this without normalizing, I still have the same problem. enter image description here

The only difference between image A and B are the arms that only appears in image B, so they should appear without any cut.

Can you see something wrong? Maybe I should filter with a threshold?

inavas
  • 161
  • 7

2 Answers2

0

Hi please pay attention to your data type ... images in matlab save in unsigned char(or int) (8-bit 0 to 255 and there is no 0.1 or 0.2 or any float number so if you have 1.2 output will be 1).

you have a wrong computation in uint8 data like below

max=uint8(255);                         %uint8
min=uint8(20);                          %uint8
data=uint8(40);                         %uint8
normalized=(data-min)/(max-min)         %uint8

output will be

normalized =

uint8

0

ooops, you may think that this output will be 0.0851 but it's not because data type is uint8 and output will be 0 ... so i guess your all data is zero( result image is dark ) ...so for prevent this mistake MATLAB have a handy function named im2double (convert uint8 to double and all data normalized between 0 and one)

I2 = im2double(I) converts the intensity image I to double precision, rescaling the data if necessary. I can be a grayscale intensity image, a truecolor image, or a binary image.

so we can rewrite your code like below

a = rgb2gray(im);
b = rgb2gray(im2);
resA = im2double(a);
resB = im2double(b);
resAbs = abs(imsubtract(a,b));    %edited
imshow(resAbs,[])

edited

so if again output image is dark you must be check that two image have different pixel by below code!!

if(isempty(nonzeros))
  disp('Two image is diffrent -> normal')
else
  disp('Two image is same -> something wrong')
end
Saeed Masoomi
  • 1,703
  • 1
  • 19
  • 33
  • You were right about the data type, thanks! But I still have the same problem.. I have edited the first post with more details and information. – inavas May 09 '17 at 18:46
0

Do not normalize the two images. Background subtraction is typically done with identical camera settings, so the two images are directly comparable. If the background image doesn't have a bright object in it, normalizing like you do would brighten it w.r.t. the second image. The intensities are no longer comparable, and you'd see differences where there were none.

If you recorded the background image with different camera settings (different exposure time, illumination, etc) then background subtraction is a lot more complicated than you think. You'd have to apply an optimization scheme to make the two images comparable, such that their difference is sparse. You'd have to look through the literature for that, it's not at all trivial.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • At first I am trying to do the background subtraction with two images with the same camera settings, but images are from a video which sometimes suffers illumination changes, so I think I need to normalize every frame because of that. Any help is appreciated. – inavas May 09 '17 at 18:22
  • In that case, use Gaussian mixture models: https://en.wikipedia.org/wiki/Background_subtraction#Background_mixture_models , https://hal.archives-ouvertes.fr/hal-00338206/document . Normalization like you do is a bad idea! – Cris Luengo May 09 '17 at 18:26
  • I see, thanks! But I don't understand why the method that I am using is not working properly with the two initial images (with the same camera settings). I mean, I don't understand why the hand doesn't appear without any cut. I tried normalizing and without normalizing and I still have the hand cut. – inavas May 09 '17 at 18:57
  • Maybe you need to convert the images to double (or another signed format) before the subtraction? With uint8, 10-100==0! – Cris Luengo May 09 '17 at 19:34
  • I used the im2double function but I still have the same problem :( – inavas May 09 '17 at 19:37
  • Also, it might be just the different contrast. You compute the intensity difference between the hand and what is behind the hand. If the wheel is brighter than the areas around the wheel, then there will be less intensity difference in those areas. Background subtraction is meant to identify pixels that changed. You threshold the result to find those pixels, then you show the original grey values of those pixels: a * (resAbs>10). – Cris Luengo May 09 '17 at 19:39