So I need to find the minimum value of corresponding elements in multiple matrices. I did find this page but I would like to extend my question a little further. My matrices has positive and negative values (and zeros) and I want to find the minimum values excluding zeros.
Example:
Z(:,:,1) = [-5 0 5
0 0 0
1 0 3];
Z(:,:,2) = [1 0 2
0 0 0
0 0 0];
Z(:,:,3) = [0 0 0
-9 0 4
0 0 0];
Z(:,:,4) = [0 0 0
-2 0 0
0 0 0];
Here's what I'm using as of now:
Zmin = min(Z,[],3);
But that gives me:
[-5 0 0
-9 0 0
0 0 0]
But I want my result to be:
[-5 0 2
-9 0 4
1 0 3]
Any ideas? When I use nonzeros, it messes up everything.
Here's a workaround:
Replace all the 0s in Z by NaN, calculate the min, then switch back to 0:
clear all
clc
close all
Z(:,:,1) = [-5 0 5
0 0 0
1 0 3];
Z(:,:,2) = [1 0 2
0 0 0
0 0 0];
Z(:,:,3) = [0 0 0
-9 0 4
0 0 0];
Z(:,:,4) = [0 0 0
-2 0 0
0 0 0];
%// Assign NaN to 0 elements
Z(Z ==0) = NaN;
Zmin = min(Z,[],3);
%// Switch back with 0
Zmin(isnan(Zmin)) = 0;
%// Same for Z;
Z(isnan(Z)) =0;
The output looks like this:
Zmin
Z
Zmin =
-5 0 2
-9 0 4
1 0 3
Z(:,:,1) =
-5 0 5
0 0 0
1 0 3
Z(:,:,2) =
1 0 2
0 0 0
0 0 0
Z(:,:,3) =
0 0 0
-9 0 4
0 0 0
Z(:,:,4) =
0 0 0
-2 0 0
0 0 0
One option is to set all zero elements to NaN that way:
Z(Z==0)=NaN;
And then use nanmean
Zmin = nanmin(Z,[],3);
Related
I have a periodic binary matrix which includes a block of ones. I need to find the boundary between zeros and ones in the matrix. Here is an example:
A=[0,1,1,1,0,0,0,1,1;
0,0,0,0,1,1,1,1,0;
0,0,0,0,1,1,1,1,0;
0,0,0,0,1,1,1,1,0;
0,1,1,1,1,1,1,0,0;
0,1,1,1,1,1,1,0,0;
0,1,1,1,0,0,0,0,0;
0,1,1,1,0,0,0,0,0;
0,1,1,1,0,0,0,0,0]
If the matrix was not periodic, I could use
perim=bwperim(A);
to find the perimeter. But this does not work perfectly for periodic matrices. I appreciate it if someone can help me with this problem.
EDIT:
a periodic matrix is a matrix that its boundary elements are connected to the boundary elements on the other side of the matrix.
You can pad the image on each side with the column/row that it's connected to. For example, the left edge will be padded with the rightmost column. Then use bwperim, and trim one row/column from each side of the result.
A = [0 1 1 1 0 0 0 1 1;
0 0 0 0 1 1 1 1 0;
0 0 0 0 1 1 1 1 0;
0 0 0 0 1 1 1 1 0;
0 1 1 1 1 1 1 0 0;
0 1 1 1 1 1 1 0 0;
0 1 1 1 0 0 0 0 0;
0 1 1 1 0 0 0 0 0;
0 1 1 1 0 0 0 0 0];
padded_A = [0 A(end,:) 0;
A(:,end) A A(:,1);
0 A(1,:) 0];
padded_perim = bwperim(padded_A);
perim = padded_perim(2:end-1,2:end-1);
Result:
perim =
0 1 1 1 0 0 0 1 1
0 0 0 0 1 1 1 1 0
0 0 0 0 1 0 0 1 0
0 0 0 0 1 0 0 1 0
0 1 1 1 0 0 1 0 0
0 1 0 0 1 1 1 0 0
0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0
You can use conv2 and padarray to find the perimeter:
4-connected:
perim = A & conv2(padarray(A, [1 1], 'circular'), [0 1 0;1 0 1;0 1 0], 'valid') < 4;
8-connected:
perim = A & conv2(padarray(A, [1 1], 'circular'), [1 1 1;1 0 1;1 1 1], 'valid') < 8;
Using the definition of the perimeter:
A pixel is part of the perimeter if it is nonzero and it is connected to at least one zero-valued pixel.
Use A & ... to ensure that the pixel is nonzero. The boundary pixels are replicated using padarray with option 'circular'. The padded array is convolved with the connectivity mask. use conv2 with option 'valid' to trim the replicated boundary pixels. If it is less than 4 or 8 it means that it is connected to at least one zero-valued pixel.
I have a formula for creating a system of equations in matrix form.and wrote it like below:
for i=1:n+1
for j=1:n+1
t(i)=(1/2)*(1+cos(((2*(n-i)+3)*pi)/(2*(n+1))));
y(i,j)=t(i)^(j-1);
end
end
now what I have to do is creating a block diagonal matrix with rows of y separately in each block. i mean each row of y that contain powers of just t(i) should repeat three times in each block, then next row be the next block with three rows. like this:
T=[y(t1) 0 0;0 y(t1) 0;0 0 y(t1); ... ;y(t n+1) 0 0;0 y(tn+1) 0;0 0 y(tn+1)]
So since I can't comment in formated mode I try to interprete your question the following way:
So if
y =
1 2
3 4
Interpretation possibility a) is
T =
1 2 0 0 0 0 3 4 0 0 0 0
0 0 1 2 0 0 0 0 3 4 0 0
0 0 0 0 1 2 0 0 0 0 3 4
or this b)
T =
1 2 0 0 0 0 0 0 0 0 0 0
0 0 1 2 0 0 0 0 0 0 0 0
0 0 0 0 1 2 0 0 0 0 0 0
0 0 0 0 0 0 3 4 0 0 0 0
0 0 0 0 0 0 0 0 3 4 0 0
0 0 0 0 0 0 0 0 0 0 3 4
Solution
You first create one block i.e.
1 2 0 0 0 0
0 0 1 2 0 0
0 0 0 0 1 2
by calculating temp{1} = kron(I, y(1,:)), where I = eye(3). You then do the same operation for the second row: temp{2} = kron(I,y(2,:)) and so on. This procedure can be done easily in a for-loop:
I = eye(3);
temp = cell(1,size(y,1));
for i = 1:size(y,1)
temp{i} = kron(I, y(i,:));
end
Option a)
The result is now just: [temp{:}].
Option b)
Here the result is: blkdiag(temp{:})
you know, I had a problem for making a system of linear equations.maybe what I wrote above in calculating the y(i) just make it difficult for me.
for the example you said, I have this:
n=3
form equation above:
t1=0.0381
t2=0.3087
t3=0.6913
t4=0.9619
now,
y(t)=[1 t t^2 t^3 t^4]
I mean
y(t1)=[1.0000 0.0381 0.0014 0.0001]
y(t2)=[1.0000 0.3087 0.0953 0.0294]
y(t3)=[1.0000 0.6913 0.4780 0.3304]
y(t4)=[1.0000 0.9619 0.9253 0.8901]
but, since I couldn't calculate every y(i) seperately, wrote it in this form
y=[1.0000 0.0381 0.0014 0.0001
1.0000 0.3087 0.0953 0.0294
1.0000 0.6913 0.4780 0.3304
1.0000 0.9619 0.9253 0.8901]
now, should have two matrices. one:
s=[y(t) 0 0;0 y(t) 0;0 0 y(t)]
r=[s(t1) ... 0; ... ;0 ... s(tn+1)]
second:
d=[ 1 -1 1 -1
0 2 -8 18
0 0 8 -48
0 0 0 32]
k=y*d
u=[0 0 0;0 k 0;0 0 0]
a=[u(t1) ... 0; ... ;0 ... u(tn+1)]
and these matrices, r and a, should have 3(n+1) columns (in this example 12 columns).
I hope it could help
I know how to build a matrix within MATLAB but the example I am working on has is defined as
a(cl,:,k)=x*ang;
cl, k, x and ang are already defined. I just wondered what the (cl,:,k) does, in particular the role of the commas?
Also, if I were to replicate this within Excel then how would I do so?
The comma , in a(cl,:,k) is to separate different dimensions of the matrix a.
The colon : in a(cl,:,k) is to select all elements along this dimension (restricted by other dimensions), which is shorthand notation for 1:end. In other words, all elements a(cl, 1:end, k) are selected, where end is the size of the second dimension of a.
For example:
a = zeros(2, 3); // 2x3 matrix with all elements are 0
a(1, :) = [1 2 3]; // <=> a(1,1:3)=[1 2 3]; assign all elements to the first row
then, a will be
1 2 3
0 0 0
The commas separate the indices along different axes of the elements of the multi dimensional array you want to access
: means 1:end - here end will become the largest index possible along that axis
>> a = zeros(3,3,3)
a(:,:,1) =
0 0 0
0 0 0
0 0 0
a(:,:,2) =
0 0 0
0 0 0
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(1,:,1) = 1
a(:,:,1) =
1 1 1
0 0 0
0 0 0
a(:,:,2) =
0 0 0
0 0 0
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(2,1:end,2) = 2
a(:,:,1) =
1 1 1
0 0 0
0 0 0
a(:,:,2) =
0 0 0
2 2 2
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(1,1,:) = 5
a(:,:,1) =
5 1 1
0 0 0
0 0 0
a(:,:,2) =
5 0 0
2 2 2
0 0 0
a(:,:,3) =
5 0 0
0 0 0
0 0 0
I have a matrix m = zeros(1000, 1000). Within this matrix I want to draw an estimate of the line which passes through 2 points from my matrix. Let's say x = [122 455]; and y = [500 500];.
How can I do this in Matlab? Are there any predefined functions to do this? I am using Matlab 2012b.
I'll denote the two endpoints as p1 and p2 because I'm planning to use x and y for something else. I'm also assuming that the first coordinate of p1 and p2 is x and the second is y. So here's a rather simple way to do it:
Obtain the equation of the line y = ax + b. In MATLAB, this can be done by:
x = p1(1):p2(1)
dx = p2(1) - p1(1);
dy = p2(2) - p1(2);
y = round((x - p1(1)) * dy / dx + p1(2));
Convert the values of x and y to indices of elements in the matrix, and set those elements to 1.
idx = sub2ind(size(m), y, x);
m(idx) = 1;
Example
Here's an example for a small 10-by-10 matrix:
%// This is our initial conditon
m = zeros(10);
p1 = [1, 4];
p2 = [5, 7];
%// Ensure the new x-dimension has the largest displacement
[max_delta, ix] = max(abs(p2 - p1));
iy = length(p1) - ix + 1;
%// Draw a line from p1 to p2 on matrix m
x = p1(ix):p2(ix);
y = round((x - p1(ix)) * (p2(iy) - p1(iy)) / (p2(ix) - p1(ix)) + p1(iy));
m(sub2ind(size(m), y, x)) = 1;
m = shiftdim(m, ix > iy); %// Transpose result if necessary
The result is:
m =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Update: I have patched this algorithm to work when dy > dx by treating the dimension with the largest displacement as if it were the x-dimension, and then transposing the result if necessary.
Neither of the provided answers work for displacements in y greater than in x (dy > dx).
As pointed out, Bresenham's line algorithm is exactly meant for that.
The matlab file provided here works similarly than the examples provided in the other answers but covers all the use-cases.
To relate to the previously provided example, the script can be used like this:
% initial conditions
m = zeros(10);
p1 = [1, 4];
p2 = [5, 10];% note dy > dx
% use file provided on file exchange
[x y] = bresenham(p1(1),p1(2),p2(1),p2(2));
% replace entries in matrix m
m(sub2ind(size(m), y, x)) = 1;
result looks like this:
m =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
For me (matlab R2013b) following line did not work, when p1(1)>p2(2) (":" can not count backwards):
x = p1(1):p2(1);
E.G.:
1:10
1 2 3 4 5 6 7 8 9 10
10:1
Empty matrix: 1-by-0
But it worked when I used linspac instead:
x = linspace(p1(1), p2(1), abs(p2(1)-p1(1))+1);
I have a y of size 5000,1 (matrix), which contains integers between 1 and 10. I want to expand those indices into a 1-of-10 vector. I.e., y contains 1,2,3... and I want it to "expand" to:
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
What is the best way to do that?
I tried:
Y = zeros(5000,10); Y(y) = 1;
but it didn't work.
It works for vectors though:
if y = [2 5 7], and Y = zeros(1,10), then Y(y) = [0 1 0 0 1 0 1 0 0 0].
Consider the following:
y = randi([1 10],[5 1]); %# vector of 5 numbers in the range [1,10]
yy = bsxfun(#eq, y, 1:10)'; %# 1-of-10 encoding
Example:
>> y'
ans =
8 8 4 7 2
>> yy
yy =
0 0 0 0 0
0 0 0 0 1
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 0 0
0 0 0 0 0
0 0 0 0 0
n=5
Y = ceil(10*rand(n,1))
Yexp = zeros(n,10);
Yexp(sub2ind(size(Yexp),1:n,Y')) = 1
Also, consider using sparse, as in: Creating Indicator Matrix.
While sparse may be faster and save memory, an answer involving eye() would be more elegant as it is faster than a loop and it was introduced during the octave lecture of that class
Here is an example for 1 to 4
V = [3;2;1;4];
I = eye(4);
Vk = I(V, :);
You can try cellfun operations:
function vector = onehot(vector,decimal)
vector(decimal)=1;
end
aa=zeros(10,2);
dec=[5,6];
%split into columns
C=num2cell(aa,1);
D=num2cell(dec,1);
onehotmat=cellfun("onehot",C,D,"UniformOutput",false);
output=cell2mat(onehotmat);
I think you mean:
y = [2 5 7];
Y = zeros(5000,10);
Y(:,y) = 1;
After the question edit, it should be this instead:
y = [2,5,7,9,1,4,5,7,8,9....]; //(size (1,5000))
for i = 1:5000
Y(i,y(i)) = 1;
end