Overlay two images of different type

9 views (last 30 days)
Xen
Xen on 15 Jan 2015
Edited: DGM on 13 Feb 2023
I have a uint8 image and another logical image of the same dimensions, containing edges found from the first one. I want to make the white pixels (edges) of the logical image red (so must be converted to rgb) and then superimpose it over the original uint8 image. Transparency is not a requirement, I want the simplest code possible! Thanks everyone.

Accepted Answer

Xen
Xen on 19 Jan 2015
Thanks for your suggestions guys. After some experimentation, I have eventually found out how to do exactly what I needed (and it's not that difficult after all). If you suggest any alterations for coding improvement, I am glad to hear them.
% these 3 conversions from uint8 to RGB are required
% otherwise the images will not overlay
image = uint16(image); % image is the original image
[indexed,map] = gray2ind(image,256);
image2 = ind2rgb(indexed,map); % image2 is the original image in RGB
[rows, columns] = find(edges); % edges is the binary image
pixelcount = size(rows,1);
for i = 1:pixelcount
image2(rows(i),columns(i),1) = 1;
image2(rows(i),columns(i),2) = 0;
image2(rows(i),columns(i),3) = 0;
% ignoring the last two makes red transparent!
end
imwrite(image2, [mysavefolder, '\overlaid.png']);
  3 Comments
Xen
Xen on 19 Jan 2015
Thanks for these tricks and sorry about that. I've certainly never heard of "burning" the color; nevertheless this method gives me a pretty much equivalent image to the overlay method in Steve's blog, in contrast to the other (also not overlay!) methods of plotting markers suggested... I think I've mentioned saving the resulting image below (?).
Image Analyst
Image Analyst on 19 Jan 2015
Plotting markers is also in the overlay. Any sort of graphics that is overlaid above the image is considered in the overlay. It's not in the overlay if the graphics actually change the value of the image variable. If I overlay an image, or lines, or text, or markers, and then check the pixel value of the variable in my program you'll see the value of the image variable is no different before or after putting up the graphics. All that stuff stays in the overlay and does not change the underlying image, only what you see displayed. This is how overlay is defined though perhaps it doesn't agree with your preconceptions of what it should be.

Sign in to comment.

More Answers (5)

Matt J
Matt J on 15 Jan 2015
This FEX file can do that,
I don't know if there are simpler ways.

Image Analyst
Image Analyst on 15 Jan 2015
See these two links for demos and code:
Also check out the functions imshowpair() and imfuse() in the Image Processing Toolbox.
  2 Comments
Xen
Xen on 17 Jan 2015
Forgive my ignorance; I am sure these are pretty obsolete questions... Steve's blog explains what to do when displaying the images on the screen (I assume!). How can I add the same procedure (copied below) in an .m code, where a loop runs over several input images and saves the resulting image for each iteration.
imshow(E, 'InitialMag', 'fit')
green = cat(3, zeros(size(E)), ones(size(E)), zeros(size(E)));
hold on
h = imshow(green);
hold off
set(h, 'AlphaData', I)
Image Analyst
Image Analyst on 18 Jan 2015
Just call export_fig after you've displayed your image and plotted dots over it. Check the file exchange for export_fig().

Sign in to comment.


Image Analyst
Image Analyst on 15 Jan 2015
Another simple way is to just get the coordinates of your binary image and then call plot to lay down a dot.
[rows, columns] = find(binaryImage); % Returns [y, x] since rows = y.
hold on;
plot(columns, rows, 'r.', 'MarkerSize', 1); % Increase marker size if you want.
  4 Comments
Image Analyst
Image Analyst on 18 Jan 2015
Try
plot(x, y, 'r.'); % Plot a single dot.
DGM
DGM on 13 Feb 2023
The apparent size of a rendered '.' marker may be 1px, but they will only be displayed correctly if their spacing is also 1px. This requires the image is to be rendered at 1:1. If it's not scaled 1:1, the colored area will be filled with interference patterns. You'd have to use truesize() to set that. That also means that this won't work for large images or docked figures.
Likewise, trying to save the image+scatter is likely going to end up with a result that's unpredictably sized and/or padded depending on version, environment, and the method used.
This is also relatively very slow. While the difference between 6ms and 600ms might not be a big deal for something that has to happen once or twice, these compromises are unnecessary.
It's pretty clever though.

Sign in to comment.


Haripriya Sharma
Haripriya Sharma on 15 Apr 2016
MATLAB R2016a introduced "imoverlay" function in Image Processing Toolbox to accomplish this. For more information please refer to the following documentation page: http://www.mathworks.com/help/images/ref/imoverlay.html
  2 Comments
Xen
Xen on 15 Apr 2016
Aha. That's great. Did you MATLAB guys got the idea from my question?!
Matt J
Matt J on 15 Apr 2016
Edited: Matt J on 15 Apr 2016
Hmmm. That's one of the unfortunate hazards of the FEX, I suppose. I've been using a function called imoverlay from the FEX for a few years now and my mfile library is now replete with it. If I now want access to R2016a's native imoverlay, or if I give my code to someone who does, I'll have to do a lot of search/replacing :-(

Sign in to comment.


DGM
DGM on 13 Feb 2023
Edited: DGM on 13 Feb 2023
This was never a complicated question, even in 2015. This is concise and works for logical and numeric masks. The background can be I/RGB, and so can the foreground color tuple.
% an image presumed to be uint8 (I or RGB works)
inpict = imread('peppers.png'); % uint8 (RGB)
%inpict = rgb2gray(inpict); % convert to gray (I)
% a mask and foreground color tuple
% mask can be numeric or logical
mask = imread('redpepmask.png');
fgcolor = [0.5 0 1]; % an I/RGB tuple in unit-scale
% do basic multiplicative composition
% since we're living in 2015, this uses bsxfun()
mask = im2double(mask);
fgc = bsxfun(@times,mask,permute(fgcolor,[1 3 2]));
bgc = bsxfun(@times,(1-mask),im2double(inpict));
outpict = im2uint8(bsxfun(@plus,fgc,bgc));
imshow(outpict)
If you really absolutely wanted code that works on nothing but logical masks, you can do that too! Believe it or not, this isn't significantly faster than doing all that multiplication.
% an image presumed to be uint8 (I or RGB works)
inpict = imread('peppers.png'); % uint8 (RGB)
%inpict = rgb2gray(inpict); % convert to gray (I)
% a mask and foreground color tuple
% mask must be logical
mask = imread('redpepmask.png')>128;
fgcolor = [0.5 0 1]; % an I/RGB tuple in unit-scale
fgchans = numel(fgcolor);
bgchans = size(inpict,3);
outpict = zeros(size(inpict));
for c = 1:max(fgchans,bgchans)
thischan = im2double(inpict(:,:,min(c,bgchans)));
thischan(mask) = fgcolor(min(c,fgchans));
outpict(:,:,c) = thischan;
end
outpict = im2uint8(outpict);
imshow(outpict)
While FEX imoverlay() existed, that's basically a simple scalar alpha composition, so it wouldn't easily work for a masked task. The contemporary IPT imoverlay() would probably satisfy OP's needs, but it didn't exist then.
Circa 2015, MIMT did have tools to do this, though I don't remember if everything had been consolidated into replacepixels() yet. If nothing else, it should have at least supported logical masks. That said, even the current version of replacepixels() works at least back to R2009b. So if you wanted the "simplest" (easiest to use, fewest lines needed, fewest restrictions to accomodate), then MIMT replacepixels() would take the cake in 2015, same as it does today.
% an image of any class (I or RGB works)
inpict = imread('peppers.png'); % uint8 (RGB)
%inpict = rgb2gray(inpict); % convert to gray (I)
% a mask and foreground color tuple
% mask can be numeric or logical
mask = imread('redpepmask.png');
fgcolor = [0.5 0 1]; % an I/RGB tuple in unit-scale
% use MIMT replacepixels(FG,BG,mask)
% FG and BG can be an I/IA/RGB/RGBA/RGBAAA image or tuple
% mask can be an I/RGB image or tuple
% mask can be logical or numeric
% output class is inherited from BG
outpict = replacepixels(fgcolor,inpict,mask); % one line
imshow(outpict)
IPT imoverlay is limited in that it really can only do logical operations (no smooth masks, no transparency), and can only do so with (at most) a color tuple as the foreground. So even though IPT imoverlay() exists today, I can't help but see it as a tiny fraction of an answer to general masked composition.

Categories

Find more on Convert Image Type in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!