0

I have a program trying to read in around 30 .jpg images (will be able to go well above that) in matlab, and I was wondering what the most efficient way to read in files was?

Here is my current code:

for i = 1:num_images
    image_arr(i,:,:) = rgb2gray(imread(strcat(fin_path, '\' , image_locations(i).name)));
        %Reads in i'th .jpg image, converts it to grayscale,
        %   then moves that into the i'th member of image_array
end

But this takes a significant amount of time to perform. Any suggestions to make this faster?

Specifically, I know that MATLAB really doesn't like for loops, so is there a way to do this without one? Such as with the ':' symbol?

NGXII
  • 407
  • 2
  • 9
  • 18
  • Could you save the images as bitmaps? Those might be faster to read in than jpgs, although they will be bigger on disk and it will take some time up front to convert them. – Andrew Jul 21 '14 at 22:44
  • The camera being used with this code saves files in .JPG files. Converting to bitmaps would be an unnecessary step... – NGXII Jul 21 '14 at 23:53
  • Ok, was hoping they would be static. – Andrew Jul 22 '14 at 00:01
  • please consider using [`fullfile`](http://www.mathworks.com/help/matlab/ref/fullfile.html) command to create file names and paths: it is platform independent. – Shai Jul 22 '14 at 08:18
  • 1
    How is this question a duplicate concerning pre-allocating space? The answer to this question is that reading images into cells is faster than into arrays. Please reconsider. – EJG89 Jul 22 '14 at 08:23

2 Answers2

2

I would try with a cell array, each of its elements being an image (a 2-d matrix).

images{num_images} = [];  % alocate memory for the cell array header
for i = 1:num_images
    images{i} = rgb2gray(imread(strcat(fin_path, '\' , image_locations(i).name)));
    % Reads in i'th .jpg image, converts it to grayscale,
end

The problem I would expect using a 3D array (instead of a cell array) are:

  • the memory needs to be contiguous: if the memory allocated is large enough for only 6 images, when you try loading the 7th, Matlab will have to reserve a larger space in memory, then copy the 6 images that are already in memory to this new (larger) memory space, before it can continue to load the 7th. This might happen several times before you finish loading your 30 images. Cell arrays however don't have this problem as each image will have its own memory allocated independently.
  • some JPEG might be smaller than others, but 3D arrays will only work if all JPEG have the same shape (it might not be your case right now, but it looks like you want your program to work for any JPEG).
nicolas
  • 3,120
  • 2
  • 15
  • 17
2

The most efficient way is of course always dependent on the situation. What resources are available, how large are the data sets, are all the images the same size, etc. etc. Your remark about using a camera suggests that all images are of the same size. To test the performance of some methods I timed the performance using tic toc for four situations. For the purpose of testing I used 44 jpeg images (1080x1920) names 1.jpg to 44.jpg.

Situation 1. Your situation, using an array without memory pre-allocation:

Elapsed time is 5.466675 seconds.

clear all
num_images=44;
tic
for ii = 1:num_images
    filename = strcat(num2str(ii),'.jpg');
    temp_img = imread(filename);
    image_arr(ii,:,:) = rgb2gray(temp_img);
    clear temp_img;
    %Reads in i'th .jpg image, converts it to grayscale,
    %   then moves that into the i'th member of image_array
end
toc

Situation 2 Situation described by seb, using cell with memory pre-allocation:

Elapsed time is 2.388686 seconds.

clear all
num_images=44;
tic
images{num_images} = [];  % alocate memory for the cell array header
for ii = 1:num_images
    images{ii} = rgb2gray(imread(strcat(num2str(ii),'.jpg')));
    % Reads in i'th .jpg image, converts it to grayscale,
end
toc

Situation 3 Since all the pictures have the same dimensions create an array of size [num_images,1080,1920], memory pre-allocation should help performance.

Elapsed time is 3.617463 seconds.

clear all
num_images=44;
tic
images = zeros(num_images,1080,1920);  % pre-alocate memory for array
for ii = 1:num_images
    images(ii,:,:) = rgb2gray(imread(strcat(num2str(ii),'.jpg')));
    % Reads in i'th .jpg image, converts it to grayscale,
end
toc

Situation 4 The same as situation 3 but now pre-allocating space slightly different: [1080,1920,num_images].

Elapsed time is 2.826266 seconds.

clear all
num_images=44;
tic
images = zeros(num_images,1080,1920);  % pre-alocate memory for array
for ii = 1:num_images
    images(ii,:,:) = rgb2gray(imread(strcat(num2str(ii),'.jpg')));
    % Reads in i'th .jpg image, converts it to grayscale,
end
toc

Conclusion

The conclusion is that cells are the fastest when handling full hd images, also it should be noted that it appears that when pre-allocating space the iterator should be used as third index instead of the first.

Note I you wonder about the performance of the code use the command profile viewer and run your code from there to see potential bottlenecks. Make sure you split commands over several lines since evaluation performance is reported per line.

EJG89
  • 1,189
  • 7
  • 17