Need help to overlay transparent red on gray scale images (or movie) using a binary mask
21 views (last 30 days)
Show older comments
Hi!
I have gray scale data with objects, to simplify in this case the 5's belong to the object e.g.:
[1, 1, 1, 1, 1, 1;
1, 1, 5, 5, 1, 1;
1, 1, 5, 5, 1, 1;
1, 1, 1, 1, 1, 1]
(In realitity the image is larger, with different values, multiple images (movie), and more objects)
Anyway I also have a mask that matches with the objects visible. e.g.:
[0, 0, 0, 0, 0, 0;
0, 0, 1, 1, 0, 0;
0, 0, 1, 1, 0, 0;
0, 0, 0, 0, 0, 0]
I would like to overlay a red transparent blur over the original image to highlight the objects using the mask.
I have tried some stuff, but the resulting images/movie turns out to be all white.
What I tried is to add RBG channels and copying the original data in each of them, and then modify the red channel by using the mask. Can anyone help me?
0 Comments
Accepted Answer
DGM
on 1 Jul 2023
Edited: DGM
on 1 Jul 2023
If you have IPT, you could use labeloverlay()
% labeloverlay() supports multichannel images
gray_image = imread('peppers.png');
gray_image = im2gray(gray_image);
% mask must be an integer-valued array whose number of unique nonzero values
% is no greater than the height of the specified colormap array (it's an index array)
mask = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1424023/redpepmask.png');
mask = mask > 128;
% note that labeloverlay() uses transparency, not opacity/alpha
alpha = 0.5;
outpict = labeloverlay(gray_image,mask,'colormap',[1 0 0],'transparency',1-alpha);
imshow(outpict,'border','tight')
... but I get tired of remembering all the little things that imoverlay() and labeloverlay() don't support. While labeloverlay() makes a lot more sense for applying a multi-class overlay to an image, I find it to be an awkward and limited choice for single-class basic composition tasks like this. MIMT replacepixels() is generalized and more convenient for composition tasks. The same task is simpler and has fewer restrictions. The antialiased mask can be used as-is, without binarization.
% each of the three main arguments to replacepixels() can be
% any properly-scaled image or tuple (I/IA/RGB/RGBA/RGBAAA)
gray_image = imread('peppers.png');
gray_image = im2gray(gray_image);
% the mask does not need to be binarized
% and it's not treated as an index array
% this is an antialiased mask.
mask = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1424023/redpepmask.png');
alpha = 0.5;
outpict = replacepixels([1 0 0],gray_image,mask*alpha);
imshow(outpict,'border','tight')
I'm assuming you meant "blob" instead of "blur", but if you actually did want the mask to be blurred or antialiased, imoverlay() and labeloverlay() are out of the question. With replacepixels(), just blur the mask.
While replacepixels() does support multiframe images, I doubt your workflow is set up like that, so it's probably not going to be of much help.
Of course, this could be done using rudimentary operations, but convenient tools exist for a reason. There are also different ways one could interpret "overlay".
2 Comments
DGM
on 1 Jul 2023
Edited: DGM
on 1 Jul 2023
There are varied conventions for how mutiframe/volumetric images are represented in different contexts. replacepixels() expects images to be arranged as [rows columns channels frames] so multiframe images/masks are represented as 4D arrays, regardless of how many channels they have.
If you have a multiframe image and mask represented as 3D arrays, you can still do that:
% let's say your image and mask are uint8 3D volumes
% in this case, they represent [rows columns frames]
gray_image = im2uint8(rand(10,10,20));
mask = im2uint8(rand(10,10,20));
% replacepixels expects the frame axis to be dim4, so permute
gray_image = permute(gray_image,[1 2 4 3]);
mask = permute(mask,[1 2 4 3]);
alpha = 0.5;
outpict = replacepixels([1 0 0],gray_image,mask*alpha);
The result will be a 4D array of size [10 10 3 20]. If you expect it to be [10 10 20 3], as you might have in GMIC, you can always use permute to rearrange the output array.
While this sort of workflow is very convenient and succinct, it does have practical limitations. Processing large monolithic arrays at once can have higher peak memory use, and allocating large blocks of contiguous memory for intermediate results can often slow things down. While page geometries are often fairly reasonable, a frame sequence from a video can be quite long. Depending on the volume of data, it's often reasonable to go ahead and process it framewise.
More Answers (2)
Mihir
on 1 Jul 2023
Hi, you can take the following steps to overlay a red transparent blur over the original grayscale image using the provided mask:
1. Define the original grayscale image and the mask.
- `gray_image` represents the grayscale image with objects. It is a 4x6 matrix in this example.
- `mask` represents the mask that matches the objects visible. It has the same size as `gray_image`.
2. Create an RGB image from the grayscale data.
- `rgb_image` is a 4x6x3 matrix created using the `cat` function. The three color channels (red, green, blue) are initialized with the same values as the grayscale image.
3. Apply the mask to the red channel of the RGB image.
- `red_channel` is extracted from `rgb_image` using `rgb_image(:,:,1)`.
- Wherever the mask is 1, the corresponding pixels in the red channel are set to 255 (maximum intensity), highlighting the objects.
4. Apply a blur to the modified red channel to create a transparent effect.
- The `imgaussfilt` function is used to apply a Gaussian blur to the `red_channel`, creating a smooth and blurred effect.
- The `blur_radius` parameter determines the extent of the blur. In this example, a radius of 5 is used.
5. Combine the modified red channel with the original green and blue channels.
- The modified red channel `blurred_red` is assigned back to the red channel of `rgb_image`, replacing the original values.
- The green and blue channels remain unchanged.
6. Display the resulting image.
- The `imshow` function is used to display the final RGB image with the overlay of the red transparent blur.
By following these steps, the code creates an image where the objects specified by the mask are highlighted with a red transparent blur effect, overlaying the original grayscale image.
% Define the original grayscale image and the mask
gray_image = [1, 1, 1, 1, 1, 1;
1, 1, 5, 5, 1, 1;
1, 1, 5, 5, 1, 1;
1, 1, 1, 1, 1, 1];
mask = [0, 0, 0, 0, 0, 0;
0, 0, 1, 1, 0, 0;
0, 0, 1, 1, 0, 0;
0, 0, 0, 0, 0, 0];
% Create an RGB image from the grayscale data
rgb_image = cat(3, gray_image, gray_image, gray_image);
% Apply the mask to the red channel of the RGB image
red_channel = rgb_image(:,:,1);
red_channel(mask == 1) = 255; % Set the value to 255 (maximum intensity) where the mask is 1
% Apply a blur to the modified red channel to create a transparent effect
blur_radius = 5; % Adjust the radius as needed
blurred_red = imgaussfilt(red_channel, blur_radius);
% Combine the modified red channel with the original green and blue channels
rgb_image(:,:,1) = blurred_red;
% Display the resulting image
imshow(rgb_image);
1 Comment
DGM
on 1 Jul 2023
Edited: DGM
on 1 Jul 2023
Blurring part of an image doesn't make it transparent. It just makes it blurry.
gray_image = imread('peppers.png');
gray_image = im2gray(gray_image); % image is presumed to be uint8, single-channel
mask = imread('redpepmask.png');
mask = mask > 128; % mask is presumed to be unit-scale
% Create an RGB image from the grayscale data
rgb_image = cat(3, gray_image, gray_image, gray_image);
% Apply the mask to the red channel of the RGB image
red_channel = rgb_image(:,:,1);
red_channel(mask == 1) = 255; % Set the value to 255 (maximum intensity) where the mask is 1
% Apply a blur to the modified red channel to create a transparent effect
blur_radius = 5; % Adjust the radius as needed
blurred_red = imgaussfilt(red_channel, blur_radius);
% Combine the modified red channel with the original green and blue channels
rgb_image(:,:,1) = blurred_red;
% Display the resulting image
imshow(rgb_image);
It's not just the red overlay that's blurred; it's the entire red channel of the original image, which will cause red-cyan halos around all the edges in the rest of the image.
% zoom in on the image to show the edge effects
sample = imcrop(rgb_image,[149 144 183 140]);
figure
imshow(sample)
If the image region is already white, then the result will not be red, but white (as your own example demonstrates; yes, that big blank region is an all-white image). You're not doing any compositing. You're merely doing what's equivalent to a max() operation.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!