Question involving nested 'for loops' pertaining to structs and cell arrays

1 view (last 30 days)
Hello,
In this script, I'm intending to create a cell array of contructs with each column corresponding to a contruct (11 total). I then intend on assigning a 'video' field to each of those constructs. For now, each 'video' field only has one video. I then intend on extracting each frame of these videos, and assign them to a 'frames' field corresponding to each trial. I know for a fact that these videos don't have the same number of frames (different video lengths).
Here's the issue. After the script is evaluated, each 'frames' field has 20 frames. While the first frames of each of these 'frames' fields is different, they all share the same last field. I'd appreciate it if someone could help me figure out why this happens.
I've been debugging this for a while now, all to no avail.
Please find the script below:
for n=2:12
t_x{1,n-1}.video=strcat('GN',num2str(n*25),'_1.mov');
end
%extracting frames of the video of each trial
n=size(t_x);
number_of_trials=n(1,2);
for n=1:number_of_trials
v=VideoReader(t_x{1,n}.video);
for m=1:v.NumberOfFrames
frames{1,m}=read(v,m);
t_x{1,n}.frames=frames;
end
end

Accepted Answer

Guillaume
Guillaume on 13 Mar 2019
First a few comments about your code:
I'd recommend you use sprintf rather than strcat + num2str, so:
t_x{n}.video = sprintf('GN%d_1.mov', n*25);
In my opinion, it's more readable.
Secondly, since your cell array is a vector, I'd recommend that you use 1d indexing as I've done above instead of your 2d indexing. (so t_x{n} instead of t_x{1, n}). number_of_trials is then simply:
number_of_trials = numel(t_x);
You don't even need the variable, simply write numel(t_x) each time you used the variable, it's more compact anyway.
Third problem, and actually the cause of your trouble. Whenever you're assigning values to elements of an array in a loop you should make sure that the array already exist and even more importantly, that it is the correct size.
If an array does not exist, before you assign to it in a loop, matlab will grow the array at each step of the loop. That involves creating a new array one size bigger than at the previous step, copying all the elements of the previous array, and deleting the previous array. That's very inefficent. Always preallocate your arrays. For example, for your t_x:
t_x = cell(1, n-1); %preallocate cell array to avoid growing it in the following loop
for n = 2:12
t_x{n}.video = sprintf('GN%d_1.mov', n*25);
end
Now the cause of all your troubles is because you haven't preallocated frames. So, the first time your m loop runs, you're growing your cell array each step up to the number of frames in the video. However, the next time your m loop runs (for the next video), the array is already there and already filled. If the new videos have more frames than the previous one, then fine, you'll overwrite everything and grow it again, but if the array has less frames, then it won't reduce in size. So everything past the size of the current video will still be in your array. Simple way to fix that: reallocate the array before the loop:
for n = 1:numel(t_x)
v=VideoReader(t_x{n}.video);
frames = cell(1, v.NumberOfFrames); %preallocate so it's always empty and the correct size
for m = 1:v.NumberOfFrames
frames{m} = read(v, m);
end
t_x{n}.frames = frames;
end
And of course, the storing in the structure should be after the m loop, when you've finished filling the array.

More Answers (1)

Raghunandan V
Raghunandan V on 13 Mar 2019
Edited: Raghunandan V on 13 Mar 2019
I think the problem is simple. Try deleting the frames using the command clear . I am pretty sure that you are just overwrite particular cells and the cells from previous iteration still exits. The code should now look like this
for n=2:12
t_x{1,n-1}.video=strcat('GN',num2str(n*25),'_1.mov');
end
%extracting frames of the video of each trial
n=size(t_x);
number_of_trials=n(1,2);
for n=1:number_of_trials
v=VideoReader(t_x{1,n}.video);
for m=1:v.NumberOfFrames
frames{1,m}=read(v,m);
end
t_x{1,n}.frames=frames;
clear frames;
end
please check and let me know if the error persists. I have also declared t_x inside other for loop as your code rewirtes everytime you are inside m loop.
  6 Comments

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by