I have to analyze some STL files with Matlab, and I import them successfully with an STL reader, but this function only returns vertices and faces (triangles).
This is the STL reader I am using, and this is an example STL file, generated by the gmsh tool with gmsh -2 -format stl -bin t4.geo. In case, the code for the STL function is at the end.
mesh = stlread("t4.stl");
Is there a function I can use to obtain the vertex/edge adjacency matrix from such a triangulation?
function [F,V,N] = stlbinary(M)
F = [];
V = [];
N = [];
if length(M) < 84
error('MATLAB:stlread:incorrectFormat', ...
'Incomplete header information in binary STL file.');
end
% Bytes 81-84 are an unsigned 32-bit integer specifying the number of faces
% that follow.
numFaces = typecast(M(81:84),'uint32');
%numFaces = double(numFaces);
if numFaces == 0
warning('MATLAB:stlread:nodata','No data in STL file.');
return
end
T = M(85:end);
F = NaN(numFaces,3);
V = NaN(3*numFaces,3);
N = NaN(numFaces,3);
numRead = 0;
while numRead < numFaces
% Each facet is 50 bytes
% - Three single precision values specifying the face normal vector
% - Three single precision values specifying the first vertex (XYZ)
% - Three single precision values specifying the second vertex (XYZ)
% - Three single precision values specifying the third vertex (XYZ)
% - Two unused bytes
i1 = 50 * numRead + 1;
i2 = i1 + 50 - 1;
facet = T(i1:i2)';
n = typecast(facet(1:12),'single');
v1 = typecast(facet(13:24),'single');
v2 = typecast(facet(25:36),'single');
v3 = typecast(facet(37:48),'single');
n = double(n);
v = double([v1; v2; v3]);
% Figure out where to fit these new vertices, and the face, in the
% larger F and V collections.
fInd = numRead + 1;
vInd1 = 3 * (fInd - 1) + 1;
vInd2 = vInd1 + 3 - 1;
V(vInd1:vInd2,:) = v;
F(fInd,:) = vInd1:vInd2;
N(fInd,:) = n;
numRead = numRead + 1;
end
end
Assuming your faces are in a n-by-3 array F:
% temporary array
T = [F(:,1) F(:,2) ; F(:,1) F(:,3) ; F(:,2) F(:,3)];
% get the edges
E = unique([min(T,[],2), max(T,[],2)],'rows');
% build the adjacency matrix
n = max(E(:,2));
A = sparse(E(:,1), E (:,2), ones(size(E,1),1), n, n);
A = A + A';
NB: sparse arrays are often useful for such adjacency matrix, especially in the large limit.
Best,
Related
I am attempting to generate 2500 psuedo-random numbers using LCG for a project. However, when I attempt to run the code I continuously receive the error "Output argument 'p' (and maybe others) not assigned during call to lcgg'.". I was hoping someone could help me understand why p is not in the output and how I can fix this?
clear;
clc;
M = 2500;
ID = 801201076;
disp('N = '); disp(mod(ID,3));
[A,p1] = lcgg(M,30269,171,0,1);
[B,p2] = lcgg(M,30307,172,0,1);
[C,p3] = lcgg(M,30323,170,0,1);
disp('Period = '); disp(p2);
% Combine the 3 generators as in Wichmann and Hill
figure(1);
subplot(2,1,1);hist(B);title('Histogram for Uniform RDN from LCG');
subplot(2,1,2);qqplot(rand(300,1),B);title('QQplot for uniform RDN from LCG');
figure(2);
scatter(B(1:(M-1),1),B(2:M,1),4);title('Plot of sequential pairs for LCG');
D = A + B + C - fix(A + B + C); % internal Matlab uniform random number generator
u = rand(M,1); % internal Matlab uniform random number generator
figure(3);
subplot(2,1,1);scatter(u(1:(M-1),1),u(2:M,1),4);title('Plot of Sequential Pairs for Matlab Internal Generator');
subplot(2,1,2);scatter(D(1:M-1),1),D(2:M,1),4;title('Plot of sequential pairs for 3 LCG Combined')
% Calculate the period
i = 1;
j = 2;
while A(i,1) ~= A(j,1) && i < m
if j < m
j = j+1;
else
i = i+1;
j = j+1;
end
end
if i == m
p = m;
else
p = j-1;
end
A = A./m;
if M <= m
A = A(1:M,:);
end
function[A,p] = lcgg(M,m,a,c,x0)
% Generates a matrix of random numbers using lcg
% Calculate the period
% Input: M: total number of random numbers needed
% m, a, x, x0
% Output: A: M * 1 matrix of random numbers
% p: period of the LCG random number generator
A = zeros(m,1);
for i = 1:m
if i == 1
A(i,1) = lcg(m,a,c,x0);
else
A(i,1) = lcg(m,a,c,A(i-1,1));
end
end
end
% The LCG Function:
function[x] = lcg(m,a,c,x0)
% Linear Congruential Generator (LCG)
x = mod(a*x0+c, m);
end
You define a function:
function[A,p] = lcgg(...)
Within the function body you need to assign a value to both output variables, A and p. You don’t assign anything to p, hence the message.
Let's say I have a matrix over GF(2) , i.e. a binary matrix. Now how do I go about computing the left null space of the given matrix over the finite field of 2?
Does MATLAB provide an in-built function for this?
I don't know of Matlab packages for linear algebra in finite space, but I programmed a simple
function that calculates LU-factorizations of matrices modulo a prime p (for example, 2):
function [L,D,U,rows,cols] = ModLU(A,p)
%
% LU-factorization of A, modulo p:
% A(rows,cols) - mod(L * diag(D)*U,p)
%
[m,n] = size(A);
% inverses in mod-p:
% mod(k*invp(k+1)) = 0 if k==0; 1 otherwise
invp = 2:p-2;
for i = 2:p-2; invp = mod(invp.*[2:p-2],p); end
invp = [0,1,invp,p-1];
% Initialize outputs:
L = eye(m); U = A;
rows = 1:m;
cols = 1:n;
% Sweep
for i = 1:m
% Pivoting
[row,col] = find(U(i:end,:));
if isempty(row); break; end
row = row(1)+i-1; col = col(1);
r = 1:m; r(i) = row; r(row) = i;
c = 1:n; c(i) = col; c(col) = i;
ri = rows(i); rows(i) = rows(row); rows(row)=ri;
ci = cols(i); cols(i) = cols(col); cols(col)=ci;
rinv = 1:m; rinv(r) = 1:m;
U = U(r,c); L=L(r,r);
% Gaussian elimination
L(i+1:end,i ) = mod(invp(U(i,i)+1) * U(i+1:end,i),p);
U(i+1:end,i:end) = mod(U(i+1:end,i:end) + (p-L(i+1:end,i)) * U(i,i:end),p);
end
% Factorize diagonal
D = zeros(m,1); D(1:min(m,n)) = diag(U);
U = mod(diag(invp(D+1)) * U,p );
Also, for an upper triangular matrix with ones on the diagonal, a function that calculates
the right-null space modulo p:
function N = NullPU(U,p)
% for an upper triangular matrix, calculate a base for the null space modulo p:
% U * N = 0
n = size(U,2);
rank = size(find(diag(U)),1);
A = U(1:rank,:);
for i=rank:-1:2
A(1:i-1,:) = mod(A(1:i-1,:) + (p-1) * A(1:i-1,i) * A(i,:),p);
end
N = [mod(p-A(:,rank+1:end),p); eye(n-rank)];
These functions are simply combined into a function that calculates the null space of
matrix A, modulo p:
function N = NullP(A,p)
% Calculate a basis for the null space of A, modulo p:
% mod(A*N,p) = 0
[L,D,U,rows,cols] = ModLU(A,p);
N = NullPU(U,p);
N(cols,:) = N;
Note that this function calculates a base for the right null space of A, modulo p. The left
null space is found using
N = NullP(A',p)';
I have a 2D image (matrix). I have found the local maxima of this image. Now I want to define the boundaries around each local maxima in such a way that I want all the pixels around the local maxima that have a value above 85% of the maximum.
Here is my existing code:
function [location]= Mfind_peak_2D( Image,varargin )
p = inputParser;
addParamValue(p,'max_n_loc_max',5);
addParamValue(p,'nb_size',3);
addParamValue(p,'thre',0);
addParamValue(p,'drop',0.15);
parse(p,varargin{:});
p=p.Results;
if sum(isnan(Image(:)))>0
Image(isnan(Image))=0;
end
hLocalMax = vision.LocalMaximaFinder;
hLocalMax.MaximumNumLocalMaxima = p.max_n_loc_max;
hLocalMax.NeighborhoodSize = [p.nb_size p.nb_size];
end
This should do the job (the code is full of comments and should be pretty self-explanatory but if you have doubts feel free to ask for more details):
% Load the image...
img = imread('peppers.png');
img = rgb2gray(img);
% Find the local maxima...
mask = ones(3);
mask(5) = 0;
img_dil = imdilate(img,mask);
lm = img > img_dil;
% Find the neighboring pixels of the local maxima...
img_size = size(img);
img_h = img_size(1);
img_w = img_size(2);
res = cell(sum(sum(lm)),3);
res_off = 1;
for i = 1:img_h
for j = 1:img_w
if (~lm(i,j))
continue;
end
value = img(i,j);
value_thr = value * 0.85;
% Retrieve the neighboring column and row offsets...
c = bsxfun(#plus,j,[-1 0 1 -1 1 -1 0 1]);
r = bsxfun(#plus,i,[-1 -1 -1 0 0 1 1 1]);
% Filter the invalid positions...
idx = (c > 0) & (c <= img_w) & (r > 0) & (r <= img_h);
% Transform the valid positions into linear indices...
idx = (((idx .* c) - 1) .* img_h) + (idx .* r);
idx = reshape(idx.',1,numel(idx));
idx = idx(idx > 0);
% Retrieve the neighbors and filter them based on te threshold...
neighbors = img(idx);
neighbors = neighbors(neighbors > value_thr);
% Update the final result...
res(res_off,:) = {sub2ind(img_size,i,j) value neighbors};
res_off = res_off + 1;
end
end
res = sortrows(res,1);
The variable res will be a cell matrix with three columns: the first one contain the linear indices to the local maxima of the image, the second one contains the values of the local maxima and the third one a vector with the pixels around the local maxima that fall within the specified threshold.
I have an array A (I have written so as to make it similar to the matrix that I am using) :
%%%%%%%%%%%%% This is Matrix %%%%%%%%%%%%%%%%%%%%
a = 3; b = 240; c = 10; d = 30; e = 1;
mtx1 = a.*rand(30,1) + a;
mtx2 = round((b-c).*rand(30,1));
mtx3 = round((d-e).*rand(30,1));
mtx4 = -9999.*ones(30,1);
A = [mtx1 mtx2 mtx3 mtx4];
for i = 10:12
for ii = 17 :19
A(i,:)= -9999;
A(ii,:)= 999;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
I would calculate some statistical values, excluding from the calculation the values **-9999 and 999.
the statistical values must be calculated with respect to each column.
the columns represent respectively: the wind speed, direction, and
other parameters
I wrote a code but it is not correct
[nr,ncc]=size(A);
for i=1:ncc
B = A(:,i); %// Temp Vector
Oup=1; Odw=1; %// for Vector Control
while Oup>0 %// || Odw>0 % Oup>0 OR Odw>0 , Oup>0 && (AND) Odw>0
B=sort(B,'descend');
U = find(B<999 & B>-9999); % find for each column of the temp
%vector
Oup = length(U); % Calculates the length
B(U)=[]; % Delete values -9999 and 9999
end
% calculates parameters with the vector temp
count(i)=length(B);
med(i)=mean(B);
devst(i)=std(B);
mediana(i)=median(B);
vari(i)=var(B);
kurt(i)=kurtosis(B);
Asimm(i)=skewness(B);
Interv(i)=range(B);
Mass(i)=max(B);
Mini(i)=min(B);
if length(B)<nr
B(length(B)+1:nr)=nan;
end
C(:,i)=B(:); %//reconstruction of the original matrix
end
would you have any suggestions?
If your data set is in A, and you want to operate on it with a function f, just use logical indexing, i.e.:
f(A( ~(A==999 & A==-9999) )) =...
Alternatively, use find and linear indexing:
ind = find( ~(A==999 & A==-9999) );
f(A(ind)) = ....
I am a total beginner in Matlab and trying to write some Machine Learning Algorithms in Matlab. I would really appreciate it if someone can help me in debugging this code.
function y = KNNpredict(trX,trY,K,X)
% trX is NxD, trY is Nx1, K is 1x1 and X is 1xD
% we return a single value 'y' which is the predicted class
% TODO: write this function
% int[] distance = new int[N];
distances = zeroes(N, 1);
examples = zeroes(K, D+2);
i = 0;
% for(every row in trX) { // taking ONE example
for row=1:N,
examples(row,:) = trX(row,:);
%sum = 0.0;
%for(every col in this example) { // taking every feature of this example
for col=1:D,
% diff = compute squared difference between these points - (trX[row][col]-X[col])^2
diff =(trX(row,col)-X(col))^2;
sum += diff;
end % for
distances(row) = sqrt(sum);
examples(i:D+1) = distances(row);
examples(i:D+2) = trY(row:1);
end % for
% sort the examples based on their distances thus calculated
sortrows(examples, D+1);
% for(int i = 0; i < K; K++) {
% These are the nearest neighbors
pos = 0;
neg = 0;
res = 0;
for row=1:K,
if(examples(row,D+2 == -1))
neg = neg + 1;
else
pos = pos + 1;
%disp(distances(row));
end
end % for
if(pos > neg)
y = 1;
return;
else
y = -1;
return;
end
end
end
Thanks so much
When working with matrices in MATLAB, it is usually better to avoid excessive loops and instead use vectorized operations whenever possible. This will usually produce faster and shorter code.
In your case, the k-nearest neighbors algorithm is simple enough and can be well vectorized. Consider the following implementation:
function y = KNNpredict(trX, trY, K, x)
%# euclidean distance between instance x and every training instance
dist = sqrt( sum( bsxfun(#minus, trX, x).^2 , 2) );
%# sorting indices from smaller to larger distances
[~,ord] = sort(dist, 'ascend');
%# get the labels of the K nearest neighbors
kTrY = trY( ord(1:min(K,end)) );
%# majority class vote
y = mode(kTrY);
end
Here is an example to test it using the Fisher-Iris dataset:
%# load dataset (data + labels)
load fisheriris
X = meas;
Y = grp2idx(species);
%# partition the data into training/testing
c = cvpartition(Y, 'holdout',1/3);
trX = X(c.training,:);
trY = Y(c.training);
tsX = X(c.test,:);
tsY = Y(c.test);
%# prediction
K = 10;
pred = zeros(c.TestSize,1);
for i=1:c.TestSize
pred(i) = KNNpredict(trX, trY, K, tsX(i,:));
end
%# validation
C = confusionmat(tsY, pred)
The confusion matrix of the kNN prediction with K=10:
C =
17 0 0
0 16 0
0 1 16