Large number of Images to stack

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 comentario

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.

Iniciar sesión para comentar.

 Respuesta aceptada

Walter Roberson
Walter Roberson el 13 de Jul. de 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 comentarios

Andrea de Marco
Andrea de Marco el 13 de Jul. de 2021
Thanks for your reply.
Actually yes, I use the same type of images with same size and name in sequence like
2fps_40X00000 2fps_40X00001 2fps_40X00002 and so on, up to 2fps_40X04999.
I'm going to try your code and let you know about the results.
Can I ask you where can I find a guide for basic programmers to OOP in matlab?
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.

Iniciar sesión para comentar.

Más respuestas (1)

Simon Chan
Simon Chan el 13 de Jul. de 2021
Editada: Simon Chan el 13 de Jul. de 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 comentarios

Andrea de Marco
Andrea de Marco el 13 de Jul. de 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 el 13 de Jul. de 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);

Iniciar sesión para comentar.

Categorías

Productos

Versión

R2020b

Preguntada:

el 12 de Jul. de 2021

Comentada:

el 14 de Jul. de 2021

Community Treasure Hunt

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

Start Hunting!

Translated by