Mean of 10000 images

3 views (last 30 days)
Efstathios Kontolatis
Efstathios Kontolatis on 3 Oct 2016
Commented: Adam on 3 Oct 2016
I have a group of 10000 uint16 tiff images. Which is the best way to create the mean image of them as a uint16 tiff. If I keep them as uint16 the sum of images obviously stops at 65535 so it doesn't take into account the rest of the images.

Accepted Answer

Guillaume
Guillaume on 3 Oct 2016
Edited: Guillaume on 3 Oct 2016
Use the mean function then, which does not suffer from overflow. Assuming the images are grayscale and in a cell array:
m = mean(cat(3, yourcellarray{:}), 3, 'native'); %'native' if you want output as uint16, otherwise it is double
If images are rgb:
m = mean(cat(4, yourcellarray{:}), 4, 'native');
Or more generically:
sz = size(yourcellarray)
assert(all(cellfun(@(im) isequal(size(im), sz), yourcellarray)), 'Not all images have the same size')
m = mean(cat(numel(sz)+1, yourcellarray{:}), numel(sz)+1, 'native');

More Answers (1)

Image Analyst
Image Analyst on 3 Oct 2016
Edited: Image Analyst on 3 Oct 2016
You have an impressive computer if you can store ten thousand images all in a cell array. For a garden variety digital camera image, that would be about 360 GB. Glad it works for you though. I was going to suggest the traditional method, which may be useful for those with not so impressive computers
In simplified form:
% Get a list of all files in the folder with the desired file name pattern.
filePattern = fullfile(myFolder, '*.jpg'); % Change to whatever pattern you need.
theFiles = dir(filePattern);
sumImage = zeros(rows, columns, numberOfColorChannels);
numberOfFiles = length(theFiles);
for k = 1 : numberOfFiles
baseFileName = theFiles(k).name;
fullFileName = fullfile(myFolder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
% Now do whatever you want with this file name,
% such as reading it in as an image array with imread()
imageArray = imread(fullFileName);
imshow(imageArray); % Display image.
drawnow; % Force display to update immediately.
sumImage = sumImage + double(imageArray); % Assumes all the same size.
end
sumImage = sumImage / numberOfFiles;
It would be good to make it more robust by making sure all the images are the same size. I attach an old demo I have that takes the average of RGB images and does the size check.
Why are you storing all of your images in a cell array anyway? Do you need them later and have enough RAM memory (like half a terabyte) and don't want to spend the time to read them in again?
  4 Comments
Efstathios Kontolatis
Efstathios Kontolatis on 3 Oct 2016
Is there a difference if I cast the result with the im2uint16 command?
Adam
Adam on 3 Oct 2016
im2uint16 will expect double data to be in the range 0-1 which it won't be unless you explicitly scaled it to that range when converting from int16 originally and it won't be in Image Analyst's answer above so you don't want to use that.
If you want to max stretch the mean to fill the full data range then you need to do more than cast it, but then it isn't technically the mean either, if that matters.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!