How to superimpose many images using loop?

11 views (last 30 days)
Ahmed Harun-Al-Rashid
Ahmed Harun-Al-Rashid on 21 Sep 2016
Edited: DGM on 20 Jun 2022
Hi,
Could anyone please help me to superimpose many image files without transparency using loop(s)?
I use the following code, but the image quality is not good.
A = imread('1.tiff');
for idx = 2 : n
B = imread([ num2str(idx) '.tiff']); %// Read 2nd image
A = imfuse(A, B, 'falsecolor', 'Scaling', 'none'); %// Fuse 1st (A) & 2nd image, and store into A again.
end
imwrite(A,'bind.png');
When I superimpose manually as shown in example, the pixels of various images mix up and create new shades of colour. So, my target is to replace any pixel by the next image pixels.

Answers (1)

DGM
DGM on 20 Jun 2022
Edited: DGM on 20 Jun 2022
Imfuse is a simple tool for visually comparing two images. It has no practical use for processing more than two images.
It should be obvious that the above wouldn't work. Whenever imfuse() does 'falsecolor' blending, the input images are converted to grayscale by calculating their luma. A composite RGB image is created by simply inserting copies of those two grayscale images into the appropriate RGB channels. Attempting to iteratively process images like this will always result in the same thing: an image with shades of two colors.
Consider the simple example:
% some test images
A = imread('stackedA_inv.png');
B = imread('stackedB_inv.png');
C = imread('stackedC_inv.png');
D = imread('stackedD_inv.png');
imstack = {A B C D};
% show the images as a montage
montage(imstack)
% replicate the OP's blending method
outpict = imstack{1};
for f = 2:numel(imstack)
outpict = imfuse(outpict,imstack{f},'falsecolor');
end
% show the result
imshow(outpict)
Note that only the last frame has unique hue. Also note that even though all the objects in prior frames originally had the exact same color, they are represented in the composite image by three different shades of magenta. Why is that? Recall that the input images are converted to their luma. Each time the output of imfuse() is fed to itself, the green and magenta regions are weighted differently, even if they came from identical source colors. The result is a bunch of garbage with inherent inconsistency that's an artifact of the process rather than the source images.
Using other modes like 'blend' will similarly result in problems due to inconsistent weighting. If data scaling other than 'none' is used in either case, the resultant data scaling would be wrong even if it weren't wrong for all these other reasons.
So how would you represent many images without transparency and without any form of color mixing? The question seems to imply that the images must be composited using some sort of yet-undefined logical masking method. How this is done might be anything from tedious to trivial depending on what the source images are and what the actual intent is -- neither of which are obvious in this case.
That said, I don't think that those stipulations were necessarily appropriate to begin with. Disregarding the plot decorations (title, box, etc) and the land profile, the content of interest is a set of dark (i assume grayscale) patches on a white background. Binary composition would likely make a mess and would be unnecessarily complicated.
How would you combine a set images with dark content on a white background without letting the background skew the composition? Again, that depends on the intent. You could do a 'multiply' blend (multiplication), a 'linear burn' blend (inverse addition), or you could do a 'darken' blend (min(A,B)). Each of these will vary in behavior where dark regions overlap. If a dark pixel overlapping another should scale the underlying pixel, then use 'multiply'. If a dark pixel should subtract from the underlying pixel, then use a linear burn. If you only are concerned with the darkest pixels out of all images, use min() or a 'darken' blend.
Consider the following examples:
% some test images
A = imread('stackedA_inv.png');
B = imread('stackedB_inv.png');
C = imread('stackedC_inv.png');
D = imread('stackedD_inv.png');
% stack on dim 4
imstack = cat(4,A,B,C,D)*0.5 + 128; % black is now gray
% show the images as a montage
montage(imstack)
% blend the images
%outpict = mergedown(imstack,1,'multiply'); % scale
%outpict = mergedown(imstack,1,'linearburn'); % subtract
outpict = mergedown(imstack,1,'darkenrgb'); % minimize
multiply
linear burn
darken rgb
While I'm using MIMT mergedown()/imblend() in this example, these are three of the simplest blending operations and can easily be done with base MATLAB tools if care is taken to account for numeric class and scaling.
How would one have applied this blending approach to the original problem? That depends. If the latter 'darken' blend is used, the blending can be done directly on the images. For the other modes, it would be important to preserve any non-data gray content. Assuming the images are as given and there is no access to the original code that created them, I'd start by trying to extract the image content that represents the data from everything else (the title, labels, grid, land outlines). It's hard to guess at what the easiest method would be without knowing what the images were.
The idea would be to have one image that represents the static content (plot decorations), and several images with all the static content removed. Blend the cleaned images of data and then combine the result with the static content. The most difficult part will be the grid lines.
Alternatively, you might choose to simply create a mask which describes areas which are non-data gray regions. Blend the original images in whole and then use the mask to replace those gray regions.
It's also worth noting that in either case, the plot title would need to be edited/replaced, since it won't represent the correct range of dates.

Community Treasure Hunt

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

Start Hunting!