How do I create a uninstantiated array of images in MATLAB - matlab

I'm looking for a way to store a set of images in my MATLAB function. Is there a way to set aside space for n images ahead of time and initialize them later?
I tried doing something like this:
array_of_images = zeros(1,5); % array of 5 images
but when I try to initialize:
array_of_images(1,1) = imread('image_01.jpg');
MATLAB reports Assignment has more non-singleton rhs dimensions than non-singleton subscripts, so I am looking for a way to do something equivalent.

Check the output of imread('image_01.jpg'), this propably something like 1200x800x3.
Then you have to preallocate ar=zeros(1200,800,3,5) and assign with ar(:,:,:,index)=imread('image.jpg')

Related

Applying (with as few loops as possible) a function to given elements/voxels (x,y,z) taken from subfields of multiple structs (nifti's) in MATLAB?

I have a dataset of n nifti (.nii) images. Ideally, I'd like to be able to get the value of the same voxel/element from each image, and apply a function to the n data points. I'd like to do this for each voxel/element across the whole image, so that I can reconvert the result back into .nii format.
I've used the Tools for NIfTI and ANALYZE image toolbox to load my images:
data(1)=load_nii('C:\file1.nii');
data(2)=load_nii('C:\file2.nii');
...
data(n)=load_nii('C:\filen.nii');
From which I obtain a struct object with each sub-field containing one loaded nifti. Each of these has a subfield 'img' corresponding to the image data I want to work on. The problem comes from trying to select a given xyz within each img field of data(1) to data(n). As I discovered, it isn't possible to select in this way:
data(:).img(x,y,z)
or
data(1:n).img(x,y,z)
because matlab doesn't support it. The contents of the first brackets have to be scalar for the call to work. The solution from googling around seems to be a loop that creates a temporary variable:
for z = 1:nz
for x = 1:nx
for y = 1:ny
for i=1:n;
points(i)=data(i).img(x,y,z);
end
[p1(x,y,z,:),~,p2(x,y,z)] = fit_data(a,points,b);
end
end
end
which works, but takes too long (several days) for a single set of images given the size of nx, ny, nz (several hundred each).
I've been looking for a solution to speed up the code, which I believe depends on removing those loops by vectorisation, preselecting the img fields (via getfield ?)and concatenating them, and applying something like arrayfun/cellfun/structfun, but i'm frankly a bit lost on how to do it. I can only think of ways to pre-select which themselves require loops, which seems to defeat the purpose of the exercise (though a solution with fewer loops, or fewer nested loops at least, might do it), or fun into the same problem that calls like data(:).img(x,y,z) dont work. googling around again is throwing up ways to select and concatenate fields within a struct, or a given field across multiple structs. But I can't find anything for my problem: select an element from a non-scalar sub-field in a sub-struct of a struct object (with the minimum of loops). Finally I need the output to be in the form of a matrix that the toolbox above can turn back into a nifti.
Any and all suggestions, clues, hints and help greatly appreciated!
You can concatenate images as a 4D array and use linear indexes to speed up calculations:
img = cat(4,data.img);
p1 = zeros(nx,ny,nz,n);
p2 = zeros(nx,ny,nz);
sz = ny*nx*nz;
for k = 1 : sz
points = img(k:sz:end);
[p1(k:sz:end),~,p2(k)] = fit_data(a,points,b);
end

MATLAB struct conversion error

I have 5 different structure and I want to calculate some variables for all of them. To do that, I wrote the following code:
for i=1:5
[StructureI(i), ReqTab(i), jt(i), B(i)]=Checkall(E);
end
The values StructureI, ReqTab, jt and B are calculated in another function and they are
StructureI= 1X4 matrix,
ReqTab= 4X2 matrix,
jt=2x1 matrix,
B=4x4 matrix
When I run the code it calculates all the varibles in the function Checkall. However, when it turns to the parent code, it gives and error "Conversion to double from struct is not possible."
How can I solve this problem?
Thanks in advance.
You cannot assign directly from double to struct, instead you have to write the specific field field_name to assign to:
[StructureI(i).field_name, ReqTab(i), jt(i), B(i)] = Checkall(E);
If all of these variables (i.e. also ReqTab, jt, B) are structures, then off course you need to specify the field in each one of them, using the . notation.
However, as mentioned in the comments, all iterations of your loop are just the same (no usage of i within it), so why do you need this loop? just to make 5 copies?

Splitting an audio file in Matlab

I'm trying to split an audio file into 30 millisecond disjoint intervals using Matlab. I have the following code at the moment:
clear all
close all
% load the audio file and get its sampling rate
[y, fs] = audioread('JFK_ES156.wav');
for m = 1 : 6000
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs) ((m+1)*(0.03)*fs)]);
end
But the problem is that I get the following error:
In an assignment A(I) = B, the number of elements in B and I
must be the same.
Error in splitting (line 12)
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs)
((m+1)*(0.03)*fs)]);
I don't see why there's a mismatch in the number of elements in B and I and how to solve this. How can I get past this error? Or is there just an easier way to split the audio file (maybe another function I don't know about or something)?
I think the easiest way to split audio is to just load it and use the vec2mat function. so you would have something like this;
[X,Fs] = audioread('JFK_ES156.wav');
%Calculate how many samples you need to capture 30ms of audio
matSize = Fs*0.3;
%Pay attention to that apostrophe. Makes sure samples are stored in columns
%rather than rows.
output = vec2mat(x,matSize)';
%You can now have your audio split up into the different columns of your matrix.
%You can call them by using the column calling command for matrices.
%Plot first 30ms of audio
plot(output(:,1));
%You can join the audio back together using this command.
output = output(:);
Hope that helps. Another good thing about this method is that it keeps all your data in one place!
Edit : One thing I thought of, you may get a problem with this depending on your vector size. But I think vec2mat actually zeroPads your vector. Not a big thing, but if you're moving back and forth between the two, then it might be a good idea to have another variable that stores the original length of your signal.
You should just use the variable y and reshape it to form your split audio. For example,
chunk_size = fs*0.03;
y_chunks = reshape(y, chunk_size, 6000);
That will give you a matrix with each column a 30 ms chunk. This code will also be faster than reading small segments from file in a loop.
As hiandbaii suggested you could also use cell array. Make sure you clear your existing variables before that. Not clearing the array t is probably the reason you got the error "Cell contents assignment to a non-cell array object."
Your original error is because you cannot assign a vector with scalar indexing. That is, 'm' is a scalar, but your audioread call is returning a vector. This is what the error says about mismatch in size of I and B. You could also fix that by making t a 2-D array and use an assignment like
[t(m,:), fs] =
It appears that each 30 ms segment is not equal to one sample. That would be the only case where your code works. i.e. 0.03*fs != 1.
You could try using cells instead.. i.e. replace t(m) with t{m}

Zero padding in Matlab

I have image, and I want to do up sampling. First of all I need to plug zeros between pixels such that [1,2,3] transforms to [1,0,2,0,3]. Can anyone tell me how to do it without using paddarray and without using for loops?
Thank you in advance!
Something like this?:
B=zeros(size(img)*2);
B(1:2:end,1:2:end)=img;
However there are ways of up-sampling in matlab without having the need of doing it by hand, for example interp2
You could also make use of MATLAB's way of dynamically allocating variables if you don't specify a number for an index into the array. By omitting indexing into certain locations in your array, MATLAB will fill in these values with zeroes by default. As such:
B(1:2:5) = 1:3
B =
1 0 2 0 3
V = [1,2,3];
padded(numel(V)*2) = 0;
padded(1:2:end) = V
And then just deal with the trailing zero if numel(V) was odd
There is a function upsample that does exactly this from Octave-Forge -- see docs on upsample.
Or you can look at the source of upsample to see what implements it. Are you opposed to using a package or a function?

what function or loop do I have to use to average the matrix?

I want to find the average of all the matrix:
Data=(Data{1}+......+Data{n})/n)
where Data{n} is a matrix of m*n..
Thank you sooo much
First, you convert your cell array into a 3D array, then you can take the average, like this:
tmp = cat(3,Data{:}); %# catenates the data, so that it becomes a m*n*z (or m*1*n)
averageData = mean(tmp,3); %# takes average along 3rd dimension
Note: if you get memory problems this way, and if you don't need to keep the variable Data around, you can replace tmp with Data and all will work fine.
Alternatively, if Data is simply a m*n numeric array
averageData = mean(Data,2);
If your cell array is really big, you might want to keep away from the above solution because of its memory usage. I'd then suggest using the utility mtimesx which is available from Matlab Central, here.
N = length(Data);
b = cell(N,1);
b(:) = {1};
averageData = mtimesx(Data,b)/N;
In the above example, I assumed that Data is a line-shaped cell array. I have never used personally mtimesx, this solution comes from there, where timing issues are also discussed.
Hope this helps.
A.