Magnitude of each column in a matrix [duplicate] - matlab

This question already has answers here:
Vector norm of an array of vectors in MATLAB
(4 answers)
Closed 5 years ago.
I have an input matrix that has 3 rows and 1000 columns. Each column represents and x, y, z variable. I want to find the magnitude of each column and store that in an output matrix that has 1 row and 1000 columns.
This is my current attempt but it doesn't seem to be working:
output(1,:) = norm(input(3,:));
my input matrix looks like:
x1, x2,...,x1000
y1, y2,...,y1000
z1, z2,...,z1000
I want my output matrix to look like:
[magnitude(x1,y1,z1), magnitude(x2,y2,z2),...,magnitude(x1000,y1000,z1000)]
Any help would be greatly appreciated.

norm(input(3,:)) will give you the norm of the 1000 elements of the third row.
Easy solution is to just run a for loop.
output = zeros(1,1000); %Preallocate space
for i = 1:length(output)
output(i) = norm(input(:, i));
end

MATLAB's norm function only works for single vectors. Let A be the name of the matrix which columns you want to find the norm to. Then this command does the job:
norm_A = sqrt(sum(A.*A));
Here is an example:
>> A = [1:5; 1:5; 1:5]
A =
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
>> norm_A = sqrt(sum(A.*A))
norm_A =
1.7321 3.4641 5.1962 6.9282 8.6603

Related

Construct single column matrix from the rows of another matrix with multiple columns in Matlab [duplicate]

This question already has answers here:
rgb to ycbcr conversion in matlab
(2 answers)
Closed 4 years ago.
I'm learning about image processing, and currently translating between RGB and YCbCr.
Basically, I have a nxmx3 matrix, which represents the brightness of each colour (RGB), and the operation to change this to Y,Cb, and Cr would be something like this:
for each row, index, in RGBMatrix:
y[index] = row[0] + row[1] + row[2]
So each row of y has one value, and that value is based on the values in the same in RGBMatrix.
I've tried the following in MATLAB:
function [y,Cb, Cr] = rgbToYCbCr(r,g,b)
signalSize = size(r);
y = zeros(signalSize);
for i = 1:signalSize(1)
for j = 1:signalSize(2)
y(i,j,1) = (0.299 * r(i,j,1)) + (0.587 * g(i,j,2)) + (0.114 * b(i,j,3));
end
end
end
However, this does not give me the results that I want as y now has the same dimensions as the RGBMatrix, when instead it should be 1 column.
How can I do this efficiently in MATLAB?
I know there is an inbuilt function for RGB to YCbCr, but for the sake of learning I'd like to implement it myself.
Example:
RGB Matrix:
R G B
[[0.5,0.5,0.5],
[0.2,0.1,0.6],
[0.1,0.4,0.7]]
Y Matrix:
[[0.5+0.5+0.5],
[-0.2-0.1+0.6],
[0.1+0.4-0.7]]
or
[[1.5],
[0.3],
[-0.2]]
Ignore the fact that values aren't realistic, what I'm more concerned about is carrying out an operation per row like I've described in Matlab without using the (typically) slower iterative way (with a for loop).
In reality I have a 1080x768x3 array. Each element in the 1080x768 dimension has a value for each colour (R,G,B) and I want to convert this to (Y,Cb,Cr) eventually.
If you have an RGB image, Imgrgb that is NxMx3 in size, do:
Imgrgb= imread('peppers.png'); % A sample RGB image
% make sure you have a double image range [0-1], you may not need this.
Imgrgb=im2double(Imgrgb);
r=Imgrgb(:,:,1);
g=Imgrgb(:,:,2);
b=Imgrgb(:,:,3);
y = (0.299 * r) + (0.587 * g) + (0.114 * b);
Cb=
Cr=
% concatenate result:
ImgYCbCr=cat(3,y,Cb,Cr);
And y shoudl be NxM, the same as r,g, and b. Do the same for the other 2 values with their corresponding equation.
If your matrix is like:
A =
1 3 5
2 4 6
then you may "flatten" it to a vector like:
>>Av = A(:)
Av =
1
2
3
4
5
6
I.e. it takes the values from the matrix in a row order and converts to a vector.
To convert it back to a matrix you may use the reshape function
>> reshape(Av,[2 3])
ans =
1 3 5
2 4 6
The A(:) method is equivalent to reshape(A,[numel(A) 1])

MATLAB - convert vector to unit vector [duplicate]

