How to average multiple images in matlab? - matlab

I am trying to get the average image from 1000 frames.
Each image is 512 by 512 pixel size.The file I got from the experiments is a tiff unit 16 data.
the tiff file contains 1000 frames of the same spot.
I was thinking writing a m file where I read out 1000 frames from the tiff file then average them but it seems will eat up the memory very fast.
What is the better way to get the average image of these 1000 frames. If the only way is to average them after load all the frames into matlab, how should I average over 1000 frames?
Thanks.

try the following:
a=zeros(512);
for i=1:1000
a=a+frame(i);
end
a=a/1000;
a is the average of the frames.

After each image is read you can accumulate it in the temporary variable, i.e. add current image to this variable at each step. After you read all images the accumulator will store the sum of all images. Finally, divide it by the number of images and you will get final image.
But it is significant that images are usually stored as uint8 (unsigned 8-bit integer). And if it is summed up, the overflow will occur. To prevent this accumulator should be e.g. uint32 or double. If you want the final image to be uint8, an explicit convertion is required.

% slight modiifcations to the last answer
if the files are named image1.tif, image2.tif,....image1000.tif)
im = imread('image1.tif');
for i = 2:1000
im = imadd(im,imread(sprintf('image%d.tif',i)));
end
im = im/1000;
imshow(im,[]);
The problem gets interesting when you have names like image00001, image00002,....image00010,...image00100,.... here just read from 2-10 in one loop 11-99 in another and so so...hope it helps

source = 'D:\file_path\'; %'
im_number=262; % image number should not exceed 16 843 009 images
sum=uint32(imread([source,'image1.bmp'],'bmp')); % converts image array to Unsigned 32-bit integer to escape overflow
for n=2:im_number;
sum=imadd(sum,uint32(imread([source,'image', num2str(n),'.bmp'],'bmp'))); % perform addition without overflow
% using images specific function imadd
end;
sum = imdivide(sum,im_number); % performing normalization of addition using images specific function imdivide
imshow(uint8(sum),[]); % displais the image converted back to Unsigned 8-bit integer
imwrite(uint8(sum),[source,'sum_image.bmp'],'bmp'); % saves the averaged image

% assuming there are files named: '1.tif','2.tif',...'1000.tif'
im = imread('1.tif');
for i = 2:1000
im = imadd(im,imread(sprintf('%d.tif',i)));
end
im = im/1000;
imshow(im,[]);

J=0;
for i =1:index %index is the number of images to be averaged
I=uint32(imread(['frame',num2str(i),'.bmp']));
J=imadd(I,J);
end
J=floor(J/index);
J=uint16(J); %J is the required image

Related

Matlab function reshape doesnt´t calculate the last dimension while trying to create a 3D image from .raw binary image file

I created binarized images by using the Otsu methode in Matlab and cut out parts of the resulting image using a function. Now i want to take a look at these images with the VolumeViewer command. I know the x,y and z dimensions of the resulting imgages. I currently run this code doing it(excluding the volumeViewerwhich happens after the loop):
files= {'C3\C3_000mal_550_539_527.raw';...
};
for i=1:numel(files)
Image = fopen(files{i},'r');
ImageData{i} = fread(Image,Inf,'uint16=>uint16');
ImageData{i} = reshape(ImageData{i},550,539,[]);
fclose(openedCrystalImage);
end
Using this code runs into the following error using reshape:
Error using reshape
Product of known dimensions, 296450, not divisible into total number of elements, 78114575.
I did the maths and 550*539=296450 and 296450 * 527=156229150: If we divide the last number by the number of elements it equals 2 and thus is divisible into the total number of elements. In my opinion the reshape function is not able to find the size of the last dimension or defines it as 1.
Defining the size of z also results in an error suggesting using the brackets [], so the function can find it.
Error using reshape
Number of elements must not change. Use [] as one of the size inputs to automatically calculate the appropriate size
for that dimension.
Now to the weird part. This code works for another set of images, with diffrent sizes of the x,y and z ranges. So don´t know where the issue lies to be frank. So i would really appreciate and Answer to my question
I figured it out. The error lies here:
ImageData{i} = fread(Image,Inf,'uint16=>uint16');
Apparently by saving them as .raw before it converts the image to an 8 bit file rather than 16 bits it had before. Therefore, my dimension is double the size of the number of elements. With this alteration it works:
ImageData{i} = fread(Image,Inf,'uint8=>uint8');
The reason i was able to look at the other pictures was that the z range was divisble by 2.
So the reshape function was not the problem but size of the integer data while creating the array for the variable ImageData.
P.S. I just started out programming so the accuracy in the answer should be taken with a grain of salt

read 2d grey images and combine them to 3d matrix

