Building adjacency matrix from faces array - matlab

I am using this code used in a toolbox for calculating adjacency matrix from a set of faces. My faces is an m*3 array for example:
23 13 12
12 22 23
13 4 12
23 14 13
22 35 23
From what I have understood, the adjacency matrix should be an nxn matrix where n is the number of vertices. For some of my mesh .ply files I get adjacency matrix which has a smaller dimension than the number of vertices. For example, n=5047 but my adjacency matrix has dimensions nxn= 4719x4719.
What could be the reason for this behavior? I get this error not on all but some mesh files only.
The code:
function A = triangulation2adjacency(face,vertex)
% triangulation2adjacency - compute the adjacency matrix
% of a given triangulation.
%
% A = triangulation2adjacency(face);
% or for getting a weighted graph
% A = triangulation2adjacency(face,vertex);
%
% Copyright (c) 2005 Gabriel Peyr
[tmp,face] = check_face_vertex([],face);
f = double(face)';
A = sparse([f(:,1); f(:,1); f(:,2); f(:,2); f(:,3); f(:,3)], ...
[f(:,2); f(:,3); f(:,1); f(:,3); f(:,1); f(:,2)], ...
1.0);
% avoid double links
A = double(A>0);
return;
nvert = max(max(face));
nface = size(face,1);
A = spalloc(nvert,nvert,3*nface);
for i=1:nface
for k=1:3
kk = mod(k,3)+1;
if nargin<2
A(face(i,k),face(i,kk)) = 1;
else
v = vertex(:,face(i,k))-vertex(:,face(i,kk));
A(face(i,k),face(i,kk)) = sqrt( sum(v.^2) ); % euclidean distance
end
end
end
% make sure that all edges are symmetric
A = max(A,A');

You can find a compact function here with name triangulation2adjacency.
That graph toolbox is very useful for 3d mesh and graph functions.

Ran into a similar problem a while a go... in a difffent context but you migth still find my experience usefull:
My Problem was the misunderstanding that n≠No.Faces. n is the number of vertices and each face can have three or more. Some Faces share vertices and thats why n≠No.Faces.
In Your example try:
B=[23 13 12;...
12 22 23;...
13 4 12;...
23 14 13;...
22 35 23];
NoVert=numel(unique(B));
NoFace=size(B,2);
In an adjacency matrix each node/vertice gets a row/colum so for B this would be a Matrix of 7x7.
Even bigger matrices result if the nodes are not numbered consecutively, for B this would result in a 35x35 Matrix, because the highest node number is 35.
a bit off topic, but try this :
G = digraph([B(:,1);B(:,2);B(:,3)],[B(:,2);B(:,3);B(:,1)]);
A = adjacency(G);
you will get the adjacency matrix with a lot less code. (and maybe time, did not test)

Related

How do I make a Mahalanobis distance matrix in MATLAB?

I have a data set with 5 repeats for each sample and 25 variables.
I am trying to make a Mahalanobis distance matrix between all of the samples using these parameters. I used the "mahal" function, but this gives a vector of all of the distances for each repeat. How can I make a matrix of distances between samples (38*38) and not a vector (1*190)?
For some test data:
X = rand(38,25); % some random test data with 38 observations and 25 variables
X = repmat(X,5,1); % 5 duplicates of each observation
You could use:
X = unique(X,'rows'); % remove duplicate observations
D = pdist(X,'mahalanobis'); % distance between all remaining observations
Z = squareform(D); % to square matrix format

Using pca Crashes Matlab

For this problem, I do not understand why my MATLAB crashes every time I run my pca line. I am using pca on a matrix containing the anomalous faces as described below:
pics.mat contains a matrix data of 40 images each with dimensions of 96*64 pixels. (a matrix of 96*64*40)
My code for this section is:
%% problem 1a: finding average face
load('pics.mat'); % loads the file
% combines the 3d matrix into a 2d matrix
total = [pics(:, :, 1)];
for i = 2:40
total = [total + pics(:, :, i)];
end
size(total) %96 by 64
A1 = total/40 % the average values divided by total # of faces for avg face
%% problem 1b: the anomalous face
Anom = [];
for i = 1:40
Anom(:, :, i) = [pics(:, :, i) - A1]; % subtract the average face from all 40 images
end
What I am having trouble with is when I do this section which involves using pca on the 40 anomalous faces from part b, my MATLAB crashes.
My code for this section is:
%% problem 1c I: pca
Anom = reshape(Anom, [6144 40]); % reshapes a 3d into 2d
[eigenfaces,scores,sigma2] = pca(Anom', 'Centered' ,'off'); % this crashes MATLAB
Why is this crashing? Is it because of my code from the earlier sections or is it because of the fact that I am running this on an extremely anemic laptop?
I had a similar problem where dimensionality makes the calculation overwhelming.
This link of Cootes Active Shape Models, in Appendix C he transform his D to T to cope with matrix dimensionality.
I hope it could be applicable in your case too because it saved me from a lot of trouble.
This is how I solved it in MatLab:
imvecs = a vector of images
meanval = their mean value
size(imvecs,2) = the number of images in my data set (N)
function [T, D] = covarianceMatrix(imvecs, meanval)
D = [];
for i = 1:size(imvecs,2),
diff = imvecs{i} - meanval;
D = [D, diff];
end
%Dimensionality reduction
T = (D' * D) ./ (size(imvecs,2));
return
T is now a NxN sized matrix, which is hopefully easier to calculate without running out of memory.
Good luck!

Making sense of CCA (Matlab implementation) 2

I am using CCA for my work and want to understand something.
This is my MATLAB code. I have only taken 100 samples to better understand the concepts of CCA.
clc;clear all;close all;
load carbig;
data = [Displacement Horsepower Weight Acceleration MPG];
data(isnan(data))=0;
X = data(1:100,1:3);
Y = data(1:100,4:5);
[wx,wy,~,U,V] = CCA(X,Y);
clear Acceleration Cylinders Displacement Horsepower MPG Mfg Model Model_Year Origin Weight when org
subplot(1,2,1),plot(U(:,1),V(:,1),'.');
subplot(1,2,2),plot(U(:,2),V(:,2),'.');
My plots are coming like this:
This points out that in the 1st figure (left), the transformed variables are highly correlated with little scatter around the central axis. While in the 2nd figure(right), the scatter around the central axis is much more.
As I understand from here that CCA maximizes the correlation between the data in the transformed space. So I tried to design a matching score which should return a minimum value if the vectors are maximally correlated. I tried to match each vector of U(i,:) with that of V(j,:) with i,j going from 1 to 100.
%% Finding the difference between the projected vectors
for i=1:size(U,1)
cost = repmat(U(i,:),size(U,1),1)- V;
for j=1:size(U,1)
c(i,j) = norm(cost(j,:),size(U,2));
end
[~,idx(i)] = min(c(i,:));
end
Ideally idx should be like this :
idx = 1 2 3 4 5 6 7 8 9 10 ....
as they are maximally correlated. However my output comes something like this :
idx = 80 5 3 1 4 7 17 17 17 10 68 78 78 75 9 10 5 1 6 17 .....
I dont understand why this happens.
Am I wrong somewhere ? Isnt the vectors supposed to be maximally correlated in the transformed CCA subspace?
If my above assumption is wrong, please point me out in the correct direction.
Thanks in advance.
First, Let me transpose your code in R2014b:
load carbig;
data = [Displacement Horsepower Weight Acceleration MPG];
% Truncate the data, to follow-up with your sample code
data = data(1:100,:);
nans = sum(isnan(data),2) > 0;
[wx, wy, r, U, V,] = canoncorr(X(~nans,1:3),X(~nans,4:5));
OK, now the trick is that the vectors which are maximally correlated in the CCA subspace are the column vectors U(:,1) with V(:,1) and U(:,2) with V(:,2), and not the row vectors U(i,:), as you are trying to compute. In the CCA subspace, vectors should be N-dimensional (here N=100), and not simple 2D vectors. That's the reason why visualization of CCA results is often quite complicated !
By the way, the correlations are given by the third output of canoncorr, that you (intentionally ?) choosed to skip in your code. If you check its content, you'll see that the correlations (i.e. the vectors) are well-ordered:
r =
0.9484 0.5991
It is hard to explain CCA better than the link you already provided. If you want to go further, you should probably invest in a book, like this one or this one.

How to mark the peak with Matlab?

How can I use the plot function to mark the peak?
Example:
a = [0 1 3 23 3 9 10 28 2]
[p,locs] = findpeaks(a)
Result:
p =
23 28
locs =
4 8
You dont provide an x range so create one (you can change this to what you want).
figure
x = [1:length(a)];
plot(x,a,'k');
The above plots your original data points the following will
hold on
plot(locs,p,'ro');
plot your peaks as red circle points on top of the original series. If you need a non-integer x-range you will need to calculate the appropriate values that correspond to the indices in your locs array and use those x values instead.

Resampling Matrix and restoring in one single Matrix

I am new to this forum, so please bear with me.
I have been working on this Matlab problem for a while now:
I have a digital elevation model (DEM) new_sub(x,y) in tif format. So it is a x-by-y matrix containing heights (z). I wish to resample parts of this DEM in different resolutions and restore this in another matrix. So far I have been working with for loops to change the resolution of different areas of the DEM and then wrote the results to an xyz-file:
x y z
1 1 123
1 2 233
1 3 231
2 1 235
2 2 531
2 3 452
and so forth.
Here is the code:
xmax = size(new_sub,2);
ymax = size(new_sub,1);
for k=1:200 % y
for l=1:xmax % x
fprintf(fid, '%d %d %d \n',l,xmax+1-k,new_sub(k,l));
end
end
% 1:4
for k=200/2+1:size(new_sub,1)/2
for l=1:size(new_sub,2)/2
fprintf(fid, '%d %d %d \n',l*2,ymax+2-k*2,new_sub(k*2,l*2));
end
end
This does work, but seems to be rather complicated. Moreover, it does not allow me to store the resampled areas in a single matrix within Matlab.
Is there a more efficient way of resampling certain areas of a Matrix with different resolutions, writing them into a new Matrix containg all resampled areas and then writing it to a file? I was looking into repmap, but could not think of a clever way of using it!
Your help is much appreciated!
THeo
To re-sample a matrix in Matlab:
For example matrix M:
M = [1 2 3 4 5;
6 7 8 9 10;
11 12 13 14 15;
16 17 18 19 20;
21 22 23 24 25];
If we wanted to sample on every nth pixel, it is as simple as this:
m = M(1:n:end, 1:n:end)
So for n=2
m = 1 3 5
11 13 15
21 23 25
I suggest you read up on indexing in matlab and also on using the colon operator to create vectors in matlab
Now in order to get in the "x y z" format you mentioned, first use meshgrid to generate matrices of X and Y coordinates.
[X, Y] = meshgrid(1:n:size(M,1), 1:n:size(M,2))
notice I use n to downsample X and Y. Now you just need to flatten the three matrices and combine them:
final = [X(:), Y(:), m(:)]
Finally to save as a file I suggest you type help save or help dlmwrite in the Matlab command promt and use either of those functions to save final
To me the easiest way to do looks like using imresize. You can treat your elevation map as an image I. Then you can cut sections out by indexing and rescaling as follows:
I = imread('my.tiff'); % read
section = I(1:200, :); % cut the first 200 rows and all columns
sectionResized = imresize(section, [numrows numcols]) % resample
imwrite(sectionResized, 'mynew.tiff'); % save