Matlab access vectors from a multi-dimensional array - arrays

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.

Related

How to scale very large numbers such that they could be represented as an array index?

I have a 2D array of size 30*70.
I have 70 columns. My values are very large ranging from 8066220960081 to (some number with same power of 10 as lowerlimit) and I need to plot a scatter plot in an array. How do I index into the array given very large values?
Also, I need to do this in kernel space
Let's take an array long long int A with large values.
A[0] = 393782040
A[1] = 2*393782040
... and so on
A[N] = 8066220960081; where N = 30*70 - 1
We can scale A with a factor or we can shift A by a certain number and scale it again. That's where you can deal with numbers ranging between 0 and 1 or -1 and 1 or x and y. You choose as per your need. Theoretically, this should not make a difference to the scatter plot other than the placement of the axis. However, if your scatter plot is also a representative of the underlying values i.e. the dots are proportional to values; then it is a good idea to be nice to your plotting tool and not flood it with terribly large values that might lead to overflow depending on how the code for plotting is written.
PS: I would assume you know how to flatten a 2d array.
I just ended up doing regular interval calculation between max and min
and then start from min + interval*index to get the number.
index would be the index in array.

Store arrays in index in a nested for loop in matlab

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.

Reshaping an outputted 1 dimensional numpy array into a 2/3 dimensional array

So I'm using an image's pixel data, applying some calculations to it, which gives me a resulting array whose shape is unknown until the calculations are done to it.
I'm having trouble reshaping the outputted array into a 2-dimensional or 3-dimensional array
Here is an example
from PIL import Image
img = Image.open('C:\Users\Amit\Desktop\sample_pic.jpeg').convert("RGB")
pixels =np.array(img)
print(pixels.shape) # (477L, 887L, 3L) PIL seems to switch height and width because original dimensions are 877 x 477
flat = pixels.flatten()
print (flat.shape) # (1269297L,)
filter1= np.array([1,1,0])
pixels2 = np.array([])
for i in range(0, len(flat),2):
pixels2 =np.append(pixels2,np.sum((flat[i:i+3] * filter1)))
The loop at the end is just doing some calculations to the flattened array, and outputting a new array whose shape I don't know till the output
print pixels2.shape
#(634649L,)
So I'm trying to reshape the outputted array into dimensions fit for a picture.
I tried the code
pixels2.reshape(800,-1)
but I got the error
pixels2.reshape(800,-1)
ValueError: total size of new array must be unchanged
same with
pixels.reshape(800,-1,3)
ValueError: total size of new array must be unchanged
I was hoping that adding the (-1) would automatically find the appropriate second dimension but that doesn't seem to be the case. I'm not bound to the number 800 as one of the dimensions but I'm looking for the first two dimensions to be above 300 so (300+, 300+, 3)
Thanks.
Update:
adding one more element to the pixels2 array, makes it a (634650L,) array which is divisible by 3. ( I found it by trial and error)
But finding the other two dimensions involves a lot of trial and error as well it seems. (800, -1, 3) doesn't work.

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 to convert a cell array of 2D matrices into a multidimensional array in MATLAB

In MATLAB, I have a defined cell array C of
size(C) = 1 by 150
Each matrix T of this cell C is of size
size(C{i}) = 8 by 16
I am wondering if there is a way to define a new multidimension (3D) matrix M that is of size 8 by 16 by 150
That is when I write the command size(M) I get 8 by 16 by 150
Thank you! Looking forward for your answers
If I'm understanding your problem correctly, you have a cell array of 150 cells, and each cell element is 8 x 16, and you wish to stack all of these matrices together in the third dimension so you have a 3D matrix of size 8 x 16 x 150.
It's a simple as:
M = cat(3, C{:});
This syntax may look strange, but it's very valid. The command cat performs concatenation of matrices where the first parameter is the dimension you want to concatenate to... so in your case, that's the third dimension, and the parameters after are the matrices you want to concatenate to make the final matrix.
Doing C{:} creates what is known as a comma-separated list. This is equivalent to typing out the following syntax in MATLAB:
C{1}, C{2}, C{3}, ..., C{150}
Therefore, by doing cat(3, C{:});, what you're really doing is:
cat(3, C{1}, C{2}, C{3}, ..., C{150});
As such, you're taking all of the 150 cells and concatenating them all together in the third dimension. However, instead of having to type out 150 individual cell entries, that is encapsulated by creating a comma-separated list via C{:}.

Resources