I have some problems with matlab 2015a Win10 X64 16GB Ram.
There is a bunch of images (1280x960x8bit) and I want to load them into a 3d matrix. In theory that matrix should store ~1.2GB for 1001 images.
What I have so far is:
values(:,:,:)= zeros(960, 1280, 1001, 'uint8');
for i = Start:Steps:End
file = strcat(folderStr, filenameStr, num2str(i), '.png');
img = imread(file);
values(:,:,i-Start+1) = img;
end
This code is working for small amount of images but using it for all 1001 images I get "Out of memory" error.
Another problem is the speed.
Reading 50 images and save them takes me ~2s, reading 100 images takes ~48s.
What I thought this method does is allocating the memory and change the "z-elements" of the matrix picture by picture. But obviously it holds more memory than needed to perform that single task.
Is there any method I can store the grey values of a 2d picture sequence to a 3d matrix in matlab without wasting that much time and ressources?
Thank you
The only possibility I can see is that your idexes are bad. But I can only guess because the values of start step and End are not given. If End is 100000000, Start is 1 and step is 100000000, you are only reading 2 images, but you are accessing values(:,:,100000000) thus making the variable incredibly huge. That is, most likely, your problem.
To solve this, create a new variable:
imagenames=Start:Step:End; %note that using End as a variable sucks, better ending
for ii=1:numel(imagenames);
file = strcat(folderStr, filenameStr, num2str(imagenames(ii)), '.png');
img = imread(file);
values(:,:,ii) = img;
end
As Shai suggests, have a look to fullfile for better filename accessing

MATLAB loading and saving a single image from a 32 bit tiff stack

I'm using MATLAB_R2011a_student. I have some image stacks saved as 32 bit tiffs, some over 1000 frames. I would like to be able to pull out a specific frame from the stack and save it as a 32 bit tiff or some readable format where there would be no data loss from the original. Currently my code looks like this:
clear, clc;
k=163;
image=('/Users/me/Filename.tiff');
A = uint8(imread(image, k));
B=A(:,:,1);
J=imadjust(B,stretchlim(B),[]);
imwrite(J,'/Users/me/163.tif','tif');
(I'm assuming reading it as 8 bit, and the way I'm saving are not the best way to do this)
Either way this code works for a seemingly random number of frames (for example in one file.tiff the above code works for frames 1-165 but none of the frames after 165, for a different file.tiff the code works for frames 1-8 but none of the frames after 8) I'm also getting a strange horizontal line in the output image when this does work:
??? Error using ==> rtifc
Invalid TIFF image index specified.
Error in ==> readtif at 52
[X, map, details] = rtifc(args);
Error in ==> imread at 443
[X, map] = feval(fmt_s.read, filename, extraArgs{:});
Thanks!
The best way (in my opinion) to handle tiff stacks is to use the Tiff library available since a few years. I must admit that I don't know much about OOP but I managed to understand enough to load a tiff stack and manipulate it.That's the kind of simple demo I wish I had seen a year ago haha.
I the following example I load a single stack and store it all into a 3D array. I use imfinfo to fetch infos about the images, notably the number of images/stack and the actual image dimensions. If you want you can choose to load only one image using appropriate indices. Please try the code below and play around with it; you'll understand what I mean.
clear
clc
%// Get tiff files you wish to open
hFiles = dir('*.tif');
%// Here I only have 1 multi-tiff file containing 30 images. Hence hInfo is a 30x1 structure.
hInfo = imfinfo(hFiles(1).name);
%// Set parameters.
ImageHeight = hInfo(1).Height;
ImageWidth = hInfo(1).Width;
SliceNumber = numel(hInfo);
%// Open Tiff object
Stack_TiffObject = Tiff(hFiles.name,'r');
%// Initialize array containing your images.
ImageMatrix = zeros(ImageHeight,ImageWidth,SliceNumber,'uint32');
for k = 1:SliceNumber
%// Loop through each image
Stack_TiffObject.setDirectory(k)
%// Put it in the array
ImageMatrix(:,:,k) = Stack_TiffObject.read();
end
%// Close the Tiff object
Stack_TiffObject.close
Hope that helps.

How to do a median projection of a large image stack in Matlab

