0

I have 2 images. One is background image and other image has same background but with some foreground object. I want to extract foreground object from background. Simple subtraction operation in matlab will not suffice as it subtracts RGB value of background image from that of foreground image (as in below code).

im1 = imread('output/frame-1.jpg')
im2 = imread('output/frame-7.jpg')

%# subtract
deltaImage = im1 - im2;
imshow(deltaImage)

So if background color is white and foreground object is blue, then output (i.e. deltaImage) comes foreground object with orange color with black background. However the output I want is foreground object with blue color (i.e. original color) with black background. How can I get this ? I tried to do it using below code, but output image is incorrect.

im1 = imread('foreground.jpg')
im2 = imread('background.jpg')
[m n k]=size(im2);
deltaImage = zeros(m,n,3);
fprintf('%d %d %d.\n',m,n,k);
for l=1:k
    for i=1:m-1
        for j=1:n-1
           if  im1(i:j:l)~=im2(i:j:l)
               deltaImage(i,j,l) = im1(i,j,l);
           end
        end 
    end
end
imshow(deltaImage)
  1. Background IMAGE

enter image description here

  1. Foreground Image

enter image description here

  1. Output Image (Here I want color of man to be blue)

enter image description here

2
  • Only subtract the background image if the pixels are equal? Commented Feb 10, 2016 at 15:23
  • @hari_OM So, do you like my answer or not? Any questions? Comments? Commented Feb 12, 2016 at 17:49

1 Answer 1

2

You can use deltaImage to create a mask (zeros and ones image) that multiplies the foreground. However, note that you will have artifacts associated with lossy image compression (.jpeg). These can be reduced, to some extent, if you use a threshold, like the average difference or a specific value you want. Try this:

im1 = double(imread('~/Downloads/foreground.jpg'));
im2 = double(imread('~/Downloads/background.jpg'));

compute the difference of the averages of the 3 channels

deltaImage = mean(im2,3) - mean(im1,3);

then use the product of the mean by a standard deviation (~3), or uncomment the line below to use a specific threshold, like 128

mask = deltaImage>3*mean(deltaImage(:));  
% mask = deltaImage>128;                  

then assuming all original images are in 8-bit format produce a result also in 8-bit format:

result = uint8(cat(3, im1(:,:,1).*mask, im1(:,:,2).*mask, im1(:,:,3).*mask));
imshow(result)

And this is the result you should get:

output

Again the weird looking pixels around the main object are artifacts of lossy image compression (.jpeg), you should try working with lossless like .png formats.

Sign up to request clarification or add additional context in comments.

3 Comments

I was getting error as Error using .* Integers can only be combined with integers of the same class, or scalar doubles.. So I made this change: result = double(im1).*mask; After running the code I am getting output like this: [work4hari.net78.net/stackoverflow/output1.jpg ](work4hari.net78.net/stackoverflow/output1.jpg)
@hari_OM The result is odd, there are lots of artifacts caused by poor compression. I have edited the answer, hopefully you will accept it.
I used your method and got output similar to what you have shown. However I tried your method over .png format, but still I am getting noise in output. One more question that arises is that when we do deltaImage = im1 - im2;, their is no noise in output.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.