C++ implementation of the Coherent Point Drift point set registration algorithm
C++ CMake Shell
Clone or download
Pull request Compare This branch is 98 commits behind gadomski:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
cmake
include/cpd
scripts
src
test
vendor/gtest-1.7.0
.appveyor.yml
.clang-format
.travis.yml
CMakeLists.txt
Doxyfile.in
LICENSE.txt
README.md
STYLE.md

README.md

cpd

Coherent Point Drift (CPD) is a point-set registration algorithm, originally developed by Andriy Myronenko et al. This is a C++ library that runs CPD.

CPD can be compared to Iterative Closest Point, another point-set registration algorithm that is widely used. While ICP minimizes point-to-point distances, CPD uses a Gaussian Mixture Model to minimize the error between a point and all other points. If you're thinking that this is very computationally intensive, you're right — both the CPD algorithm and the underlying error calculations take a lot of time, which is why we've created fgt to speed up those Gauss transforms. We hope this library provides a freer and more performant alternative to the original reference Matlab implementation.

This library supports three variants of CPD:

  • rigid: Uses a rigid transformation (i.e. rotation and translation, with an optional scaling) to align the two datasets.
  • nonrigid: Uses a two-parameter non-rigid transformation function to align the two datasets.
  • affine: Uses an affine transformation (with an optional scaling) to align the two datasets.

Andriy's reference implementation comes with one other type of registration, nonrigid_lowrank, which is not implemented in the latest version of this library (yet) (see History for information on how to find and use a previous version of this library that has nonrigid_lowrank).

This code lives on Github. It has some Doxygen documentation and is tested by Travis and by AppVeyor. We also have a gitter chatroom.

Build Status Build status

Usage

cpd has a simple functional interface, which accepts Eigen matrices and aligns them using some sensible default parameters:

#include <cpd/rigid.hpp>

cpd::RigidResult align_with_rigid(const Eigen::MatrixXd& X, const Eigen::MatrixXd& Y) {
    return cpd::rigid(X, Y);
}

If you want more control over the parameters, you can use the class-based interface:

#include <cpd/rigid.hpp>

cpd::RigidResult align_with_rigid(const Eigen::MatrixXd& X, const Eigen::MatrixXd& Y) {
    cpd::Rigid rigid;
    rigid.allow_scaling(true).no_reflections(false);
    return rigid.compute(X, Y);
}

Installation

cpd depends on fgt at runtime and CMake and Eigen at build-time.

On OSX

If you're on a Mac, use homebrew and my tap to install:

brew tap gadomski/gadomski
brew install cpd

From source

Install fgt (which also requires Eigen) and CMake, then use the usual CMake build incantation for cpd:

mkdir build
cd build
cmake ..
make

Using downstream

cpd provides CMake export targets that you can import and use in your own project:

find_package(Cpd REQUIRED)
add_library(my-great-library
    the_code.cpp
    )
target_link_libraries(my-great-library
    PUBLIC
    Cpd::Library-C++
    )

The Cpd::Library-C++ target includes all the interface settings you need, so you shouldn't need any other calls to get set up.

OpenMP

Both fgt and Eigen support OpenMP for some operations. As of yet, the interaction between the two is untested, so our official recommendation is to only use OpenMP with one of the projects, not both. If you do some work with OpenMP we'd love to hear how it goes.

Contributing

Github issues and pull requests, per usual.

History

The v0.1 and v0.2 lineages of cpd used armadillo for linear arithmetic instead of Eigen. Armadillo is a bit smoother for doing advanced eigenvalue decompositions and other operations, which made it a bit easier at first to directly port the Matlab reference implementation. For a couple of reasons, we decided to switch to Eigen for v0.3.

First, the Armadillo project had the bad habit of removing old versions from their download site, making it hard to maintain working code as their codebase developed. Second, many downstream applications use Eigen themselves, making Eigen a lower-friction choice for those users.

As of this writing, the Eigen implementation is less feature-full than the old Armadillo implementation, particularly with respect to the nonrigid_lowrank version. If you require some of that old functionality, use the v0.2 branch. If you need armadillo-5.x, which is required for the old cpd but is no longer available from the armadillo website, you can use my mirror. Thanks for your understanding during this switch.

License

This library is GPL2, copyright 2016 Peter J. Gadomski. See LICENSE.txt for the full license text.

This work is directly inspired by Andriy Myronenko's reference implementation, and we owe him many thanks.