Large number of Images to stack

10 views (last 30 days)
Hey there!
I have a large number of images (5000) to analyze by performing fast fourier transforms and other operations.
In particular these images are in another folder with respect to the .m file.
I want them to be saved in a vector (stack), so that calling
stack(i)
I can access the i-th image.
I tried to create a class but I'm not so skilled in OOP and the operation in a bit time consuming. Here is the code:
clc
clear all
imageNumber = 5000;
pixels = 800;
myFolder = 'C:\here i put the path folder containing the images';
files = dir( fullfile( myFolder, '*.bmp' ) );
stack = ImageStack( myFolder, files, imageNumber);
for i = 1:imageNumber
stack(i) = ImageStack( myFolder, files(i), imageNumber );
end
while in a separate file i defined the class:
classdef ImageStack
properties
img
end
methods
function object = ImageStack( myFolder, files, numImg )
for i = 1:numImg
ImNames = files(i).name;
fullImNames = fullfile( myFolder, ImNames );
object.img = imread( fullImNames );
end
end
end
end
and it took 18s.
I'm sure there is a clever way to perform this but I cannot see it. And, since I'm a beginner, I'm pretty sure as well that there is a better way to write this code.
Do you have any advice?
Thanks for your support!
Andrea
  1 Comment
Walter Roberson
Walter Roberson on 13 Jul 2021
Is there a particular reason that you are passing in the number of images, instead of just using size() or length() to figure out how many elements are in the files structure ?
object.img = imread( fullImNames );
You are overwriting all of the img property of object each time through the loop.

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 13 Jul 2021
This code does not assume that the images are rgb or grayscale, but it does enforce that every image after the first is the same size as the first. It assumes that the images are all the same datatype, same as the first file. It preallocates memory for efficiency.
The code enforces that indexing by a single index returns corresponding images. It permits multiple image numbers to be passed in. If multiple images are requested, then the result will be a 4D array.
This version of the code does not support any other kind of indexing than single () index.
There are little tweaks that could be done to improve performance, such as reading in reverse order (reduces the preallocation logic.) And of course the size error checking slows down the code compared to just letting the code fail in ways that make little sense to the user.
classdef ImageStack
properties
img
end
methods
function object = ImageStack( myFolder, files )
sizefail = false;
numImage = numel(files);
for i = 1: numImg
ImNames = files(i).name;
fullImNames = fullfile( myFolder, ImNames );
try
thisimg = imread(fullImNames);
if i == 1
thisimg(:,:,:,2:numImg) = 0;
object.img = thisimg;
else
objsize = size(object.img);
if isequal(size(thisimage), objsize(1:3))
object.img(:,:,:,i) = thisimg;
else
sizefail = true;
%do not error() here because we are in try/catch
break;
end
end
catch ME
error('ImageStack failed to read file "%s"', fullImNames);
end
if sizefail
error('ImageStack file not compatible size, "%s"', fullImNames);
end
end
end
function varargout = subsref(obj,s)
% want them to be saved in a vector (stack), so that calling
% stack(i) I can access the i-th image.
switch s(1).type
case '()'
if length(s) == 1
% Implement obj(indices)
varargout{1} = obj.img(:,:,:,s(1).subs);
else
error('() must be last indexing expression')
end
otherwise
error('Only () indexing is permitted')
end
end
end
end
  3 Comments
Walter Roberson
Walter Roberson on 14 Jul 2021
If you want the user to be able to use
stack(:)
to retrieve all images, or if you want to permit using the end keyword such as
stack(end-2:end)
then you might need to implement the end method as well, in which case it should return size(obj.img,4)
I would suggest to you that it would be more in the matlab style to use {} indexing,
stack{i}
instead of stack(i) . The general style encourages by MATLAB is that when you use () indexing [rather than () for function call] that the datatype of the returned object will be the same as the datatype of the object. For example,
A = {'hello', 'bye'}
A(2)
datatype of A(2) is cell -- the cell {'bye'} is returned, rather than 'bye' directly.
You might, for example, want to prove operations such as crop(stack, rectangle) whose internal operation might be to set active indices into a 4D block of data, and want to be able to process that without having to explicitly extract the data .
To do sharing into a 4D block of data, you might want to create a handle object that represents the 4D block, after which your visible ImageStack might be constructing "views" into that data. A view might include selecting a subset of images, creating another "view". And you might not extract the image contents until you used {} indexing.

Sign in to comment.

More Answers (1)

Simon Chan
Simon Chan on 13 Jul 2021
Edited: Simon Chan on 13 Jul 2021
Do not have 5000 images to try, just try because "cellfun" may be a bit slow.
myFolder = 'C:\here i put the path folder containing the images';
files = dir( fullfile( myFolder, '*.bmp' ) );
fileList = {files.name};
fileread = cellfun(@(x) imread(x), fileList, 'UniformOutput', false);
stack = cell2struct(fileread, 'object', 1);
  2 Comments
Andrea de Marco
Andrea de Marco on 13 Jul 2021
Thanks for your reply.
Unfortunately it does not work for me, maybe I missed something but the fileList does not recognise the path of each image, so when I call "fileread" and "stack" it says the image does not exist.
Simon Chan
Simon Chan on 13 Jul 2021
Add one more line and try again if you wish, because the code only allows the scipt to be run in the directory contains the images.
myFolder = 'C:\here i put the path folder containing the images';
files = dir( fullfile( myFolder, '*.bmp' ) );
fileList = {files.name};
cd(myFolder);
fileread = cellfun(@(x) imread(x), fileList, 'UniformOutput', false);
stack = cell2struct(fileread, 'object', 1);

Sign in to comment.

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!