Store arrays in index in a nested for loop in matlab - arrays

I have 50 images, stored as arrays in a 1x50 cell index called AllImages. Basically I want to make a new index with arrays that contain elements in the same position of the 50 arrays.
I want to see how each pixel in the same spot of the 50 images changes in the 50 images.
Theoretically, I would get an index of arrays with 50 elements each, because I want the first element of each of the 50 arrays in its own array, the second element of each of the 50 arrays in its own array, so on and so forth.
So far, here is my code:
for m = 1:5000 % number of pixels per image
for n = 1:50 % for the 50 images, all the same size
pixels(n) = allImages{n}(m)
end
allpixels{m} = pixels
end
I end up getting a 1x50 cell index for allpixels, even though I want 5000. I'm not sure what I did wrong.
Is there an easier way to do this or fix the code? Thanks so much!

are the images of the same size?
in that case first change them to a matrix using cell2mat
[i,j] = size(allImages{1})
n = numel(allImages)
allImages = cell2mat(allImages);
allImages = reshape(allImages,[i,j,n]);
because now you can just select your pixel. for example:
pixel = squeeze(allImages(1,1,:))
To get them all in a new cell you could permute and reshape your matrix
allImages = permute(allImages ,[3 1 2]);
allImages = reshape(allImages ,[n,i*j]);
pixels = mat2cell(allImages,n,ones([1,i*j]));
But for most mathematical operations it is easier to just keep them as one matrix.
As two rules of thumb in matlab you want to use matrices as much as possible, and avoid for-loops.

Related

How do i store sequence of 2D matrices into a 3D array in Matlab?

I have these series of 2D CT images and i have been able to read them into Matlab using "imread". The issue however is that i need the image read-in as a single 3D matrix rather than stack of several 2D matrices. I have been made aware that it is possible to store the number of 2D layers as the 3rd dimension, but i have no idea how to do this as i am still a learner.
The code i have for reading in the 2D stack are as follows:
a = dir('*.tif');
for i = 1: numel(a)
b = imread(a(i).name); %read in the image
b_threshold = graythresh(b); %apply threshold
b_binary = im2bw(b, b_threshold); %binarize image
[m, n] = size(b); %compute the size of the matrix
phi(i) = ((m*n) - sum((b_binary(:))))/(m*n); %compute the fraction of pore pixels in the image
phi(:,i) = phi(i); %store each of the above result
end
I have added just a single image although several of these are needed. Nevertheless, one can easily duplicate the image to create a stack of 2D images. For the code to work, it is however important to rename them in a numerical order.pore_image
Any help/suggestions/ideas is welcomed. Thanks!
You can simply assign along the third dimension using i as your index
stack_of_images(:,:,i) = b_binary
Well, the first advice is try to don't use the variable i and j in matlab because they are reserved (have a look here and here).
After it depends on along which dimension you want to store the 2D images:
if you want to store the images along the first dimension just use this code:
a = dir('*.tif');
for ii = 1: numel(a)
b = imread(a(ii).name); %read in the image
b_threshold = graythresh(b); %apply threshold
b_binary = im2bw(b, b_threshold); %binarize image
[m, n] = size(b); %compute the size of the matrix
phi(ii) = ((m*n) - sum((b_binary(:))))/(m*n); %compute the fraction of pore pixels in the image
phi(:,ii) = phi(ii); %store each of the above result
matrix_3D_images(ii,:,:)=b_binary; %adding a new layer
end
If you want to store the images along other dimensions it is easy to do: just change the posizion of the "pointer" ii:
matrix_3D_images(:,ii,:)=b_binary; or
matrix_3D_images(:,:,ii)=b_binary;

How do I create an array in matlab consisting of multiple 3d imagedata arrays

I have 15 images that I am reading using imagedata = imread('imagename.jpg') its size is always 320 by 320 by 3
How do I put the data in an array (using a for for loop) such that when I access the first element of the new array I get the RGB data of the first image I input?
You should probably use cell
imCell = {};
for i = 1 :15
imCell{i} = imread(num2str(something));
end
And you could easily have access,
for j = 1 : 15
subplot(5,3,j);
imshow(imCell{j});
end
imCell is a cell with size 1x15. However imCell{i} is an arrey with size 320x320x3.
Using cell will allow you to even save arrays of different sizes in it.
Since all images have the same size, it may be more efficient to use a 4D array than a cell array:
imArray = NaN(320,320,3,15);
for n = 1:15
imArray(:,:,:,n) = imread(filename); %// filename should probably change
end
You can then access the first image as imArray(:,:,:,1), etc.

Turning an array in to a matrix in MATLAB

