|
| 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