Clear Filters
Clear Filters

Find the average of two images

44 views (last 30 days)
Marcus Johnson
Marcus Johnson on 16 Nov 2023
Edited: DGM on 17 Nov 2023
I have these two dark images and I was wondering how to get the average of them.

Accepted Answer

DGM on 16 Nov 2023
Edited: DGM on 16 Nov 2023
% all GIF files are indexed color
% you must read the maps
[im1 map1] = imread('Im1.GIF');
[im2 map2] = imread('Im2.GIF');
% apply the maps
rgb1 = ind2rgb(im1,map1);
rgb2 = ind2rgb(im2,map2);
% the images must be floating-point for this to work
% otherwise, truncation is very likely to occur during addition
% bear in mind that im1 and im2 are going to be integer-class
imAvg = (rgb1 + rgb2)/2;
% show the image
% it's not exactly constant-valued
While in this specific case, both images use the same gray map, that's not generally something that we can expect. Similarly, while they're both gray and could be reduced from RGB to I, that's not generally true. We could reduce it if we knew that were appropriate.
if all(~diff(imAvg,2,3),'all')
imAvgGray = imAvg(:,:,1);
Image Analyst
Image Analyst on 16 Nov 2023
I think this is the preferred, more robust answer. However you can convert to double, even if they are already double though I haven't heard of a gif that is already double.
imAvg = (double(rgb1) + double(rgb2))/2; % Cast to double to ensure sums don't clip at 255.
% Show the image. Must use [] if showing a gray scale double image.
imshow(imAvg, [])
Or you can cast back to the nearest integer if you want
imAvg = uint8(imAvg);
and then you wouldn't have to use [] in imshow. If the image is RGB, then the [] does not apply but the values have to either be floating point in the range 0-1, OR uint8 in the range 0-255, otherwise you'll likely have large areas of all black or all white in the image.
DGM on 16 Nov 2023
Edited: DGM on 16 Nov 2023
Ignoring the specific example above, the problem with generally using double() on the way in to operations is that you will need to keep track of what the input class was and conditionally re-cast or re-scale the ouput, something that's inconvenient because there is no equivalent to imcast() in IPT.
% this will be wrong if the input classes are not both uint8
imAvg = (double(rgb1) + double(rgb2))/2;
imAvg = uint8(imAvg);
% or you could use cast(), but they'd still need to match
imAvg = (double(rgb1) + double(rgb2))/2;
imAvg = cast(imAvg,class(rgb1));
This could be solved by using im2double() on the way in and asserting any fixed output class, but in the given case, the outputs from ind2rgb() are going to be double.
How would I do it?
% class agnostic, output class is inherited from BG
% inputs can be I/IA/RGB/RGBA, single or multiframe
% most modes are parametric, so weighted averages are available
outpict = imblend(FG,BG,0.5,'normal'); % 50% FG, 50% BG
outpict = imblend(FG,BG,1,'average'); % 50% FG, 50% BG
outpict = imblend(FG,BG,1,'average',1.5); % 75% FG, 25% BG
... but really, for 50% average, imfuse() would also work.
Maybe all that doesn't matter, if the average is always going to then be normalized anyway. I'm going to assume that's not the case. At least it's not something that can be relied upon to generally be true.
It kind of made sense to use [] for visualization, given that it's a relatively narrow range.
GIFs are always uint8 or logical.

Sign in to comment.

More Answers (1)

Jon on 16 Nov 2023
im1 = imread('Im1.gif');
im2 = imread('Im2.gif');
imAvg = (im1 + im2)/2;
Jon on 17 Nov 2023
@DGM- Thanks for the thoughtful followup. No problem, on crediting the answer, I'm just trying to help when I can, but also learn, and I learned a lot here. Also made me realize I should be a little more careful when jumping into things I'm not well versed in. I do occassional image processing but usually monchrome .png's with simple pixel intensity stored in the array. I definitely should have remembered that these are returned as integers not doubles, and so they should be converted to doubles before, for example computing an average. I hadn't been aware of the further complexities of .gif files and indices to color maps. Thanks for helping me learn more.
DGM on 17 Nov 2023
Edited: DGM on 17 Nov 2023
As far as I'm concerned, I appreciate sincere motivations a lot more these days. There's plenty of room for answers that aren't ideal, so long as there's also room to improve. I'm not exactly careful myself :D
The canonical workflows suggested by the form of things in MATLAB/IPT leaves plenty of room for these sorts of problems with numeric class magically changing or causing incompatibility with mixed-class operations. MIMT might be a giant hobbyist embarrassment, but at least it's working toward providing class and depth-agnostic workflows in some ways. As I mentioned to IA, the way I would've done the averaging using imblend() wouldn't need to know the class of either input.

Sign in to comment.


Find more on Image Processing Toolbox 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!