Element wise creation of matrix - matlab

How can we create element wise matrix from 4 matrices without using loops. For ex.we have
A=[a1 a2;a3 a4] B=[b1 b2;b3 b4] C=[c1 c2;c3 c4] D=[d1 d2;d3 d4]
We need to create a cell array such that each array location contains values such as
[a1 b1;c1 d1] %Matrix at First location
[a2 b2;c2 d2] %Matrix at Second location
and so on so that all the elements are covered.
Thanks in advance.

The short version:
newMatrix= permute(reshape([A(:),B(:),C(:),D(:)]',2,2,4),[2,1,3]);
The matrices that you need are in newMatrix(:,:,idx)
Lets break it down:
temp1 = [A(:),B(:),C(:),D(:)]';
temp1 is a new matrix that contains all of the other matrices values in every row and the values you need for the new matrices (that you wanted to create) in every column.
temp2 = reshape([A(:),B(:),C(:),D(:)]',2,2,4);
temp2 takes temp1 and permutates it. Basically it changes the matrix dimensions from a 4X4 to 2X2X4. if you look at each "layer" (along the 3rd dimension) of this 3D matrix i.e. every 2X2 it contains the information you wanted only transposed. So all thats left to do is transpose it , here ' doesnt work since its a 3D matrix so we use
newMatrix = permute(temp2,[2,1,3]);
This means that the third dimensions stais the same but you switch between dimensions 1,2.

Related

How to loop through each value in a 3D matrix?

I have a matrix, 10x10x40, that is storing information of an image through time, where the the rows and columns indicate the spectral value at a specific point, and the third dimension is time. So in other words, a 10x10 image at 40 points in time. I would like to loop through each row, column and view that pixel history (1,1,:), (1,2,:)....(10,10,:).
Here's what I'm doing now:
val = [];
for i = 1:10;
for j = 1:10;
for k = 1:length(timevector)
val(k) = my_matrix(i,j,k);
end
end
end
Since I want to iterate through each pixel in time and then save that data, what would be the best way to store the new value/time vectors? I want to end up with 100 pixel history vectors, right now I end with one, and it's because val is written over within the loop. I know it's not advised to create variables within a loop, so what is the best alternative? Should I look into storing the output as a structure? I've been staring at this and I have over-complicated everything.
Depending on the structure you prefer, you can also use matlab's functions reshape and num2cell to get the output in the following form:
Alternative 1:
A = reshape(A,[],10);
This will return a matrix (100x40) where each row is a pixel's history.
Alternative 2:
A = num2cell( reshape(A,[],40), 2)
This will return a cell array (100x1) where each cell contains a vector (40x1) with each pixel's history.
Alternative 3:
A = squeeze( num2cell( permute(A, [3,1,2]), 1) );
This will return a cell array (10x10) where each cell contains a vector (40x1) with each pixel's history.
Depending on what you want to do with it, you don't need to store them in separate vectors. You can just get one of these pixel history vectors, like so,
pixel_history = squeeze(my_matrix(1,1,:));
squeeze will remove the singleton dimension from the slice, and make it into a 40-by-1 vector, instead of a 1-by-1-by-40 matrix.
To make the time dimension the first matrix dimension, you could also permute the matrix,
permute(my_matrix, [3 2 1]);
This will swap the 3rd and 1st dimensions, making the 1st dimension time.

Matrix Multiplication Issue - Matlab

In an attempt to create my own covariance function in MatLab I need to perform matrix multiplication on a row to create a matrix.
Given a matrix D where
D = [-2.2769 0.8746
0.6690 -0.4720
-1.0030 -0.9188
2.6111 0.5162]
Now for each row I need manufacture a matrix. For example the first row R = [-2.2770, 0.8746] I would want the matrix M to be returned where M = [5.1847, -1.9915; -1.9915, 0.7649].
Below is what I have written so far. I am asking for some advice to explain how to use matrix multiplication on a rows to produce matrices?
% Find matrices using matrix multiplication
for i=1:size(D, 1)
P1 = (D(i,:))
P2 = transpose(P1)
M = P1*P2
end
You are trying to compute the outer product of each row with itself stored as individual slices in a 3D matrix.
Your code almost works. What you're doing instead is computing the inner product or the dot product of each row with itself. As such it'll give you a single number instead of a matrix. You need to change the transpose operation so that it's done on P1 not P2 and P2 will now simply be P1. Also you are overwriting the matrix M at each iteration. I'm assuming you'd like to store these as individual slices in a 3D matrix. To do this, allocate a 3D matrix where each 2D slice has an equal number of rows and columns which is the number of columns in D while the total number of slices is equal to the total number of rows in D. Then just index into each slice and place the result accordingly:
M = zeros(size(D,2), size(D,2), size(D,1));
% Find matrices using matrix multiplication
for ii=1:size(D, 1)
P = D(ii,:);
M(:,:,ii) = P.'*P;
end
We get:
>> M
M(:,:,1) =
5.18427361 -1.99137674
-1.99137674 0.76492516
M(:,:,2) =
0.447561 -0.315768
-0.315768 0.222784
M(:,:,3) =
1.006009 0.9215564
0.9215564 0.84419344
M(:,:,4) =
6.81784321 1.34784982
1.34784982 0.26646244
Depending on your taste, I would recommend using bsxfun to help you perform the same operation but perhaps doing it faster:
M = bsxfun(#times, permute(D, [2 3 1]), permute(D, [3 2 1]));
In fact, this solution is related to a similar question I asked in the past: Efficiently compute a 3D matrix of outer products - MATLAB. The only difference is that the question wanted to find the outer product of columns instead of the rows.
The way the code works is that we shift the dimensions with permute of D so that we get two matrices of the sizes 2 x 1 x 4 and 1 x 2 x 4. By performing bsxfun and specifying the times function, this allows you to efficiently compute the matrix of outer products per slice simultaneously.

Subtract vector from 3d array

Say if I have a 3d array:
lat = 45:49;
lon = -116:-110;
b = rand(5,7,12);
where the first dimension represents the latitude, the second dimension represents the longitude and the third row represents the data. I aim to plot this 3d data on a map using the mapping toolbox. But, before doing this, I would like to find the difference between the data in 'b' and the following vector:
vals = [2.3,5,6.8,5.4,3.3,12,1.5,4.6,9.8,82,3.3,1];
Specifically, for each spatial data point that I have in my mapped data I owuld like to calculate the mean absolute error between that vector and the data at each point in b. If these were two normal vectors I would use:
mae = mean(abs(bv - vals))
but I'm not sure how this can be done with the 3d array. Eventually, I aim to map this mean absolute error to see how it varies spatially. Can anyone suggest how this can be done in matlab?
Use bsxfun for this (it's more efficient than repmat):
V = permute(vals, [1,3,2]) %// Make sure that the dimesions 'align' correctly. i.e. 12 elements must go in the thrid dimension to match b
mae = mean(abs(bsxfun(#minus, b, V)),3)
As MATLAB does not support broadcasting, you need to create a matrix the same size as b with the repeated values of vals. To be able to do that, first you need to change vals to a shape of 1x1x12 and then repeat it 5x7 times. You can do that with
values=repmat(permute(vals,[1 3 2]),[5 7 1]);
now you can
mae = mean(abs(bv - values))

How do i find a matrix of 150*25 from two vectors such that each vector elements multiply with each element of another vector of dim 1*150 &1*25?

I have a vector created from linspace between specific numbers and have dimensions of 1*150. Now i want to multiply each element of the above created vector with another vector whose dimension is 1*25. The detail of my code is given below
c_p = linspace(1,.3*pi,150);
c = c_p';
C = zeros([150,25]);
for i= 1:1:size(C,1)
wp= c(i);
for n= 1:25
c_wp(n) = cos(n*wp);
end
C(i,25)= c_wp;
end
The vector is actually a multiple of cosine of length 25 and here wp is the elements of first vector of dimension 1*150. SO by the logic, I must have an output of 150*25 but instead giving me "subscripted assignment dimension mismatch". Any help would be appreciated, as i am new to matlab.
To multiply each element of a row vector a with each element of another row vector b, we can use linear algebra. We transpose a to make it a column vector and then use matrix multiplication:
a.' * b
That way you don't even need a for loop.

How to access particular matrix element for all blocks in entire image?

I have a 512x512 image , which i made 4x4 block for entire image, then i want access the (3rd row , 3rd element) of the all indivial 4x4 matrices and add it to the index values, which i obtained. Please help me on below code.
[row col] = size(a);
m = zeros(row,col);
count = [(row-4)*(col-4)]/4;
outMat = zeros(4,4,count);
l = 0;
for i=2:4:row-4
for j=2:4:col-4
l = l + 1;
outMat(:,:,l) = double(a(i-1:i+2,j-1:j+2));% for each matrix i have to find(3rd row,3rd element of each matrix.
end;
end;
Adding the (3rd row,3rd element):
m(i,j) = sum(sum(a .* w)); %index value of each 4x4 matrix % w = 4x4 matrix.
LUT = m(i,j)+ outMat(3,3);%(3rd row,3rd element each matrix should be added to all m(i,j) values. In which i fail to add all(3rd row,3rd element) of all 4x4 matrices.
I am going to reword your question so that it's easier to understand, as well as allowing it to be easy for me to write an answer.
From your comments in Kostya's post, you have two images img1 and img2 where they are decomposed into 4 x 4 blocks. outMat would be a 3D matrix where each slice contains a 4 x 4 block extracted from img1. From this, you have a matrix m that stores a weighted sum of 4 x 4 blocks stored outMat.
Next, you'll have another matrix, let's call this outMat2, which also is a 3D matrix where each slice is a 4 x 4 block extracted from img2. From this 3D matrix, you wish to extract the third row and third column of each block, add this to the corresponding position of m and store the output into a variable called LUT.
All you have to do is extract a single vector that slices through all of the slices located at the third row and third column. You would then have to reshape this into a matrix that is the same size as m then add this on top of m and store it into a variable called LUT. Bear in mind that if we reshape this into a matrix, the reshaping will be done in column major format, and so you would stack the values by columns. Because your blocks were created row-wise, what we need to do reshape this matrix so that it has size(m,2) rows and size(m,1) columns then transpose it.
Therefore:
vec = outMat2(3,3,:);
vec = vec(:); %// Make sure it's a 1D vector
m2 = reshape(vec, size(m,2), size(m,1)).';
LUT = m + m2;
LUT will contain a 2D matrix where each element contains the weighted sum of the 4 x 4 blocks from img1 with the corresponding third row, third column of each block in img2.
Next time, please update your question so that you have all of the information. We shouldn't have to dig through your comments to figure out what you want.
I think you can do just
LUT = sum( sum( a(3:4:row,3:4,col) * w(3,3) ) );