Reputation: 49
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
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
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