matlab: align 3D shapes - matlab

I am looking for a way to align 3D shapes. I have matrices AB, A, and B, each contains a 3D item. Matrix AB is composed of A and B.
I would like to find the transformation (rotation, translation) needed for A and B to rebuild AB.
Do you have any methodology, or useful functions that could help me ?
Regards.

I think of the following approach:
First obtain transform matrices that will take care of the relevant degrees of freedom. Then use a non-linear optimization to minimize the binary 3D difference.
About the degrees of freedom:
Each object at a (x,y,z) position and (theta,phi,psi) angluar orientation (Euler). So one would think you'll need 6+6=12 degrees of freedom (or dimensions) to perform a search. However, the dimensionality is lower, because you have the constraint that the 2 bodies must be present, so it is enough to look for the relative spatial separation (dx,dy,dz) and the relative angular difference (theta,phi,psi) . In addition, we can ask whether there is symmetry in the shapes, for example, if on of the shapes is a sphere, angles are irrelevant, etc..
So for each degree of freedom I'd expect to have a relevant 3x3 transformation matrices, Rtheta,Rphi,Rpsi,Tx,Ty,Tz. where Rtheta looks something like:
Rtheta = [cos(theta) 0 -sin(theta) 0
0 1 0 0
sin(theta) 0 cos(theta) 0
0 0 0 1];
These matrices can be combined a general rotation matrix
Rot=Rtheta*Rphi*Rpsi;
and the similarly obtain the translation matrix Trans=Tx*Ty*Tz, Then
tform_Trans = maketform('affine', Trans);
tform_Rot = maketform('affine', Rot);
tform_RT = maketform('composite',tform_Rot,tform_Trans);
and the transform is applied using the function
tformarray(A, tform_RT, R, TDIMS_A, TDIMS_B, TSIZE_B, TMAP_B, F)
Check out a more detailed account of this in the following link.

Related

Partial fft of multidimensional array

I have a 3D array of dimension (NX,NY,NZ) which represents a variable in physical space, let's say velocities, taken from a simulation in a 3D domain.
1) I want to Fourier-transform only the dimensions X and Z, how should I use the built-in function fft in this case? At some point I want to also get back to the physical space, but only on X, so the same question applies.
2) I read that FFTW uses only 2*N/3 points, should I specify NX and NZ as the number of retained modes or fewer?
3) When using the FFTW package, is there any issue with the coefficient in front of the integral defining the Fourier transformation? Does this package assume that my domain is 2pix2pix2pi?
1°) The function for 2D FFT is fft2, and it will by default apply to the two first dimensions of the array. That is, fft2(velocities) will give you a 3D array with NZ Fourier transforms along dimensions X and Y
In order to do the FFT along other dimensions, you have to manually decompose the 2D FFT as two 1D FFTs. fft will work by default along dimension 1 and produce as many samples as there were in the input. fft(X[],n) does the same, but along dimension n.
Thus, you may compute a 2D FFT of your 3D array, along dimensions X and Z with the command:
my_FFT = fft(fft(velocities),[],3);
2°) There will be as many samples out as samples in.
3°) I believe the normalization by the size of the array is fully applied on the reverse transform, and not at all on the direct transform.
fft([1 0 0 0 0 0])
ans =
1 1 1 1 1 1
To maintain normalization, a coefficient sqrt(NX*NZ) should be applied (multiply when doing FFT, divide when doing an IFFT).

Finding length between a lot of elements

