|
a |
|
b/src/labelStats.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 "itkImage.h" |
|
|
11 |
#include "itkLabelStatisticsImageFilter.h" |
|
|
12 |
#include "itkImageRegionIteratorWithIndex.h" |
|
|
13 |
|
|
|
14 |
#include "antsImage.h" |
|
|
15 |
|
|
|
16 |
namespace nb = nanobind; |
|
|
17 |
using namespace nb::literals; |
|
|
18 |
|
|
|
19 |
template< unsigned int Dimension > |
|
|
20 |
nb::dict labelStatsHelper( |
|
|
21 |
typename itk::Image< float, Dimension >::Pointer image, |
|
|
22 |
typename itk::Image< unsigned int, Dimension>::Pointer labelImage) |
|
|
23 |
{ |
|
|
24 |
typedef float PixelType; |
|
|
25 |
typedef itk::Image< PixelType, Dimension > ImageType; |
|
|
26 |
typedef unsigned int LabelType; |
|
|
27 |
typedef typename ImageType::PointType PointType; |
|
|
28 |
typedef itk::Image< LabelType, Dimension > LabelImageType; |
|
|
29 |
typedef itk::ImageRegionIteratorWithIndex<LabelImageType> Iterator; |
|
|
30 |
typedef itk::LabelStatisticsImageFilter< ImageType, LabelImageType > |
|
|
31 |
LabelStatisticsImageFilterType; |
|
|
32 |
typename LabelStatisticsImageFilterType::Pointer labelStatisticsImageFilter = |
|
|
33 |
LabelStatisticsImageFilterType::New(); |
|
|
34 |
labelStatisticsImageFilter->SetInput( image ); |
|
|
35 |
labelStatisticsImageFilter->SetLabelInput( labelImage ); |
|
|
36 |
labelStatisticsImageFilter->Update(); |
|
|
37 |
|
|
|
38 |
typedef typename LabelStatisticsImageFilterType::ValidLabelValuesContainerType |
|
|
39 |
ValidLabelValuesType; |
|
|
40 |
|
|
|
41 |
long nlabs = labelStatisticsImageFilter->GetNumberOfLabels(); |
|
|
42 |
|
|
|
43 |
std::vector<double> labelvals(nlabs); |
|
|
44 |
std::vector<double> means(nlabs); |
|
|
45 |
std::vector<double> mins(nlabs); |
|
|
46 |
std::vector<double> maxes(nlabs); |
|
|
47 |
std::vector<double> variances(nlabs); |
|
|
48 |
std::vector<double> counts(nlabs); |
|
|
49 |
std::vector<double> volumes(nlabs); |
|
|
50 |
std::vector<double> x(nlabs); |
|
|
51 |
std::vector<double> y(nlabs); |
|
|
52 |
std::vector<double> z(nlabs); |
|
|
53 |
std::vector<double> t(nlabs); |
|
|
54 |
std::vector<double> mass(nlabs,0.0); |
|
|
55 |
|
|
|
56 |
typename ImageType::SpacingType spacing = image->GetSpacing(); |
|
|
57 |
float voxelVolume = 1.0; |
|
|
58 |
for (unsigned int ii = 0; ii < spacing.Size(); ii++) |
|
|
59 |
{ |
|
|
60 |
voxelVolume *= spacing[ii]; |
|
|
61 |
} |
|
|
62 |
|
|
|
63 |
std::map<LabelType, LabelType> RoiList; |
|
|
64 |
|
|
|
65 |
LabelType ii = 0; // counter for label values |
|
|
66 |
for (typename ValidLabelValuesType::const_iterator |
|
|
67 |
labelIterator = labelStatisticsImageFilter->GetValidLabelValues().begin(); |
|
|
68 |
labelIterator != labelStatisticsImageFilter->GetValidLabelValues().end(); |
|
|
69 |
++labelIterator) |
|
|
70 |
{ |
|
|
71 |
if ( labelStatisticsImageFilter->HasLabel(*labelIterator) ) |
|
|
72 |
{ |
|
|
73 |
LabelType labelValue = *labelIterator; |
|
|
74 |
labelvals[ii] = labelValue; |
|
|
75 |
means[ii] = labelStatisticsImageFilter->GetMean(labelValue); |
|
|
76 |
mins[ii] = labelStatisticsImageFilter->GetMinimum(labelValue); |
|
|
77 |
maxes[ii] = labelStatisticsImageFilter->GetMaximum(labelValue); |
|
|
78 |
variances[ii] = labelStatisticsImageFilter->GetVariance(labelValue); |
|
|
79 |
counts[ii] = labelStatisticsImageFilter->GetCount(labelValue); |
|
|
80 |
volumes[ii] = labelStatisticsImageFilter->GetCount(labelValue) * voxelVolume; |
|
|
81 |
RoiList[ labelValue ] = ii; |
|
|
82 |
} |
|
|
83 |
++ii; |
|
|
84 |
} |
|
|
85 |
|
|
|
86 |
Iterator It( labelImage, labelImage->GetLargestPossibleRegion() ); |
|
|
87 |
std::vector<PointType> comvec; |
|
|
88 |
for ( unsigned int i = 0; i < nlabs; i++ ) |
|
|
89 |
{ |
|
|
90 |
typename ImageType::PointType myCenterOfMass; |
|
|
91 |
myCenterOfMass.Fill(0); |
|
|
92 |
comvec.push_back( myCenterOfMass ); |
|
|
93 |
} |
|
|
94 |
for( It.GoToBegin(); !It.IsAtEnd(); ++It ) |
|
|
95 |
{ |
|
|
96 |
LabelType label = static_cast<LabelType>( It.Get() ); |
|
|
97 |
if( label > 0 ) |
|
|
98 |
{ |
|
|
99 |
typename ImageType::PointType point; |
|
|
100 |
image->TransformIndexToPhysicalPoint( It.GetIndex(), point ); |
|
|
101 |
for( unsigned int i = 0; i < spacing.Size(); i++ ) |
|
|
102 |
{ |
|
|
103 |
comvec[ RoiList[ label ] ][i] += point[i]; |
|
|
104 |
} |
|
|
105 |
mass[ RoiList[ label ] ] += image->GetPixel( It.GetIndex() ); |
|
|
106 |
} |
|
|
107 |
} |
|
|
108 |
for ( unsigned int labelcount = 0; labelcount < comvec.size(); labelcount++ ) |
|
|
109 |
{ |
|
|
110 |
for ( unsigned int k = 0; k < Dimension; k++ ) |
|
|
111 |
{ |
|
|
112 |
comvec[ labelcount ][k] = comvec[ labelcount ][k] / counts[labelcount]; |
|
|
113 |
} |
|
|
114 |
x[labelcount]=comvec[ labelcount ][0]; |
|
|
115 |
y[labelcount]=comvec[ labelcount ][1]; |
|
|
116 |
if ( Dimension > 2 ) z[labelcount]=comvec[ labelcount ][2]; |
|
|
117 |
if ( Dimension > 3 ) t[labelcount]=comvec[ labelcount ][3]; |
|
|
118 |
} |
|
|
119 |
|
|
|
120 |
nb::dict labelStats; |
|
|
121 |
labelStats["LabelValue"] = labelvals; |
|
|
122 |
labelStats["Mean"] = means; |
|
|
123 |
labelStats["Min"] = mins; |
|
|
124 |
labelStats["Max"] = maxes; |
|
|
125 |
labelStats["Variance"] = variances; |
|
|
126 |
labelStats["Count"] = counts; |
|
|
127 |
labelStats["Volume"] = volumes; |
|
|
128 |
labelStats["Mass"] = mass; |
|
|
129 |
labelStats["x"] = x; |
|
|
130 |
labelStats["y"] = y; |
|
|
131 |
labelStats["z"] = z; |
|
|
132 |
labelStats["t"] = t; |
|
|
133 |
|
|
|
134 |
return (labelStats); |
|
|
135 |
} |
|
|
136 |
|
|
|
137 |
template <unsigned int Dimension> |
|
|
138 |
nb::dict labelStats(AntsImage<itk::Image<float, Dimension>> & py_image, |
|
|
139 |
AntsImage<itk::Image<unsigned int, Dimension>> & py_labelImage) |
|
|
140 |
{ |
|
|
141 |
typedef itk::Image<float, Dimension> FloatImageType; |
|
|
142 |
typedef itk::Image<unsigned int, Dimension> IntImageType; |
|
|
143 |
typedef typename FloatImageType::Pointer FloatImagePointerType; |
|
|
144 |
typedef typename IntImageType::Pointer IntImagePointerType; |
|
|
145 |
|
|
|
146 |
|
|
|
147 |
FloatImagePointerType myimage = py_image.ptr; |
|
|
148 |
IntImagePointerType mylabelimage = py_labelImage.ptr; |
|
|
149 |
|
|
|
150 |
return labelStatsHelper<Dimension>( myimage, mylabelimage ); |
|
|
151 |
} |
|
|
152 |
|
|
|
153 |
void local_labelStats(nb::module_ &m) |
|
|
154 |
{ |
|
|
155 |
m.def("labelStats2D", &labelStats<2>); |
|
|
156 |
m.def("labelStats3D", &labelStats<3>); |
|
|
157 |
m.def("labelStats4D", &labelStats<4>); |
|
|
158 |
} |