Masking an RGB Image with Binary Mask

Duane picture Duane · Sep 14, 2013 · Viewed 15.6k times · Source

I have an RGB image (M x N x 3 matrix) in MATLAB that I read in. I also have a Binary mask (M x N matrix) for the image, which is simply 0 for some region of interest and 1 everywhere else.

I'm trying to figure out how to mask the RGB image with that binary mask. I've tried changing datatypes around (working with either double or uint8 to see if results change, but sometimes they don't or I get an error) and I've tried using various functions like conv2, immultiply, imfilter, and so on.

What I currently do is try to apply the mask individually (as it is size M x N) to each R, G, and B channel of the original image. Anywhere that the mask is 0, I wish to make exactly 0 in the original image, while anywhere the mask is 1 I just want to leave alone.

None of those functions above have seemed to work so far. Obviously, the method I know that will work is if I just went through and did a for-loop through all of this, but that would be terrible as MATLAB has these image functions, but I can't seem to get them to work.

Sometimes imfilter or immultiply (depending on how I'm messing around with the images) will just stall and crash MATLAB completely. Sometimes they finish quickly but I either get an all-white image or an all-black image (through both imshow AND imagesc).

I've checked to make sure that my image channels match up in size with the mask, and I've checked the values in both the image and the mask and they're correct. I just can't seem to get the actual masking operation to work.

Any ideas please? Maybe I'm missing something in MATLAB's rules?

Here's a current attempt:

% NOTE: The code may not be "elegant" but I\'ll worry about optimization later.
%
% Setup image and size
image = imread(im);
[numrows, numcols, temp] = size(image); % not used currently

% Request user polygon for ROI
bw = roipoly(image);

% Set up the mask -- it is indeed all 0's and 1's
t = double(imcomplement(bw));

% "Mask" the image
z = double(image);    % Double to match up with t as a double
z(:, :, 1) = imfilter(z(:, :, 1), t);
z(:, :, 2) = imfilter(z(:, :, 2), t);
z(:, :, 3) = imfilter(z(:, :, 3), t);
imshow(z); figure; imagesc(z);

=================

EDIT

Found out that the following works:

im_new = im_old .* repmat(mask, [1,1,3]);   % if both image and mask are uint8
imshow(im_new);

Answer

umlum picture umlum · Sep 14, 2013

You are misusing imfilter() there. Imfilter is used for linear filter operations, not for masking or thresholding. Better do this:

z = image;          % image() is also a function. 
                    % Overwriting this name should be avoided

% Request user polygon for ROI
bw = roipoly(z);

% Create 3 channel mask
mask_three_chan = repmat(bw, [1, 1, 3]);

% Apply Mask
z(~mask_three_chan) = 0;

% Display
imshow(z);