/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkKLMSegmentationRegion_h #define itkKLMSegmentationRegion_h #include "itkKLMSegmentationBorder.h" #include "itkSegmentationRegion.h" #include "ITKKLMRegionGrowingExport.h" #include "vnl/vnl_vector.h" namespace itk { /** * \class KLMSegmentationRegion * \brief Base class for KLMSegmentationRegion object * * itkKLMSegmentationRegion is the base class for the KLMSegmentationRegion * objects. It provides the basic function definitions that are inherent to * KLMSegmentationRegion objects. * * This object supports data handling of multiband images. The object * accepts images in vector format, where each pixel is a vector and each * element of the vector corresponds to an entry from 1 particular band of * a multiband dataset. * * We expect the user to provide the input to the routine in vector format. * A single band image is treated as a vector image with a single element * for every vector. * * Data structure for a region: * A region is defined as a closed area in the image that is surrounded * by a list of borders objects (see itkKLMSegmentationBorder class). * * Shown below is an initial two-dimensional 8x9 image with a 4x3 grid size * partition. The initial region blocks are labelled in hexadecimal. * Below the grid partition, the borders are shown as E, where C * is an image pixel from the initial image. Note that each border is * placed in between two regions. Each two-dimensional region is * surrounded by four borders. * * Initial regions of a 8 by 9 image with a 4 by 3 grid partition. * \f[\begin{tabular}{|c|c|c|c|c|c|c|c|c|} * \hline * 1 & 1 & 1 & 2 & 2 & 2 & 3 & 3 & 3 \\ \hline * 1 & 1 & 1 & 2 & 2 & 2 & 3 & 3 & 3 \\ \hline * 4 & 4 & 4 & 5 & 5 & 5 & 6 & 6 & 6 \\ \hline * 4 & 4 & 4 & 5 & 5 & 5 & 6 & 6 & 6 \\ \hline * 7 & 7 & 7 & 8 & 8 & 8 & 9 & 9 & 9 \\ \hline * 7 & 7 & 7 & 8 & 8 & 8 & 9 & 9 & 9 \\ \hline * a & a & a & b & b & b & c & c & c \\ \hline * a & a & a & b & b & b & c & c & c \\ \hline * \end{tabular}\f] * * Region borders are shown as "E". * \f[\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|} * \hline * C & C & C & & C & C & C & & C & C & C \\ \hline * C & C & C & E & C & C & C & E & C & C & C \\ \hline * & E & & & & E & & & & E & \\ \hline * C & C & C & & C & C & C & & C & C & C \\ \hline * C & C & C & E & C & C & C & E & C & C & C \\ \hline * & E & & & & E & & & & E & \\ \hline * C & C & C & & C & C & C & & C & C & C \\ \hline * C & C & C & E & C & C & C & E & C & C & C \\ \hline * & E & & & & E & & & & E & \\ \hline * C & C & C & & C & C & C & & C & C & C \\ \hline * C & C & C & E & C & C & C & E & C & C & C \\ \hline * \end{tabular}\f] * * \ingroup RegionGrowingSegmentation * \ingroup ITKKLMRegionGrowing */ // Forward reference because of circular dependencies class ITK_FORWARD_EXPORT KLMSegmentationBorder; class ITKKLMRegionGrowing_EXPORT KLMSegmentationRegion : public SegmentationRegion { public: ITK_DISALLOW_COPY_AND_MOVE(KLMSegmentationRegion); /** Standard class type aliases. */ using Self = KLMSegmentationRegion; using Superclass = SegmentationRegion; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(KLMSegmentationRegion); /** Type definition for an double vector. */ using MeanRegionIntensityType = vnl_vector; /** Type definition for vector container that stores the borders * associated with a current region. */ using RegionBorderVectorType = std::vector; using RegionBorderVectorSizeType = RegionBorderVectorType::size_type; /** Type definition for the region border vector iterators to be used. */ using RegionBorderVectorIterator = RegionBorderVectorType::iterator; /** Type definition for the const region border vector iterators to be used. */ using RegionBorderVectorConstIterator = RegionBorderVectorType::const_iterator; /** type definition for the region label type. */ using RegionLabelType = Superclass::RegionLabelType; /** Get a head pointer to the vector container storing the borders * associated with a region. */ RegionBorderVectorIterator GetRegionBorderItBegin(); RegionBorderVectorConstIterator GetRegionBorderConstItBegin(); /** Get a tail pointer to the vector container storing the borders * associated with a region. */ RegionBorderVectorIterator GetRegionBorderItEnd(); RegionBorderVectorConstIterator GetRegionBorderConstItEnd(); /** Get the number of borders in the vector container storing the borders * associated with a region. */ RegionBorderVectorSizeType GetRegionBorderSize() const; /** Set/Get the mean pixel intensity in the region. */ itkSetMacro(MeanRegionIntensity, MeanRegionIntensityType); itkGetConstReferenceMacro(MeanRegionIntensity, MeanRegionIntensityType); /** Set the region with parameter values * defining the region. */ void SetRegionParameters(MeanRegionIntensityType meanRegionIntensity, double regionArea, RegionLabelType label); /** Function to print the region parameters using std::cout. */ void PrintRegionInfo(); /** Insert a region border to the front of the list. */ void PushFrontRegionBorder(KLMSegmentationBorder * pBorderCandidate); /** Insert a region border to the back of the list. */ void PushBackRegionBorder(KLMSegmentationBorder * pBorderCandidate); /** Insert a region border to the list, where position is unknown * (sorting based on region labels is done to maintain consistency). */ void InsertRegionBorder(KLMSegmentationBorder * pBorderCandidate); /** Insert a region border into the border list at a given location. */ void InsertRegionBorder(RegionBorderVectorIterator RegionBorderVectorIt, KLMSegmentationBorder * pBorderCandidate); /** Delete a region border from the border list. */ void DeleteRegionBorder(KLMSegmentationBorder * pBorderCandidate); /** Delete all region borders in the border list. */ void DeleteAllRegionBorders(); /** Set the region with parameter values (mean and area) * defining the region when merged with the new region. */ void CombineRegionParameters(const Self * region); /** Compute the energy cost (mean squared difference scaled by area) * that would result if this region is merged with another region. */ double EnergyFunctional(const Self * region); /** Reset a region's label to that of the supplied region and update * the regions borders to that of the supplied region. */ void ResetRegionLabelAndUpdateBorders(Self * region); /** Splice the regions borders from the new region into the current * region. If duplicate borders are found, the duplicate border * region is not inserted into the new region borders list, rather, * it has its pointers to region1 and region2 set to nullptr and * Lambda set to -1.0. * * For example, take an image with 3 regions A, B, C * \f[\begin{tabular}{|c|c|} * \hline * A & A \\ \hline * B & C \\ \hline * \end{tabular}\f] * where region A has region borders A-B and A-C; * region B has region borders A-B and B-C; and * region C has region borders A-C and B-C. * * Suppose region border A-B has been removed, so that region B * can be merged into region A. When splicing the region * borders from A and B into the new region A, duplicate * region borders A-C and A-C (one of which was formerly B-C) * will be present. In this case, one of the region borders * A-C is given the combined length of the two former borders * and is put into the region borders list. The other is * nullified by having its pointers to region1 and region2 set * to nullptr and its Lambda value set to -1.0. */ void SpliceRegionBorders(Self * region); /** Recalculate the Lambda values using EvaluateLambda() for all * the borders defining the region. */ void UpdateRegionBorderLambda(); protected: KLMSegmentationRegion(); ~KLMSegmentationRegion() override; void PrintSelf(std::ostream & os, Indent indent) const override; private: RegionBorderVectorType m_RegionBorderVector{}; MeanRegionIntensityType m_MeanRegionIntensity{}; }; // class SegmentationRegion } // namespace itk #endif