I need to turn a large array into a matrix in the following way: to take the first m entries of the array and make that the 1st row of the matrix.
For example: if I had an array that was 100 entries long, the corresponding matrix would be 10 rows and each row would be 10 entries of the array with the order preserved.
I've tried the following code:
rows = 10
row_length = 10
a = randi(1,100);
x = zeros(rows,row_length)
for i=1:rows
x(i) = a(i:i+row_length)
end
but with no luck. I'm stuck on how to slide the window along by row_length so that i will start from row_length+1 in the second (and subsequent) iterations of the loop.
The best way to do it is to use Matlab's reshape function:
reshape(a,row_length,[]).'
It will reshape by first assigning down the columns which is why I transpose at the end (i.e. .')
However just for the sake of your learning, this is how you could have done it your way:
rows = 10
row_length = 10
a = rand(1,100)
x = zeros(rows,row_length)
for i=1:row_length:rows*row_length %// use two colons here, the number between them is the step size
x(i:i+row_length-1) = a(i:i+row_length-1) %// You need to assign to 10 elements on the left hand side as well!
end

Matlab access vectors from a multi-dimensional array

I have a 4D matrix of size 300x200x3x20 where 300x200 is the size of one video frame, 3 is the number of channels (Red-Green-Blue channels) and 20 is the number of frames.
I want to extract all the color vectors from this matrix and store them in a 2D array of size 3x1,200,000 (300 x 200 x 20 = 1,200,000) where each row represents a component of the RGB color space and each column contain the RGB values of one pixel in the original matrix.
Besides, I want to carry out pixel-wise operations on this data such as extracting visual features but I cannot find a way to effectively access vectors along the third dimension.
How could I efficiently do these, possible without using loops?
Try this code -
IN = your_4D_data;
OUT = reshape(permute(IN,[3 1 2 4]),3,numel(IN)/3);
help reshape says:
B = reshape(A,m,n,p,...) or B = reshape(A,[m n p ...]) returns an n-dimensional array with the same elements as A but reshaped to have the size m-by-n-by-p-by-.... The product of the specified dimensions, m*n*p*..., must be the same as numel(A).
is this what you are looking for?
also, you can adress pixels like this: Matrix(i,j,:,k) which gives you the 3 colorchanels of pixel i,j in frame k.

Reshape multidimensional N-D array in matlab correctly without distorting data

So I have found many questions and answers about this on SO already and I think my approach should work as it is not very complicated. However I have tried every position for my time dimension possible and for me right now reshaping and keeping one dimension the same does not work:
I have a 400x400x20x24 array in which 400x400 is an image and 24 is a number of images at 20 times. I have to do an operation on each voxel and to make this quicker I want to reshape my array into a 2D matrix where one dimension is 20 and only has the time values. I know (or thought I knew) how to do this and have tried every possible order of dimensions prior to reshaping, but none result in my old data:
array1 = rand(400,400,20,24);
This is how one voxel ove time looks
plot([1:20], squeeze(array1(200,200,:,12)))
twoD1 = reshape(array1, [], 20);
size(twoD)
ans = 3840000 20
so far so good until I plot a pixel and its time values
plot([1:20], squeeze(twoD1(962400,:)))
Hmmm wait a minute the dimension of size 20 is no longer the original dimension of size 20, maybe rearranging my original dimensions will affect this.
array2 = permute(array1, [3 1 2 4]);
array3 = permute(array1, [1 3 2 4]);
array4 = permute(array1, [1 2 4 3]);
twoD2 = reshape(array2, [], 20);
twoD3 = reshape(array3, [], 20);
twoD4 = reshape(array4, [], 20);
plot([1:20], squeeze(twoD2(962400,:)))
plot([1:20], squeeze(twoD3(962400,:)))
plot([1:20], squeeze(twoD4(962400,:)))
I dont understand why it doesnt work. Ive looked at these questions, but they seem to suggest I do it right, right?
Reshaping a matrix in matlab
How do I resize a matrix in MATLAB?
Reshaping a 3 dimensional array to 2 dimensions
Change a multidimensional vector to two dimensional vector matlab
MATLAB reshape matrix converting indices to row index
How to reshape matlab matrices for this example?
Reshape matrix from 3d to 2d keeping rows
Reshape 3d matrix to 2d matrix
Of course I also read:
http://www.mathworks.nl/help/matlab/ref/reshape.html
http://www.mathworks.nl/help/matlab/ref/permute.html
All to no avail. Someone please help me? Thank you!
The first issue to note is that twoD1 = reshape(array1, [], 20); does not do what you want since array1 is 400x400x20x24. The reshape only works as intended if the last dimension is 20:
twoD = reshape(permute(array1,[1 2 4 3]),[],20);
That gives you all pixels, all 24 images by 20 time points. If you want to plot the 20 time points for pixel (200,200) for image 12, do the following:
[numRows,numCols,numTimes,numSlices] = size(array1);
imgInd = 12; pixRow = 200; pixCol = 200;
ind = sub2ind([numRows numCols numSlices],pixRow,pixCol,imgInd)
% ind = pixRow + numRows*(pixCol-1) + numRows*numCols*(imgInd-1)
plot(1:size(twoD,2), twoD(ind,:))
EDIT: Sorry, I computed ind wrong first. Works now.

Resources