|
a |
|
b/src/reorientImage.cxx |
|
|
1 |
|
|
|
2 |
#include <nanobind/nanobind.h> |
|
|
3 |
#include <nanobind/stl/vector.h> |
|
|
4 |
#include <nanobind/stl/string.h> |
|
|
5 |
#include <nanobind/stl/tuple.h> |
|
|
6 |
#include <nanobind/stl/list.h> |
|
|
7 |
#include <nanobind/ndarray.h> |
|
|
8 |
#include <nanobind/stl/shared_ptr.h> |
|
|
9 |
|
|
|
10 |
#include <exception> |
|
|
11 |
#include <vector> |
|
|
12 |
#include <string> |
|
|
13 |
|
|
|
14 |
#include "itkAffineTransform.h" |
|
|
15 |
#include "itkImage.h" |
|
|
16 |
#include "itkImageFileWriter.h" |
|
|
17 |
#include "itkImageMomentsCalculator.h" |
|
|
18 |
#include "itkResampleImageFilter.h" |
|
|
19 |
#include "itkTransformFileWriter.h" |
|
|
20 |
#include "vnl/vnl_inverse.h" |
|
|
21 |
|
|
|
22 |
#include "antsImage.h" |
|
|
23 |
|
|
|
24 |
namespace nb = nanobind; |
|
|
25 |
using namespace nb::literals; |
|
|
26 |
|
|
|
27 |
/* |
|
|
28 |
template< unsigned int ImageDimension > |
|
|
29 |
int antsReoHelper( |
|
|
30 |
typename itk::Image< float , ImageDimension >::Pointer image1, |
|
|
31 |
std::string txfn, std::vector<int> axis , std::vector<int> axis2, |
|
|
32 |
std::vector<int> doReflection, std::vector<int> doScale ) |
|
|
33 |
{ |
|
|
34 |
typedef double RealType; |
|
|
35 |
typedef itk::Image< float , ImageDimension > ImageType; |
|
|
36 |
|
|
|
37 |
typedef typename itk::ImageMomentsCalculator<ImageType> ImageCalculatorType; |
|
|
38 |
typedef itk::AffineTransform<RealType, ImageDimension> AffineType; |
|
|
39 |
typedef typename ImageCalculatorType::MatrixType MatrixType; |
|
|
40 |
typedef itk::Vector<float, ImageDimension> VectorType; |
|
|
41 |
VectorType ccg1; |
|
|
42 |
VectorType cpm1; |
|
|
43 |
MatrixType cpa1; |
|
|
44 |
VectorType ccg2; |
|
|
45 |
VectorType cpm2; |
|
|
46 |
MatrixType cpa2; |
|
|
47 |
typename ImageCalculatorType::Pointer calculator1 = |
|
|
48 |
ImageCalculatorType::New(); |
|
|
49 |
calculator1->SetImage( image1 ); |
|
|
50 |
typename ImageCalculatorType::VectorType fixed_center; |
|
|
51 |
fixed_center.Fill(0); |
|
|
52 |
|
|
|
53 |
// was a try-catch block around this in ANTsR |
|
|
54 |
calculator1->Compute(); |
|
|
55 |
fixed_center = calculator1->GetCenterOfGravity(); |
|
|
56 |
ccg1 = calculator1->GetCenterOfGravity(); |
|
|
57 |
cpm1 = calculator1->GetPrincipalMoments(); |
|
|
58 |
cpa1 = calculator1->GetPrincipalAxes(); |
|
|
59 |
|
|
|
60 |
unsigned int eigind1 = 1; |
|
|
61 |
unsigned int eigind2 = 1; |
|
|
62 |
typedef vnl_vector<RealType> EVectorType; |
|
|
63 |
typedef vnl_matrix<RealType> EMatrixType; |
|
|
64 |
EVectorType evec1_2ndary = cpa1.GetVnlMatrix().get_row( eigind2 ); |
|
|
65 |
EVectorType evec1_primary = cpa1.GetVnlMatrix().get_row( eigind1 ); |
|
|
66 |
EVectorType evec2_2ndary; |
|
|
67 |
evec2_2ndary.set_size( ImageDimension ); |
|
|
68 |
evec2_2ndary.fill(0); |
|
|
69 |
EVectorType evec2_primary; |
|
|
70 |
evec2_primary.set_size( ImageDimension ); |
|
|
71 |
evec2_primary.fill(0); |
|
|
72 |
for ( unsigned int i = 0; i < ImageDimension; i++ ) |
|
|
73 |
evec2_primary[i] = axis[i]; |
|
|
74 |
// Solve Wahba's problem http://en.wikipedia.org/wiki/Wahba%27s_problem |
|
|
75 |
EMatrixType B = outer_product( evec2_primary, evec1_primary ); |
|
|
76 |
if( ImageDimension == 3 ) |
|
|
77 |
{ |
|
|
78 |
for ( unsigned int i = 0; i < ImageDimension; i++ ) |
|
|
79 |
evec2_primary[i] = axis2[i]; |
|
|
80 |
B = outer_product( evec2_2ndary, evec1_2ndary ) |
|
|
81 |
+ outer_product( evec2_primary, evec1_primary ); |
|
|
82 |
} |
|
|
83 |
vnl_svd<RealType> wahba( B ); |
|
|
84 |
vnl_matrix<RealType> A_solution = wahba.V() * wahba.U().transpose(); |
|
|
85 |
A_solution = vnl_inverse( A_solution ); |
|
|
86 |
RealType det = vnl_determinant( A_solution ); |
|
|
87 |
if( det < 0 ) |
|
|
88 |
{ |
|
|
89 |
vnl_matrix<RealType> id( A_solution ); |
|
|
90 |
id.set_identity(); |
|
|
91 |
for( unsigned int i = 0; i < ImageDimension; i++ ) |
|
|
92 |
{ |
|
|
93 |
if( A_solution( i, i ) < 0 ) |
|
|
94 |
{ |
|
|
95 |
id( i, i ) = -1.0; |
|
|
96 |
} |
|
|
97 |
} |
|
|
98 |
A_solution = A_solution * id.transpose(); |
|
|
99 |
} |
|
|
100 |
if ( doReflection[0] == 1 || doReflection[0] == 3 ) |
|
|
101 |
{ |
|
|
102 |
vnl_matrix<RealType> id( A_solution ); |
|
|
103 |
id.set_identity(); |
|
|
104 |
id = id - 2.0 * outer_product( evec2_primary , evec2_primary ); |
|
|
105 |
A_solution = A_solution * id; |
|
|
106 |
} |
|
|
107 |
if ( doReflection[0] > 1 ) |
|
|
108 |
{ |
|
|
109 |
vnl_matrix<RealType> id( A_solution ); |
|
|
110 |
id.set_identity(); |
|
|
111 |
id = id - 2.0 * outer_product( evec1_primary , evec1_primary ); |
|
|
112 |
A_solution = A_solution * id; |
|
|
113 |
} |
|
|
114 |
if ( doScale[0] > 0 ) |
|
|
115 |
{ |
|
|
116 |
vnl_matrix<RealType> id( A_solution ); |
|
|
117 |
id.set_identity(); |
|
|
118 |
id = id * doScale[0]; |
|
|
119 |
A_solution = A_solution * id; |
|
|
120 |
} |
|
|
121 |
det = vnl_determinant( A_solution ); |
|
|
122 |
std::cout << " det " << det << std::endl; |
|
|
123 |
std::cout << " A_solution " << std::endl; |
|
|
124 |
std::cout << A_solution << std::endl; |
|
|
125 |
typename AffineType::Pointer affine1 = AffineType::New(); |
|
|
126 |
typename AffineType::OffsetType trans = affine1->GetOffset(); |
|
|
127 |
itk::Point<RealType, ImageDimension> trans2; |
|
|
128 |
trans2.Fill(0); |
|
|
129 |
for( unsigned int i = 0; i < ImageDimension; i++ ) |
|
|
130 |
{ |
|
|
131 |
trans2[i] = fixed_center[i] * ( 1 ); |
|
|
132 |
} |
|
|
133 |
affine1->SetIdentity(); |
|
|
134 |
affine1->SetOffset( trans ); |
|
|
135 |
affine1->SetMatrix( A_solution ); |
|
|
136 |
affine1->SetCenter( trans2 ); |
|
|
137 |
// write tx |
|
|
138 |
typedef itk::TransformFileWriter TransformWriterType; |
|
|
139 |
typename TransformWriterType::Pointer transformWriter = TransformWriterType::New(); |
|
|
140 |
transformWriter->SetInput( affine1 ); |
|
|
141 |
transformWriter->SetFileName( txfn.c_str() ); |
|
|
142 |
transformWriter->Update(); |
|
|
143 |
|
|
|
144 |
return 0; |
|
|
145 |
|
|
|
146 |
} |
|
|
147 |
|
|
|
148 |
template <typename ImageType, unsigned int Dimension> |
|
|
149 |
int reorientImage( py::capsule in_image, std::string txfn, |
|
|
150 |
std::vector<int> axis1, std::vector<int> axis2, |
|
|
151 |
std::vector<int> rrfl, std::vector<int> rscl ) |
|
|
152 |
{ |
|
|
153 |
typedef typename ImageType::Pointer ImagePointerType; |
|
|
154 |
ImagePointerType itk_image = as<ImageType>( in_image ); |
|
|
155 |
antsReoHelper<Dimension>( itk_image, txfn, axis1, axis2, rrfl, rscl ); |
|
|
156 |
|
|
|
157 |
return 0; |
|
|
158 |
} |
|
|
159 |
|
|
|
160 |
*/ |
|
|
161 |
|
|
|
162 |
|
|
|
163 |
template <typename ImageType, unsigned int Dimension> |
|
|
164 |
std::vector<double> centerOfMass( AntsImage<ImageType> & image ) |
|
|
165 |
{ |
|
|
166 |
typedef typename ImageType::Pointer ImagePointerType; |
|
|
167 |
ImagePointerType itkimage = image.ptr; |
|
|
168 |
|
|
|
169 |
typedef typename itk::ImageMomentsCalculator<ImageType> ImageCalculatorType; |
|
|
170 |
typename ImageCalculatorType::VectorType com( Dimension ); |
|
|
171 |
com.Fill( 0 ); |
|
|
172 |
|
|
|
173 |
std::vector<double> myCoM( Dimension ); |
|
|
174 |
|
|
|
175 |
typename ImageCalculatorType::Pointer calculator1 = ImageCalculatorType::New(); |
|
|
176 |
calculator1->SetImage( itkimage ); |
|
|
177 |
calculator1->Compute(); |
|
|
178 |
com = calculator1->GetCenterOfGravity(); |
|
|
179 |
|
|
|
180 |
for ( unsigned int k = 0; k < Dimension; k++ ) |
|
|
181 |
{ |
|
|
182 |
myCoM[ k ] = com[ k ]; |
|
|
183 |
} |
|
|
184 |
|
|
|
185 |
return myCoM; |
|
|
186 |
} |
|
|
187 |
|
|
|
188 |
void local_reorientImage(nb::module_ &m) |
|
|
189 |
{ |
|
|
190 |
// m.def("reorientImageF2", &reorientImage<itk::Image<float, 2>, 2>); |
|
|
191 |
// m.def("reorientImageF3", &reorientImage<itk::Image<float, 3>, 3>); |
|
|
192 |
// m.def("reorientImageF4", &reorientImage<itk::Image<float, 4>, 4>); |
|
|
193 |
|
|
|
194 |
m.def("centerOfMass", ¢erOfMass<itk::Image<float, 2>, 2>); |
|
|
195 |
m.def("centerOfMass", ¢erOfMass<itk::Image<float, 3>, 3>); |
|
|
196 |
m.def("centerOfMass", ¢erOfMass<itk::Image<float, 4>, 4>); |
|
|
197 |
} |