1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
|
/*=========================================================================
*
* 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 itkFastMarchingBase_h
#define itkFastMarchingBase_h
#include "itkIntTypes.h"
#include "itkFastMarchingStoppingCriterionBase.h"
#include "itkFastMarchingTraits.h"
#include "ITKFastMarchingExport.h"
#include <queue>
#include <functional>
namespace itk
{
/**
* \class FastMarchingTraitsEnums
* \ingroup ITKFastMarching
* */
class FastMarchingTraitsEnums
{
public:
/**
* \class TopologyCheck
* \ingroup ITKFastMarching
* */
enum class TopologyCheck : uint8_t
{
Nothing = 0,
NoHandles,
Strict
};
};
// Define how to print enumeration
extern ITKFastMarching_EXPORT std::ostream &
operator<<(std::ostream & out, const FastMarchingTraitsEnums::TopologyCheck value);
/**
* \class FastMarchingBase
* \brief Abstract class to solve an Eikonal based-equation using Fast Marching
* Method.
*
* Fast marching solves an Eikonal equation where the speed is always
* non-negative and depends on the position only. Starting from an
* initial position on the front, fast marching systematically moves the
* front forward one node at a time.
*
* Updates are performed using an entropy satisfy scheme where only
* "upwind" neighborhoods are used. This implementation of Fast Marching
* uses a std::priority_queue to locate the next proper node to
* update.
*
* Fast Marching sweeps through N points in (N log N) steps to obtain
* the arrival time value as the front propagates through the domain.
*
* The initial front is specified by two containers:
* \li one containing the known nodes (Alive Nodes: nodes that are already
* part of the object),
* \li one containing the trial nodes (Trial Nodes: nodes that are
* considered for inclusion).
*
* In order for the filter to evolve, at least some trial nodes must be
* specified. These can for instance be specified as the layer of
* nodes around the alive ones.
*
* The algorithm is terminated early by setting an appropriate stopping
* criterion, or if there are no more nodes to process.
*
* \tparam TTraits traits which includes definition such as:
* \li InputDomainType (itk::Image or itk::QuadEdgeMesh)
* \li OutputDomainType (similar to InputDomainType)
* \li NodeType (itk::Index if itk::Image and PointIdentifier if
* itk::QuadEdgeMesh)
* \li NodePairType std::pair< NodeType, OutputPixelType >
* \li Superclass (itk::ImageToImageFilter or
* itk::QuadEdgeMeshToQuadEdgeMeshFilter )
*
* \todo In the current implementation, std::priority_queue only allows
* taking nodes out from the front and putting nodes in from the back.
* Use itk::PriorityQueueContainer instead.
*
* \par Topology constraints:
* Additional flexibility in this class includes the implementation of
* topology constraints for image-based fast marching. Further details
* can be found in the paper
*
* NJ Tustison, BA Avants, MF Siqueira, JC Gee. "Topological Well-
* Composedness and Glamorous Glue: A Digital Gluing Algorithm for
* Topologically Constrained Front Propagation, IEEE Transactions on
* Image Processing, 20(6):1756-1761, June 2011.
*
* Essentially, one can constrain the propagating front(s) such that
* they either:
* 1. don't merge (using the "Strict" option)
* 2. don't create handles (using the "NoHandles" option)
*
* Whereas the majority of related work uses the digital topological
* concept of "simple points" to constrain the evolving front, this
* filter uses the concept of "well-composedness". Advantages of
* the latter over the former includes being able to use the standard
* marching cubes algorithm to produce a mesh whose genus is identical
* to that of the evolved front(s).
*
* \sa FastMarchingStoppingCriterionBase
*
* \ingroup ITKFastMarching
*/
template <typename TInput, typename TOutput>
class ITK_TEMPLATE_EXPORT FastMarchingBase : public FastMarchingTraits<TInput, TOutput>::SuperclassType
{
public:
ITK_DISALLOW_COPY_AND_MOVE(FastMarchingBase);
using Traits = FastMarchingTraits<TInput, TOutput>;
using SuperclassType = typename Traits::SuperclassType;
using Self = FastMarchingBase;
using Superclass = typename FastMarchingTraits<TInput, TOutput>::SuperclassType;
using Pointer = SmartPointer<Self>;
using ConstPointer = SmartPointer<const Self>;
/** \see LightObject::GetNameOfClass() */
itkOverrideGetNameOfClassMacro(FastMarchingBase);
/** Input Domain related definitions */
using InputDomainType = typename Traits::InputDomainType;
using InputDomainPointer = typename Traits::InputDomainPointer;
using InputPixelType = typename Traits::InputPixelType;
/** Output Domain related definitions */
using OutputDomainType = typename Traits::OutputDomainType;
using OutputDomainPointer = typename Traits::OutputDomainPointer;
using OutputPixelType = typename Traits::OutputPixelType;
/** NodeType type of node */
using NodeType = typename Traits::NodeType;
/** NodePairType pair of node and corresponding value */
using NodePairType = typename Traits::NodePairType;
using NodePairContainerType = typename Traits::NodePairContainerType;
using NodePairContainerPointer = typename Traits::NodePairContainerPointer;
using NodePairContainerConstIterator = typename Traits::NodePairContainerConstIterator;
using LabelType = typename Traits::LabelType;
/** StoppingCriterionType stopping criterion */
using StoppingCriterionType = FastMarchingStoppingCriterionBase<TInput, TOutput>;
using StoppingCriterionPointer = typename StoppingCriterionType::Pointer;
/*
using ElementIdentifier = long;
using PriorityQueueElementType = MinPriorityQueueElementWrapper< NodeType,
OutputPixelType,
ElementIdentifier >;
using PriorityQueueType = PriorityQueueContainer< PriorityQueueElementType,
PriorityQueueElementType, OutputPixelType, ElementIdentifier >;
using PriorityQueuePointer = typename PriorityQueueType::Pointer;
*/
using TopologyCheckEnum = FastMarchingTraitsEnums::TopologyCheck;
#if !defined(ITK_LEGACY_REMOVE)
using TopologyCheckType = FastMarchingTraitsEnums::TopologyCheck;
/**Exposes enums values for backwards compatibility*/
static constexpr TopologyCheckEnum Nothing = TopologyCheckEnum::Nothing;
static constexpr TopologyCheckEnum NoHandles = TopologyCheckEnum::NoHandles;
static constexpr TopologyCheckEnum Strict = TopologyCheckEnum::Strict;
#endif
/** Set/Get the TopologyCheckType macro indicating whether the user
wants to check topology (and which one). */
itkSetEnumMacro(TopologyCheck, TopologyCheckEnum);
itkGetConstReferenceMacro(TopologyCheck, TopologyCheckEnum);
/** Set/Get TrialPoints */
itkSetObjectMacro(TrialPoints, NodePairContainerType);
itkGetModifiableObjectMacro(TrialPoints, NodePairContainerType);
/** Set/Get AlivePoints */
itkSetObjectMacro(AlivePoints, NodePairContainerType);
itkGetModifiableObjectMacro(AlivePoints, NodePairContainerType);
/** Set/Get ProcessedPoints */
itkSetObjectMacro(ProcessedPoints, NodePairContainerType);
itkGetModifiableObjectMacro(ProcessedPoints, NodePairContainerType);
/** Set/Get ForbiddenPoints */
itkSetObjectMacro(ForbiddenPoints, NodePairContainerType);
itkGetModifiableObjectMacro(ForbiddenPoints, NodePairContainerType);
/** \brief Set/Get the Stopping Criterion */
itkSetObjectMacro(StoppingCriterion, StoppingCriterionType);
itkGetModifiableObjectMacro(StoppingCriterion, StoppingCriterionType);
/** \brief Set/Get SpeedConstant */
itkGetMacro(SpeedConstant, double);
itkSetMacro(SpeedConstant, double);
/** \brief Set/Get NormalizationFactor */
itkGetMacro(NormalizationFactor, double);
itkSetMacro(NormalizationFactor, double);
/** \brief Get the value reached by the front when it stops propagating */
itkGetMacro(TargetReachedValue, OutputPixelType);
/** Set the Collect Points flag. Instrument the algorithm to collect
* a container of all nodes which it has visited. Useful for
* creating Narrowbands for level set algorithms that supports
* narrow banding. */
itkSetMacro(CollectPoints, bool);
/** Get the Collect Points flag. */
itkGetConstReferenceMacro(CollectPoints, bool);
itkBooleanMacro(CollectPoints);
protected:
/** \brief Constructor */
FastMarchingBase();
/** \brief Destructor */
~FastMarchingBase() override = default;
StoppingCriterionPointer m_StoppingCriterion{};
double m_SpeedConstant{};
double m_InverseSpeed{};
double m_NormalizationFactor{};
OutputPixelType m_TargetReachedValue{};
OutputPixelType m_LargeValue{};
OutputPixelType m_TopologyValue{};
NodePairContainerPointer m_TrialPoints{};
NodePairContainerPointer m_AlivePoints{};
NodePairContainerPointer m_ProcessedPoints{};
NodePairContainerPointer m_ForbiddenPoints{};
bool m_CollectPoints{};
// PriorityQueuePointer m_Heap;
using HeapContainerType = std::vector<NodePairType>;
using NodeComparerType = std::greater<NodePairType>;
using PriorityQueueType = std::priority_queue<NodePairType, HeapContainerType, NodeComparerType>;
PriorityQueueType m_Heap{};
TopologyCheckEnum m_TopologyCheck{};
/** \brief Get the total number of nodes in the domain */
virtual IdentifierType
GetTotalNumberOfNodes() const = 0;
/** \brief Get the output value (front value) for a given node */
virtual const OutputPixelType
GetOutputValue(OutputDomainType * oDomain, const NodeType & iNode) const = 0;
/** \brief Set the output value (front value) for a given node */
virtual void
SetOutputValue(OutputDomainType * oDomain, const NodeType & iNode, const OutputPixelType & iValue) = 0;
/** \brief Get the LabelEnum Value for a given node
\param[in] iNode
\return its label value */
virtual unsigned char
GetLabelValueForGivenNode(const NodeType & iNode) const = 0;
/** \brief Set the Label Value for a given node
\param[in] iNode
\param[in] iLabel */
virtual void
SetLabelValueForGivenNode(const NodeType & iNode, const LabelType & iLabel) = 0;
/** \brief Update neighbors to a given node
\param[in] oDomain
\param[in] iNode
*/
virtual void
UpdateNeighbors(OutputDomainType * oDomain, const NodeType & iNode) = 0;
/** \brief Update value for a given node
\param[in] oDomain
\param[in] iNode
*/
virtual void
UpdateValue(OutputDomainType * oDomain, const NodeType & iNode) = 0;
/** \brief Check if the current node violate topological criterion.
\param[in] oDomain
\param[in] iNode
*/
virtual bool
CheckTopology(OutputDomainType * oDomain, const NodeType & iNode) = 0;
/** \brief */
void
Initialize(OutputDomainType * oDomain);
/** */
virtual void
InitializeOutput(OutputDomainType * oDomain) = 0;
/** */
void
GenerateData() override;
/** \brief PrintSelf method */
void
PrintSelf(std::ostream & os, Indent indent) const override;
};
} // namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
# include "itkFastMarchingBase.hxx"
#endif
#endif
|