den
den

Reputation: 49

Image blending with mask

I'm trying to combine the two images based on the information from the mask. I'm using the color information from the background image if the mask is 0 and color information from foreground image if the mask is 1. Because the mask and both Images are of the same size, I would like to use logical indexing of matrices to achieve this.

My attempt:

mask = imread('mask.png');
foreground = imread('fg.jpg');
background = imread('bg.jpg');
[r,c,~]=size(mask);
A = zeros(size(mask));

for i=1:r    
  for j=1:c        
    if mask(i,j) == 0
        A(i,j,:) = background(i,j,:);
    end
    if mask(i,j) > 0
        A(i,j,:) = foreground(i,j,:);
    end       
  end
end

imshow(A);

The result looks like a flickering blue image, but I don't want that. Please help.

Upvotes: 2

Views: 1028

Answers (2)

lhcgeneva
lhcgeneva

Reputation: 1981

You can do this a bit more concisely:

f = double(foreground).*double(mask);
b = double(background).*double(~mask);
blend = f+b;
imshow(blend, []);

Using logical indexing you could also do

foreground(logical(mask)) = 0;
background(logical(~mask)) = 0;
blend = foreground+background;

The ISNOT operator '~' inverts your matrix in the second line, so you cut out the area you would like for background.

NOTE: This works for black and white (one channel). For coloured images see rayryeng's solution.

Upvotes: 3

rayryeng
rayryeng

Reputation: 104555

There are two problems with your code. The first problem is that you are trying to assign colour pixels to the output image A, yet this image is only two-dimensional. You want an image with three channels, not two. In addition, the output image type you are specifying is wrong. By default, the output image A is of type double, yet you are copying values into it that aren't double... most likely unsigned 8-bit integer.

As such, cast the image to the same type as the input images. Assuming both input images are the same type, initialize your A so that:

A = zeros(size(foreground), class(foreground));

This correctly makes a colour image with the same type as any of the inputs, assuming that they're both the same type.

Now, your for loop is fine, but it's better if you do this in one shot with logical indexing. If you want to use logical indexing, create a new image that's initially blank like what you've done, but then make sure your mask has three channels to match the number of channels the other images have. After, you simply need to index into each image and set the right locations accordingly:

mask = imread('mask.png');
foreground = imread('fg.jpg');
background = imread('bg.jpg');
[r,c,d]=size(mask); %// Change

%// If your mask isn't three channels, make it so
%// Change
if d ~= 3
    mask = cat(3, mask, mask, mask);
end

A = zeros(size(foreground), class(foreground)); %// Change

A(mask) = foreground(mask); %// Assign pixels to foreground
A(~mask) = background(~mask); %// Assign pixels to background

imshow(A);

Upvotes: 2

Related Questions