I have an image of a cytoskeleton. There are a lot of small objects inside and I want to calculate the length between all of them in every axis and to get a matrix with all this data. I am trying to do this in matlab.
My final aim is to figure out if there is any axis with a constant distance between the object.
I've tried bwdist and to use connected components without any luck.
Do you have any other ideas?
So, the end goal is that you want to globally stretch this image in a certain direction (linearly) so that the distances between nearest pairs end up the closest together, hopefully the same? Or may you do more complex stretching ? (note that with arbitrarily complex one you can always make it work :) )
If linear global one, distance in x' and y' is going to be a simple multiplication of the old distance in x and y, applied to every pair of points. So, the final euclidean distance will end up being sqrt((SX*x)^2 + (SY*y)^2), with SX being stretch in x and SY stretch in y; X and Y are distances in X and Y between pairs of points.
If you are interested in just "the same" part, solution is not so difficult:
Find all objects of interest and put their X and Y coordinates in a N*2 matrix.
Calculate distances between all pairs of objects in X and Y. You will end up with 2 matrices sized N*N (with 0 on the diagonal, symmetric and real, not sure what is the name for that type of matrix).
Find minimum distance (say this is between A an B).
You probably already have this. Now:
Take C. Make N-1 transformations, which all end up in C->nearestToC = A->B. It is a simple system of equations, you have X1^2*SX^2+Y1^2*SY^2 = X2^2*SX^2+Y2*SY^2.
So, first say A->B = C->A, then A->B = C->B, then A->B = C->D etc etc. Make sure transformation is normalized => SX^2 + SY^2 = 1. If it cannot be found, the only valid transformation is SX = SY = 0 which means you don't have solution here. Obviously, SX and SY need to be real.
Note that this solution is unique except in case where X1 = X2 and Y1 = Y2. In this case, grab some other point than C to find this transformation.
For each transformation check the remaining points and find all nearest neighbours of them. If distance is always the same as these 2 (to a given tolerance), great, you found your transformation. If not, this transformation does not work and you should continue with the next one.
If you want a transformation that minimizes variations between distances (but doesn't require them to be nearly equal), I would do some optimization method and search for a minimum - I don't know how to find an exact solution otherwise. I would pick this also in case you don't have linear or global stretch.
If i understand your question correctly, the first step is to obtain all of the objects center of mass points in the image as (x,y) coordinates. Then, you can easily compute all of the distances between all points. I suggest taking a look on a histogram of those distances which may provide some information as to the nature of distance distribution (for example if it is uniformly random, or are there any patterns that appear).
Obtaining the center of mass points is not an easy task, consider transforming the image into a binary one, or some sort of background subtraction with blob detection or/and edge detector.
For building a histogram you can use histogram.

Quadratic optimisation to compute a transformation matrix

I have two 3D meshes and on these meshes exists points that are mapped to each other and points with no mapping. For these points I want to calculate a mapping.
I want to do this by calculating a transformation Matrix for each point of one mesh that is already mapped to a point in the other mesh. Afterwards I want to calculate with an quadratic optimization the best possible mapping for all other points.
f(p) = T_i * p
(I'm using homogeneous coordinates - so every transfomation matrix should look like this:
1 0 0 a_i
0 1 0 b_i
0 0 1 c_i
0 0 0 1
Because of some not existing mathematics knowledge I stuck at this point, could somebody tell what exactly I need to feed matlab with that it gives me back an optimized transformation matrix, preferably with a quadratic optimization.
(and maybe an elegant way to do the transformation matrix calculation - actually I do it with a loop that runs over all points and calcs line by line the a_i, b_i, c_i and transforms them to a new matrix..., is there a function in matlab?)
Thanks in advance.

Is there a matlab function that converts a rotation matrix to acceleration vector?

Given some 3 x 3 rotation matrix with some constant acceleration A, I would like to find the component acceleration the three directions, ie, Ax,Ay,Az.
Though it's not difficult to just "reinvent the wheel", I am wondering if there's a Matlab function that does this already, particular in the Aerospace toolbox?
An NxN rotation matrix has N (N-1) / 2 embedded angles. The rotation of a unit right-hand-rule coordinate system into the orientation of R requires these many rotations. In your case there are three angles.
No, Matlab does not have such a built in function. I, too, rolled my own. Take care with the arc-tan's you'll need, certainly use the atan(y, x) form so that you don't lose a 180 deg rotation.
A rotation matrix is always a relative information, probably it gives the orientation relative to [1 0 0]. To get the components, you have to multiply:
R*[A;0;0]

Sampling uniformly from many circles on the sphere efficiently in matlab

I have a 3-by-N matrix X whose columns are vectors on the unit sphere (i.e., the Euclidean length of each vector is 1), and I have a 1-by-N vector Theta whose entries are all angles between 0 and pi. For each i, there is a circle on the sphere centered at X(:,i) defined as the set of all points that have the angle Theta(i) with X(:,i). I would like to get one uniform sample from the circle for each i, avoiding for loops because they can be slow in Matlab. I know that in vectorized Matlab code I can easily get one sample each from all circles with angles in Theta if I assume the center of all circles is [0,0,1], and then I know how to get a rotation matrix (using Rodrigues rotation formula) that rotates [0,0,1] to another desired vector x, so for each i, I can just apply this rotation matrix to the sample point I obtained assuming [0,0,1] was the center.
I would like to this for all i without for loops, i.e. using array/matrix/vector notation.
If you're using Rodrigues' rotation formula, you're trying to convert from axis-angle representation to rotation matrices. You're in luck. I happen to have written fast vectorized code to do exactly what I believe you're asking about. You can can find the code here: axang2rotmat.m. Use is pretty straightforward (read the help):
n = 1e3; % Number of axis-angles and rotation matrices
th = pi*rand(1,n); % Random rotation angles between 0 and pi
v = normc(rand(3,n)); % Random rotation vectors, normalized across columns
R = axang2rotmat(v,th); % Generate n rotation matrices, R is 3-by-3-n
Note, the above code is just to demonstrate the use of axang2rotmat and won't give you uniformly sampled rotation matrices (See Miles, Biometrika 1962 for details on why and workaround). I recommend that you calculate random rotation matrices directly, however. You can us another of my functions for that: randrotmat.m.
I also have code to convert back from rotation matrices to axis-angle and check if a particular matrix is a rotation matrix here.