Skip to content

Commit 366ccd8

Browse files
authored
Merge pull request InsightSoftwareConsortium#6268 from hjmjohnson/ingest-Thickness3D
ENH: Ingest ITKThickness3D into Modules/Filtering/Thickness3D
2 parents 63f6ddc + 6ae191d commit 366ccd8

16 files changed

Lines changed: 1684 additions & 51 deletions
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
project(Thickness3D)
2+
3+
itk_module_impl()
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*=========================================================================
2+
*
3+
* Copyright NumFOCUS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*=========================================================================*/
18+
#ifndef itkBinaryThinningImageFilter3D_h
19+
#define itkBinaryThinningImageFilter3D_h
20+
21+
#include "itkNeighborhoodIterator.h"
22+
#include "itkImageToImageFilter.h"
23+
#include "itkImageRegionIteratorWithIndex.h"
24+
#include "itkConstantBoundaryCondition.h"
25+
26+
namespace itk
27+
{
28+
/** \class BinaryThinningImageFilter3D
29+
*
30+
* \brief This filter computes one-pixel-wide skeleton of a 3D input image.
31+
*
32+
* This class is parametrized over the type of the input image
33+
* and the type of the output image.
34+
*
35+
* The input is assumed to be a binary image. All non-zero valued voxels
36+
* are set to 1 internally to simplify the computation. The filter will
37+
* produce a skeleton of the object. The output background values are 0,
38+
* and the foreground values are 1.
39+
*
40+
* A 26-neighbourhood configuration is used for the foreground and a
41+
* 6-neighbourhood configuration for the background. Thinning is performed
42+
* symmetrically in order to guarantee that the skeleton lies medial within
43+
* the object.
44+
*
45+
* This filter is a parallel thinning algorithm and is an implementation
46+
* of the algorithm described in:
47+
*
48+
* T.C. Lee, R.L. Kashyap, and C.N. Chu.
49+
* Building skeleton models via 3-D medial surface/axis thinning algorithms.
50+
* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994.
51+
*
52+
* To do: Make use of multi-threading.
53+
*
54+
* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK.
55+
*
56+
* \sa MorphologyImageFilter
57+
* \ingroup ImageEnhancement MathematicalMorphologyImageFilters Thickness3D
58+
*/
59+
60+
template <typename TInputImage, typename TOutputImage>
61+
class ITK_TEMPLATE_EXPORT BinaryThinningImageFilter3D : public ImageToImageFilter<TInputImage, TOutputImage>
62+
{
63+
public:
64+
ITK_DISALLOW_COPY_AND_MOVE(BinaryThinningImageFilter3D);
65+
66+
/** Standard class typedefs. */
67+
using Self = BinaryThinningImageFilter3D;
68+
using Superclass = ImageToImageFilter<TInputImage, TOutputImage>;
69+
using Pointer = SmartPointer<Self>;
70+
using ConstPointer = SmartPointer<const Self>;
71+
72+
/** Method for creation through the object factory */
73+
itkNewMacro(Self);
74+
75+
/** Run-time type information (and related methods). */
76+
itkOverrideGetNameOfClassMacro(BinaryThinningImageFilter3D);
77+
78+
/** Type for input image. */
79+
using InputImageType = TInputImage;
80+
81+
/** Type for output image: Skeleton of the object. */
82+
using OutputImageType = TOutputImage;
83+
84+
/** Type for the region of the input image. */
85+
using RegionType = typename InputImageType::RegionType;
86+
87+
/** Type for the index of the input image. */
88+
using IndexType = typename RegionType::IndexType;
89+
90+
/** Type for the pixel type of the input image. */
91+
using InputImagePixelType = typename InputImageType::PixelType;
92+
93+
/** Type for the pixel type of the input image. */
94+
using OutputImagePixelType = typename OutputImageType::PixelType;
95+
96+
/** Type for the size of the input image. */
97+
using SizeType = typename RegionType::SizeType;
98+
99+
/** Pointer Type for input image. */
100+
using InputImagePointer = typename InputImageType::ConstPointer;
101+
102+
/** Pointer Type for the output image. */
103+
using OutputImagePointer = typename OutputImageType::Pointer;
104+
105+
/** Boundary condition type for the neighborhood iterator */
106+
using ConstBoundaryConditionType = ConstantBoundaryCondition<TInputImage>;
107+
108+
/** Neighborhood iterator type */
109+
using NeighborhoodIteratorType = NeighborhoodIterator<TInputImage, ConstBoundaryConditionType>;
110+
111+
/** Neighborhood type */
112+
using NeighborhoodType = typename NeighborhoodIteratorType::NeighborhoodType;
113+
114+
/** Get Skeleton by thinning image. */
115+
OutputImageType *
116+
GetThinning();
117+
118+
/** ImageDimension enumeration */
119+
static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;
120+
static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;
121+
122+
#ifdef ITK_USE_CONCEPT_CHECKING
123+
/** Begin concept checking */
124+
itkConceptMacro(SameDimensionCheck, (Concept::SameDimension<InputImageDimension, 3>));
125+
itkConceptMacro(SameTypeCheck, (Concept::SameType<InputImagePixelType, OutputImagePixelType>));
126+
itkConceptMacro(InputAdditiveOperatorsCheck, (Concept::AdditiveOperators<InputImagePixelType>));
127+
itkConceptMacro(InputConvertibleToIntCheck, (Concept::Convertible<InputImagePixelType, int>));
128+
itkConceptMacro(IntConvertibleToInputCheck, (Concept::Convertible<int, InputImagePixelType>));
129+
itkConceptMacro(InputIntComparableCheck, (Concept::Comparable<InputImagePixelType, int>));
130+
/** End concept checking */
131+
#endif
132+
133+
protected:
134+
BinaryThinningImageFilter3D();
135+
~BinaryThinningImageFilter3D() override = default;
136+
void
137+
PrintSelf(std::ostream & os, Indent indent) const override;
138+
139+
/** Compute thinning Image. */
140+
void
141+
GenerateData() override;
142+
143+
/** Prepare data. */
144+
void
145+
PrepareData();
146+
147+
/** Compute thinning image. */
148+
void
149+
ComputeThinImage();
150+
151+
/** Check for Euler invariance (see [Lee94]). */
152+
bool
153+
IsEulerInvariant(const NeighborhoodType & neighbors, const int * LUT);
154+
155+
/** Fill the Euler look-up table (LUT) for later check of the Euler
156+
* invariance (see [Lee94]). */
157+
void
158+
FillEulerLUT(int * LUT);
159+
160+
/** Check if the current point is a simple point.
161+
* This method is named 'N(v)_labeling' in [Lee94].
162+
* Outputs the number of connected objects in a neighborhood of a point
163+
* after this point would have been removed. */
164+
bool
165+
IsSimplePoint(const NeighborhoodType & neighbors);
166+
167+
/** Recursive method that calculates the number of connected components in
168+
* the 3D neighbourhood after the center pixel would have been removed (see)
169+
* [Lee94]). */
170+
void
171+
OctreeLabeling(int octant, int label, int * cube);
172+
173+
}; // end of BinaryThinningImageFilter3D class
174+
175+
} // end namespace itk
176+
177+
#ifndef ITK_MANUAL_INSTANTIATION
178+
# include "itkBinaryThinningImageFilter3D.hxx"
179+
#endif
180+
181+
#endif // itkBinaryThinningImageFilter3D_h

0 commit comments

Comments
 (0)