I have a large stack of 800 16bit gray scale images with 2048x2048px. They are read from a single BigTIFF file and the whole stack barely fits into my RAM (8GB).
Now I need do a median projection. That means I want to compute the median of each pixel across all 800 frames. The Matlab median function fails because there is not enough memory left make a copy of the whole array for the function call. What would be an efficient way to compute the median?
I have tried using a for loop to compute the median one pixel at a time, but this is still terribly slow.
Iterating over blocks, as #Shai suggests, may be the most straightforward solution. If you do have this problem frequently, you may want to consider converting the image to a mat-file, so that you can access the pixels as n-d array directly from disk.
%# convert to mat file
matObj = matfile('dest.mat','w');
matObj.data(2048,2048,numSlices) = 0;
for t = 1:numSlices
matObj.data(:,:,t) = imread(tiffFile,'index',t);
end
%# load a block of the matfile to take median (run as part of a loop)
medianOfBlock = median(matObj.data(1:128,1:128,:),3);
I bet that the distributions of the individual pixel values over the stack (i.e. the histograms of the pixel jets) are sparse.
If that's the case, the amount of memory needed to keep all the pixel histograms is much less than 2K x 2K x 64k: you can use a compact hash map to represent each histogram, and update them loading the images one at a time. When all updates are done, you go through your histograms and compute the median of each.
If you have access to the Image Processing Toolbox, Matlab has a set of tool to handle large images called Blockproc
From the docs :
To avoid these problems, you can process large images incrementally: reading, processing, and finally writing the results back to disk, one region at a time. The blockproc function helps you with this process.
I will try my best to provide help (if any), because I don't have an 800-stack TIFF image, nor an 8GB computer, but I want to see if my thinkings can form a solution.
First, 800*2048*2048*8bit = 3.2GB, not including the headers. With your 8GB RAM it should not be too difficult to store it at once; there might be too many programs running and chopping up the contiguous memories. Anyway, let's treat the problem as Matlab can't load it as a whole into the memory.
As Jonas suggests, imread supports loading a TIFF image by index. It also supports a PixelRegion parameter, so you can also consider accessing parts of the image by this parameter if you want to utilize Shai's idea.
I came up with a median algo that doesn't use all the data at the same time; it barely scans through a sequence of un-ordered data, one at each time; but it does keep a memory of 256 counters.
_
data = randi([0,255], 1, 800);
bins = num2cell(zeros(256,1,'uint16'));
for ii = 1:800
bins{data(ii)+1} = bins{data(ii)+1} + 1;
end
% clearvars data
s = cumsum(cell2mat(bins));
if find(s==400)
med = ( find(s==400, 1, 'first') + ...
find(s>400, 1, 'first') ) /2 - 1;
else
med = find(s>400, 1, 'first') - 1;
end
_
It's not very efficient, at least because it uses a for loop. But the benefit is instead of keeping 800 raw data in memory, only 256 counters are kept; but the counters need uint16, so actually they are roughly equivalent to 512 raw data. But if you are confident that for any pixel the same grayscale level won't count for more than 255 times among the 800 samples, you can choose uint8, and hence reduce the memory by half.
The above code is for one pixel. I'm still thinking how to expand it to a 2048x2048 version, such as
for ii = 1:800
img_data = randi([0,255], 2048, 2048);
(do stats stuff)
end
By doing so, for each iteration, you only need these kept in memory:
One frame of image;
A set of counters;
A few supplemental variables, with size comparable to one frame of image.
I use a cell array to store the counters. According to this post, a cell array can be pre-allocated while its elements can still be stored in memory non-contigously. That means the 256 counters (512*2048*2048 bytes) can be stored separately, which is quite reasonable for your 8GB RAM. But obviously my sample code does not make use of it since bins = num2cell(zeros(....

Loading multiple images in MATLAB

Here is the desired workflow:
I want to load 100 images into MATLAB workspace
Run a bunch of my code on the images
Save my output (the output returned by my code is an integer array) in a new array
By the end I should have a data structure storing the output of the code for images 1-100.
How would I go about doing that?
If you know the name of the directory they are in, or if you cd to that directory, then use dir to get the list of image names.
Now it is simply a for loop to load in the images. Store the images in a cell array. For example...
D = dir('*.jpg');
imcell = cell(1,numel(D));
for i = 1:numel(D)
imcell{i} = imread(D(i).name);
end
BEWARE that these 100 images will take up too much memory. For example, a single 1Kx1K image will require 3 megabytes to store, if it is uint8 RGB values. This may not seem like a huge amount.
But then 100 of these images will require 300 MB of RAM. The real issue comes about if your operations on these images turn them into doubles, then they will now take up 2.4 GIGAbytes of memory. This will quickly eat up the amount of RAM you have, especially if you are not using a 64 bit version of MATLAB.
Assuming that your images are named in a sequential way, you could do this:
N = 100
IMAGES = cell(1,N);
FNAMEFMT = 'image_%d.png';
% Load images
for i=1:N
IMAGES{i} = imread(sprintf(FNAMEFMT, i));
end
% Run code
RESULT = cell(1,N);
for i=1:N
RESULT{i} = someImageProcessingFunction(IMAGES{i});
end
The cell array RESULT then contains the output for each image.
Be aware that depending on the size of your images, prefetching the images might make you run out of memory.
As many have said, this can get pretty big. Is there a reason you need ALL of these in memory when you are done? Could you write the individual results out as files when you are done with them such that you never have more than the input and output images in memory at a given time?
IMWRITE would be good to get them out of memory when you are done.