How can I define a 3D matrix in MATLAB?
For example a matrix of size (8 x 4 x 20) or add a 3rd dimension to an existing 2D matrix?
Create a 3D matrix
A = zeros(20, 10, 3); %# Creates a 20x10x3 matrix
Add a 3rd dimension to a matrix
B = zeros(4,4);
C = zeros(size(B,1), size(B,2), 4); %# New matrix with B's size, and 3rd dimension of size 4
C(:,:,1) = B; %# Copy the content of B into C's first set of values
zeros is just one way of making a new matrix. Another could be A(1:20,1:10,1:3) = 0 for a 3D matrix. To confirm the size of your matrices you can run: size(A) which gives 20 10 3.
There is no explicit bound on the number of dimensions a matrix may have.
If you want to define a 3D matrix containing all zeros, you write
A = zeros(8,4,20);
All ones uses ones, all NaN's uses NaN, all false uses false instead of zeros.
If you have an existing 2D matrix, you can assign an element in the "3rd dimension" and the matrix is augmented to contain the new element. All other new matrix elements that have to be added to do that are set to zero.
For example
B = magic(3); %# creates a 3x3 magic square
B(2,1,2) = 1; %# and you have a 3x3x2 array
I use Octave, but Matlab has the same syntax.
Create 3d matrix:
octave:3> m = ones(2,3,2)
m =
ans(:,:,1) =
1 1 1
1 1 1
ans(:,:,2) =
1 1 1
1 1 1
Now, say I have a 2D matrix that I want to expand in a new dimension:
octave:4> Two_D = ones(2,3)
Two_D =
1 1 1
1 1 1
I can expand it by creating a 3D matrix, setting the first 2D in it to my old
(here I have size two of the third dimension):
octave:11> Three_D = zeros(2,3,2)
Three_D =
ans(:,:,1) =
0 0 0
0 0 0
ans(:,:,2) =
0 0 0
0 0 0
octave:12> Three_D(:,:,1) = Two_D
Three_D =
ans(:,:,1) =
1 1 1
1 1 1
ans(:,:,2) =
0 0 0
0 0 0
Related
I want to convert a onehot array to an array of integer values in MATLAB. Given:
Y = 1 0 0
0 1 0
0 1 0
I want to return:
new_y = 1
2
2
You could use find and return only the column indices like so
Y = [1 0 0; 0 1 0; 0 1 0];
[~, new_y] = find(Y); % output: [1; 2; 2] is the col indices of your 1s
Similarly you can return the row indices if your input was the transpose
[new_y, ~] = find(Y); % output: [1; 2; 3] is the row indices of your 1s
The Neural Network toolbox of MATLAB has built-in functions for converting between one-hot vectors and indices: ind2vec() to create a one-hot matrix, and vec2ind() to convert the one-hot matrix back to a vector of indices.
Note: ind2vec returns a sparse matrix. To convert it to a full matrix, you have to use the full() function.
>> Y = full(ind2vec([1, 2, 3]))
Y =
1 0 0
0 1 0
0 0 1
>> new_y = vec2ind(Y)
new_y =
1 2 3
I have managed to code a function for plotting a pascal's triangle in the form of a matrix, but want to make it look like a triangle.
When I ask for a pascal's triangle with four rows, it gives
1 0 0 0
1 1 0 0
1 2 1 0
1 3 3 1
Is there a possible way to make this
1
1 1
1 2 1
1 3 3 1
function x = testfunc(n)
x = eye(n);
x(:, 1) = 1;
for j=3:n
for i = 2 : n - 1
x(j, i) = x(j - 1, i - 1) + x(j - 1, i);
end
end
end
This is my code so far
If you are just interested in the visuals then you can turn it into an cell-array and then use cellfun to loop over all cells and then only display the values that are not 0.
a= mat2cell(x,ones(n,1),n); %turn into cell array
cellfun(#(a)disp(a(a~=0)),a) %loop over cells and print only nonzero elements
If you are interested in saving memory, you can either use cell arrays from the beginning or turn it into a sparse matrix, e.g.
x = sparse(eye(n));
Then only non-zero elements will be represented
This code generates a matrix having 1 in each row and this 1 may be on same locations in rows.
I want for each row the location of 1 must be different i.e 1 must not overlap in columns.
Suppose you want the result matrix to be of size [m, n].
First, randomly select , for each column, the index of the 1
idx = randi(m, 1, n);
Second, allocate an all-zero matrix of size [m,n]
res = zeros(m,n);
Finally, set the corresponding entries to one:
res( sub2ind([m,n], idx, 1:n) ) = 1;
An example result for [3,4] matrix:
res =
0 0 1 0
0 0 0 0
1 1 0 1
I have been having problem with identifying two maximum values' position in 3D matrix (MATLAB). Say I have matrix A output as follows:
A(:,:,1) =
5 3 5
0 1 0
A(:,:,2) =
0 2 0
8 0 8
A(:,:,3) =
3 0 0
0 7 7
A(:,:,4) =
6 6 0
4 0 0
For the first A(:,:,1), I want to identify that the first row have the highest value (A=5). But I need the two index position, which in this case, 1 and 3. And this is the same as the other A(:,:,:).
I have searched through SO but since I am bad in MATLAB, I couldn't find way to work this through.
Please do help me on this. It would be better if I don't need to use for loop to get the desired output.
Shot #1 Finding the indices for maximum values across each 3D slice -
%// Reshape A into a 2D matrix
A_2d = reshape(A,[],size(A,3))
%// Find linear indices of maximum numbers for each 3D slice
idx = find(reshape(bsxfun(#eq,A_2d,max(A_2d,[],1)),size(A)))
%// Convert those linear indices to dim1, dim2,dim3 indices and
%// present the final output as a Nx3 array
[dim1_idx,dim2_idx,dim3_idx] = ind2sub(size(A),idx)
out_idx_triplet = [dim1_idx dim2_idx dim3_idx]
Sample run -
>> A
A(:,:,1) =
5 3 5
0 1 0
A(:,:,2) =
0 2 0
8 0 8
A(:,:,3) =
3 0 0
0 7 7
A(:,:,4) =
6 6 0
4 0 0
out_idx_triplet =
1 1 1
1 3 1
2 1 2
2 3 2
2 2 3
2 3 3
1 1 4
1 2 4
out_idx_triplet(:,2) is what you are looking for!
Shot #2 Finding the indices for highest two numbers across each 3D slice -
%// Get size of A
[m,n,r] = size(A)
%// Reshape A into a 2D matrix
A_2d = reshape(A,[],r)
%// Find linear indices of highest two numbers for each 3D slice
[~,sorted_idx] = sort(A_2d,1,'descend')
idx = bsxfun(#plus,sorted_idx(1:2,:),[0:r-1]*m*n)
%// Convert those linear indices to dim1, dim2,dim3 indices
[dim1_idx,dim2_idx,dim3_idx] = ind2sub(size(A),idx(:))
%// Present the final output as a Nx3 array
out_idx_triplet = [dim1_idx dim2_idx dim3_idx]
out_idx_triplet(:,2) is what you are looking for!
The following code gives you the column and row of the respective maximum.
The first step will obtain the maximum of each sub-matrix containing the first and second dimension. Since max works per default with the first dimension, the matrix is reshaped to combine the original first and second dimension.
max_vals = max(reshape(A,size(A,1)*size(A,2),size(A,3)));
max_vals =
5 8 7 6
In the second step, the index of elements equal to the respective max_vals of each sub-matrix is obtained using arrayfun over the third dimension. Since the output of arrayfun are cells, cell2mat is used to transform the output into a matrix. As a last step, the linear index from find is transformed into sub-indices by ind2sub.
[i,j] = ind2sub(size(A(:,:,1)),cell2mat(arrayfun(#(i)find(A(:,:,i)==max_vals(i)),1:size(A,3),'UniformOutput',false)))
i =
1 2 2 1
1 2 2 1
j =
1 1 2 1
3 3 3 2
Hence, the values in j are the ones you want to have.
Suppose I have matrix, where each cell of this matrix describes a location (e.g. a bin of a histogram) in a two dimensional space. Lets say, some of these cells contain a '1' and some a '2', indicating where object number 1 and 2 are located, respectively.
I now want to find those cells that describe the "touching points" between the two objects. How do I do that efficiently?
Here is a naive solution:
X = locations of object number 1 (x,y)
Y = locations of object number 2 (x,y)
distances = pdist2(X,Y,'cityblock');
Locations (x,y) and (u,v) touch, iff the respective entry in distances is 1. I believe that should work, however does not seem very clever and efficient.
Does anyone have a better solution? :)
Thank you!
Use morphological operations.
Let M be your matrix with zeros (no object) ones and twos indicating the locations of different objects.
M1 = M == 1; % create a logical mask of the first object
M2 = M == 2; % logical mask of second object
dM1 = imdilate( M1, [0 1 0; 1 1 1; 0 1 0] ); % "expand" the mask to the neighboring pixels
[touchesY touchesX] =...
find( dM1 & M2 ); % locations where the expansion of first object overlap with second one
Code
%%// Label matrix
L = [
0 0 2 0 0;
2 2 2 1 1;
2 2 1 1 0
0 1 1 1 1]
[X_row,X_col] = find(L==1);
[Y_row,Y_col] = find(L==2);
X = [X_row X_col];
Y = [Y_row Y_col];
%%// You code works till this point to get X and Y
%%// Peform subtractions so that later on could be used to detect
%%// where Y has any index that touches X
%%// Subtract all Y from all X. This can be done by getting one
%%//of them and in this case Y into the third dimension and then subtracting
%%// from all X using bsxfun. The output would be used to index into Y.
Y_touch = abs(bsxfun(#minus,X,permute(Y,[3 2 1])));
%%// Perform similar subtractions, but this time subtracting all X from Y
%%// by putting X into the third dimension. The idea this time is to index
%%// into X.
X_touch = abs(bsxfun(#minus,Y,permute(X,[3 2 1]))); %%// for X too
%%// Find all touching indices for X, which would be [1 1] from X_touch.
%%// Thus, their row-sum would be 2, which can then detected and using `all`
%%// command. The output from that can be "squeezed" into a 2D matrix using
%%// `squeeze` command and then the touching indices would be any `ones`
%%// columnwise.
ind_X = any(squeeze(all(X_touch==1,2)),1)
%%// Similarly for Y
ind_Y = any(squeeze(all(Y_touch==1,2)),1)
%%// Get the touching locations for X and Y
touching_loc = [X(ind_X,:) ; Y(ind_Y,:)]
%%// To verify, let us make the touching indices 10
L(sub2ind(size(L),touching_loc(:,1),touching_loc(:,2)))=10
Output
L =
0 0 2 0 0
2 2 2 1 1
2 2 1 1 0
0 1 1 1 1
L =
0 0 10 0 0
2 10 10 10 1
10 10 10 10 0
0 10 10 1 1