This question already has answers here:
Normalizing rows of matrix, so that their norm is equal to 1 (MATLAB)
(2 answers)
Closed 6 years ago.
I have a vector:
vector = [1 2 3;4 5 6; 7 9 0]
vector =
1 2 3
4 5 6
7 9 0
I want to take this and create a unit vector. We can get the magnitude by doing:
mag = sqrt(sum(vector'.^2))'
mag =
3.7417
8.7750
11.4018
When we try to divide each element by the magnitude I get an error:
vector./mag
Error using ./
Matrix dimensions must agree.
Essentially I must divide every vector element in each row by every row in the mag vector. How can I do this?
The other answers give the correct result but you can vectorize the calculation for faster calculation.
ret = bsxfun(#rdivide, vector, mag)
I recommend using the bsxfun, it is a very useful function for matrix calculation.
The problem is that, as the error message says, the dimensions of vector and mag don't match.
You want to divide every element of the first row of vector by mag(1).
What you need is repmat(), which "repeats copies of array".
Writing
repmat(mag,1,3)
returns a 3x3 matrix such that every column is an exact copy of mag:
3.7417 3.7417 3.7417
8.7750 8.7750 8.7750
11.4018 11.4018 11.4018
So you can use the one-liner:
vector./repmat(mag,1,3)
ans =
0.26726 0.53452 0.80178
0.45584 0.56980 0.68376
0.61394 0.78935 0.00000
That way, the first row of vector, i.e., [1 2 3], is divided element-by-element by [3.7417 3.7417 3.7417].
In other words, every element of vector is divided by the correct magnitude.
You can use matrix operators in MATLAB:
result = diag(1./mag)*vector;
If dimension of mag can be too big you can use sparse version of it:
result = spdiags(1./mag,0,speye(numel(mag)))*vector;
A simple solution is the use of a for-loop:
vector = [1 2 3; 4 5 6; 7 9 0];
mag = sqrt(sum(vector'.^2))';
A = [];
for i = 1:numel(mag)
A(i,:) = vector(i,:)./mag(i);
end
vector = [1 2 3; 4 5 6 ;7 9 0] ;
[n,m]=size(vector);
for i=1:n
normv=norm(vector(i,:),2);
nvector(i,:)=vector(i,:)/normv;
end
the nvector will contain the normalized vector of each line

How to add elements of a matrix to create a new matrix?

Say I have a matrix
x = [1 2 3 4 ]
and I want to create a matrix that adds two elements and outputs a third?
y = [1+2 3+4]
y = [3 7]
For four values, I can just do y=[x(1)+x(2) x(3)+x(4)].
How would I go about doing that if x was bigger and variable (say a thousand elements)? How would I program y?
I've been struggling with this for two days now... thanks in advance...
A simple way would be to reshape the original array x into a matrix containing k rows, k being the number of elements you are summing together (here 2, sorry I don't know how to explain this), and then simply call sum on this matrix which will calculate the sum of each column and output it into a new vector y.
Example:
x = [1:10]
block = 2
r = reshape(x,block,[])
So here r looks like this:
r =
1 3 5 7 9
2 4 6 8 10
Therefore calling sum with the 1st dimension on r yields the following:
y = sum(reshape(x,block,[]),1)
y =
3 7 11 15 19

MATLAB: Applying vectors of row and column indices without looping

I have a situation analogous to the following
z = magic(3) % Data matrix
y = [1 2 2]' % Column indices
So,
z =
8 1 6
3 5 7
4 9 2
y represents the column index I want for each row. It's saying I should take row 1 column 1, row 2 column 2, and row 3 column 2. The correct output is therefore 8 5 9.
I worked out I can get the correct output with the following
x = 1:3;
for i = 1:3
result(i) = z(x(i),y(i));
end
However, is it possible to do this without looping?
Two other possible ways I can suggest is to use sub2ind to find the linear indices that you can use to sample the matrix directly:
z = magic(3);
y = [1 2 2];
ind = sub2ind(size(z), 1:size(z,1), y);
result = z(ind);
We get:
>> result
result =
8 5 9
Another way is to use sparse to create a sparse matrix which you can turn into a logical matrix and then sample from the matrix with this logical matrix.
s = sparse(1:size(z,1), y, 1, size(z,1), size(z,2)) == 1; % Turn into logical
result = z(s);
We also get:
>> result
result =
8
5
9
Be advised that this only works provided that each row index linearly increases from 1 up to the end of the rows. This conveniently allows you to read the elements in the right order taking advantage of the column-major readout that MATLAB is based on. Also note that the output is also a column vector as opposed to a row vector.
The link posted by Adriaan is a great read for the next steps in accessing elements in a vectorized way: Linear indexing, logical indexing, and all that.
there are many ways to do this, one interesting way is to directly work out the indexes you want:
v = 0:size(y,2)-1; %generates a number from 0 to the size of your y vector -1
ind = y+v*size(z,2); %generates the indices you are looking for in each row
zinv = z';
zinv(ind)
>> ans =
8 5 9

Averaging every n elements of a vector in matlab

I would like to average every 3 values of an vector in Matlab, and then assign the average to the elements that produced it.
Examples:
x=[1:12];
y=%The averaging operation;
After the operation,
y=
[2 2 2 5 5 5 8 8 8 11 11 11]
Therefore the produced vector is the same size, and the jumping average every 3 values replaces the values that were used to produce the average (i.e. 1 2 3 are replaced by the average of the three values, 2 2 2). Is there a way of doing this without a loop?
I hope that makes sense.
Thanks.
I would go this way:
Reshape the vector so that it is a 3×x matrix:
x=[1:12];
xx=reshape(x,3,[]);
% xx is now [1 4 7 10; 2 5 8 11; 3 6 9 12]
after that
yy = sum(xx,1)./size(xx,1)
and now
y = reshape(repmat(yy, size(xx,1),1),1,[])
produces exactly your wanted result.
Your parameter 3, denoting the number of values, is only used at one place and can easily be modified if needed.
You may find the mean of each trio using:
x = 1:12;
m = mean(reshape(x, 3, []));
To duplicate the mean and reshape to match the original vector size, use:
y = m(ones(3,1), :) % duplicates row vector 3 times
y = y(:)'; % vector representation of array using linear indices