sitk_registration_sys/lib.rs
1//! This crate does two things:
2//! - find an affine transform or translation that transforms one image into the other
3//! - use bspline or nearest neighbor interpolation to apply a transformation to an image
4//!
5//! To do this, [SimpleITK](https://github.com/SimpleITK/SimpleITK), which is written in
6//! C++, is used. An adapter library is created using [autocxx](https://crates.io/crates/autocxx)
7//! to expose the required functionality in SimpleITK. Because of this, compilation of this crate
8//! requires quite some time, several GB of memory, up to 50 GB of hard disk space, as well as
9//! cmake, a C++ compiler, llvm and git. Use at your own risk!
10//!
11//! # Examples
12//! ## Registration
13//! ```
14//! use ndarray::Array2;
15//! use sitk_registration_sys::registration::{AffineTransform, julia_image};
16//!
17//! let j = julia_image(0f32, 0f32).unwrap();
18//! let shape = j.shape();
19//! let origin = [
20//! ((shape[1] - 1) as f64) / 2f64,
21//! ((shape[0] - 1) as f64) / 2f64,
22//! ];
23//! let s = AffineTransform::new([1.2, 0., 0., 1., 5., 7.], origin, [shape[0], shape[1]]);
24//! let k: Array2<_> = s.transform_image_bspline(j.view()).unwrap().into();
25//! let t = AffineTransform::register_affine(j.view(), k.view()).unwrap().inverse().unwrap();
26//! let d = (t.matrix() - s.matrix()).powi(2).sum();
27//! assert!(d < 0.025, "d: {}, t: {:?}", d, t.parameters);
28//! ```
29//!
30//! ## Interpolation
31//! ```
32//! use ndarray::Array2;
33//! use sitk_registration_sys::registration::{AffineTransform, julia_image};
34//!
35//! let j = julia_image(-120f32, 10f32).unwrap();
36//! let k = julia_image(0f32, 0f32).unwrap();
37//! let shape = j.shape();
38//! let origin = [
39//! ((shape[1] - 1) as f64) / 2f64,
40//! ((shape[0] - 1) as f64) / 2f64,
41//! ];
42//! let transform = AffineTransform::new([1., 0., 0., 1., 120., -10.], origin, [shape[0], shape[1]]);
43//! let n: Array2<_> = transform.transform_image_bspline(j.view()).unwrap().into();
44//! let d = (k.mapv(|x| x as f64) - n.mapv(|x| x as f64)).powi(2).sum();
45//! assert!(d <= (shape[0] * shape[1]) as f64);
46//! ```
47
48extern crate link_cplusplus;
49pub mod registration;
50
51/// The bindings generated by [autocxx](https://google.github.io/autocxx).
52/// Everything in here is unsafe.
53pub use ffi::itk::simple;
54
55use autocxx::prelude::*;
56
57include_cpp! {
58 #include "sitkAdditionalProcedures.h"
59 #include "sitkAffineTransform.h"
60 #include "sitkElastixImageFilter.h"
61 #include "sitkInterpolator.h"
62 #include "sitkImage.h"
63 #include "sitkTransform.h"
64 safety!(unsafe)
65 generate!("itk::simple::AffineTransform")
66 generate!("itk::simple::ElastixImageFilter")
67 generate!("itk::simple::InterpolatorEnum")
68 generate!("itk::simple::Image")
69 generate!("itk::simple::Resample")
70 generate!("itk::simple::Transform")
71 opaque!("itk::simple::ElastixImageFilter") // deleted constructor
72}
73
74/// Manually generated bindings for some things that autocxx does not understand.
75#[cxx::bridge]
76pub mod ffi_extra {
77 unsafe extern "C++" {
78 include!("ffi_extra.h");
79
80 #[namespace = "itk::simple"]
81 type ElastixImageFilter = crate::ffi::itk::simple::ElastixImageFilter;
82 type ParameterMap;
83
84 fn new_parameter_map() -> UniquePtr<ParameterMap>;
85 fn insert(self: Pin<&mut ParameterMap>, key: &CxxString, value: &CxxVector<CxxString>);
86 fn keys(self: &ParameterMap) -> UniquePtr<CxxVector<CxxString>>;
87 fn get(self: &ParameterMap, key: &CxxString) -> UniquePtr<CxxVector<CxxString>>;
88
89 fn get_transform_parameter_map(
90 tfilter: &mut ElastixImageFilter,
91 index: u32,
92 ) -> UniquePtr<ParameterMap>;
93
94 fn get_default_parameter_map(kind: &CxxString) -> UniquePtr<ParameterMap>;
95
96 fn set_parameter_map(
97 tfilter: &mut ElastixImageFilter,
98 parameter_map: &UniquePtr<ParameterMap>,
99 );
100 }
101}