public class ICPRegistration
extends java.lang.Object
Modifier and Type | Class and Description |
---|---|
static class |
ICPRegistration.Prealign
Specifies whether to prealign the mesh using principal component analysis
(PCA), and if so, which of the resulting PCA axes to try.
|
Modifier and Type | Field and Description |
---|---|
static double |
myAdjustTime |
static double |
myDistanceTime |
static double |
myPCATime |
static boolean |
myProfiling |
Constructor and Description |
---|
ICPRegistration() |
Modifier and Type | Method and Description |
---|---|
void |
addAxisFlips(java.util.LinkedList<RotationMatrix3d> flips,
RotationMatrix3d R,
Vector3d axis,
int n) |
void |
computeAdjustment(AffineTransform3d dX,
int ndists,
int n)
Computes an adjustment
dX to the current AffineTransform3d
X such that dX moves all the points in such a
way as to minimize their distance to the surface. |
RotationMatrix3d[] |
computeFlips(Vector3d sig) |
double |
computeInertia(Matrix3d J,
Vector3d c,
PolygonalMesh mesh) |
static void |
computeOBBFromPCA(OBB obb,
MeshBase mesh)
Use PCA to determine the OBB for a mesh.
|
static double |
computePCA(Matrix3d J,
Vector3d c,
MeshBase mesh)
Based on "Non-rigid Transformations for Musculoskeletal Model", by Petr
Kellnhofer.
|
boolean |
isDualDistancingEnabled() |
void |
registerICP(AffineTransform3d X,
PolygonalMesh mesh1,
PolygonalMesh mesh2,
ICPRegistration.Prealign align,
int[] npar)
Computes an affine transform that tries to register
mesh2 onto
mesh1 , using an interative closest point (ICP) approach. |
void |
registerICP(AffineTransform3d X,
PolygonalMesh mesh1,
PolygonalMesh mesh2,
int... npar)
Computes an affine transform that tries to register mesh2 onto mesh1,
using an interative closest point (ICP) approach.
|
void |
registerInertia(AffineTransform3d X,
PolygonalMesh mesh1,
PolygonalMesh mesh2) |
void |
registerPCA(AffineTransform3d X,
PolygonalMesh mesh1,
PolygonalMesh mesh2) |
void |
setDualDistancingEnabled(boolean enable) |
public static boolean myProfiling
public static double myDistanceTime
public static double myAdjustTime
public static double myPCATime
public boolean isDualDistancingEnabled()
public void setDualDistancingEnabled(boolean enable)
public void computeAdjustment(AffineTransform3d dX, int ndists, int n)
dX
to the current AffineTransform3d
X
such that dX
moves all the points in such a
way as to minimize their distance to the surface. Specifically, we want
to move each point by a displacement dp_i
such that the
projection of this displacement onto the normal n_i
arising
from the nearest surface point equals the negative of the offset
o_i
from the surface:
n_i^T dp_i = -o_iNow,
dp_i
is determined by dX p_i
,
and dX
is itself described by n
independent
coordinates y
, where n
is either 3, 6, 7, or 12:
y0:y2
describing the translation parameters;y3:y5
describing the incremental yaw, pitch and roll angles;y6
describing the incremental scaling;y0:y2
describing the translation parameters and y3:y11
the coefficients of the 3 x 3 affine matrix.dX
takes the general form
[ y6 -y5 y4 y0 ] dX = [ y5 y6 -y3 y1 ] [ -y4 y3 y6 y2 ] [ 0 0 0 1 ]where
yi = 0
whenever i >= n
.
For each of the above cases, the relation
n_i^T dp_i = -o_i
can be expressed as
a_i^T y = -o_iwhere
a_i
is a n-vector formed from n_i
and p_i
.
Assembling these into a single matrix equation for all points, we end up with the linear least squares problem
A y = -owhere
A
is formed from individual rows a_i^T
and o
is formed from the aggregate of o_i
.
This least squares problem can be solved directly using the normal
equations approach:
A^T A y = -A^T oWe use this instead of QR decomposition for reasons of speed.
dX
- returns the computed adjustment transformndists
- number of points being adjustedn
- number of independent coordinates in dX. 3 corrresponds
to translation only, 6 to a rigid transform, 7 to a rigid
transform plus scaling, and 9 to a general affine transform.public static double computePCA(Matrix3d J, Vector3d c, MeshBase mesh)
public void registerPCA(AffineTransform3d X, PolygonalMesh mesh1, PolygonalMesh mesh2)
public void addAxisFlips(java.util.LinkedList<RotationMatrix3d> flips, RotationMatrix3d R, Vector3d axis, int n)
public RotationMatrix3d[] computeFlips(Vector3d sig)
public static void computeOBBFromPCA(OBB obb, MeshBase mesh)
public double computeInertia(Matrix3d J, Vector3d c, PolygonalMesh mesh)
public void registerInertia(AffineTransform3d X, PolygonalMesh mesh1, PolygonalMesh mesh2)
public void registerICP(AffineTransform3d X, PolygonalMesh mesh1, PolygonalMesh mesh2, int... npar)
registerICP(AffineTransform3d,PolygonalMesh,PolygonalMesh,Prealign,int[])
,
only with align
set to ICPRegistration.Prealign.PCA_ALL
and npar
specified as a variable argument list.
The computed transform X
is the transform that should be
applied to the vertex positions of mesh2
in order to register
them to mesh1
.
X
- returns the resulting transformmesh1
- target meshmesh2
- mesh to registernpar
- DOFs to use in the final registration, as well as
any preliminary registrationspublic void registerICP(AffineTransform3d X, PolygonalMesh mesh1, PolygonalMesh mesh2, ICPRegistration.Prealign align, int[] npar)
mesh2
onto
mesh1
, using an interative closest point (ICP) approach. The
resulting transform is returned in X
. The npar
argument
can be used to constrain the transform to rigid, rigid + scaling, or full
affine (rigid + scaling + shearing), as described below.
The computed transform X
is the transform that should be
applied to the vertex positions of mesh2
in order to register
them to mesh1
.
The align
argument can be used to specify whether or not to
try prealigning the orientation using principal component analysis:
ICPRegistration.Prealign.NONE
specifies no prealignment, while ICPRegistration.Prealign.PCA_ALL
specifies trying all possible PCA axis combinations for
the best fit.
The argument npar
contains integers specifying the number of
DOFs to be used in both the final registration transform, as well as any
preliminary registrations that should be applied first. The last integer
specifies the DOFs in the final transformation, while any previous
integers specify the preliminary registrations (in order). The integers
are restricted to the following values:
npar
containing the
sequence
3, 7would instruct the method to first perform a translational registration, and then finish with a final registration consisting of a rigid transform plus scaling. Likewise, an
npar
containing the sequence
6, 12would instruct the method to first perform a rigid registration, and then finish with a final full affine registration. Repeating numbers in
npar
simply requests that the same registration be performed
again.X
- returns the resulting transformmesh1
- target meshmesh2
- mesh to registeralign
- specifies whether or not to use PCA for prealignmentnpar
- DOFs to use in the final registration, as well as
any preliminary registrations