1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 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 * http://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 itkBSplineDeformableTransform_h 19 #define itkBSplineDeformableTransform_h 20 21 #include "itkBSplineBaseTransform.h" 22 23 namespace itk 24 { 25 /** \class BSplineDeformableTransform 26 * 27 * \brief Deformable transform using a BSpline representation 28 * 29 * \note BSplineTransform is a newer version of this class, and it is 30 * preferred. 31 * 32 * This class encapsulates a deformable transform of points from one 33 * N-dimensional space to another N-dimensional space. 34 * The deformation field is modelled using B-splines. 35 * A deformation is defined on a sparse regular grid of control points 36 * \f$ \vec{\lambda}_j \f$ and is varied by defining a deformation 37 * \f$ \vec{g}(\vec{\lambda}_j) \f$ of each control point. 38 * The deformation \f$ D(\vec{x}) \f$ at any point \f$ \vec{x} \f$ 39 * is obtained by using a B-spline interpolation kernel. 40 * 41 * The deformation field grid is defined by a user specified GridRegion, 42 * GridSpacing and GridOrigin. Each grid/control point has associated with it 43 * N deformation coefficients \f$ \vec{\delta}_j \f$, representing the N 44 * directional components of the deformation. Deformation outside the grid 45 * plus support region for the BSpline interpolation is assumed to be zero. 46 * 47 * Additionally, the user can specified an addition bulk transform \f$ B \f$ 48 * such that the transformed point is given by: 49 * \f[ \vec{y} = B(\vec{x}) + D(\vec{x}) \f] 50 * 51 * The parameters for this transform is an N x N-D grid of spline coefficients. 52 * The user specifies the parameters as one flat array: each N-D grid 53 * is represented by an array in the same way an N-D image is represented 54 * in the buffer; the N arrays are then concatentated together on form 55 * a single array. 56 * 57 * For efficiency, this transform does not make a copy of the parameters. 58 * It only keeps a pointer to the input parameters and assumes that the memory 59 * is managed by the caller. 60 * 61 * The following illustrates the typical usage of this class: 62 * \verbatim 63 * using TransformType = BSplineDeformableTransform<double,2,3>; 64 * TransformType::Pointer transform = TransformType::New(); 65 * 66 * transform->SetGridRegion( region ); 67 * transform->SetGridSpacing( spacing ); 68 * transform->SetGridOrigin( origin ); 69 * 70 * // NB: the region must be set first before setting the parameters 71 * 72 * TransformType::ParametersType parameters( 73 * transform->GetNumberOfParameters() ); 74 * 75 * // Fill the parameters with values 76 * 77 * transform->SetParameters( parameters ) 78 * 79 * outputPoint = transform->TransformPoint( inputPoint ); 80 * 81 * \endverbatim 82 * 83 * An alternative way to set the B-spline coefficients is via array of 84 * images. The grid region, spacing and origin information is taken 85 * directly from the first image. It is assumed that the subsequent images 86 * are the same buffered region. The following illustrates the API: 87 * \verbatim 88 * 89 * TransformType::ImageConstPointer images[2]; 90 * 91 * // Fill the images up with values 92 * 93 * transform->SetCoefficientImages( images ); 94 * outputPoint = transform->TransformPoint( inputPoint ); 95 * 96 * \endverbatim 97 * 98 * Warning: use either the SetParameters() or SetCoefficientImages() 99 * API. Mixing the two modes may results in unexpected results. 100 * 101 * The class is templated coordinate representation type (float or double), 102 * the space dimension and the spline order. 103 * 104 * \ingroup ITKTransform 105 * 106 * \sa BSplineTransform 107 * 108 * \wiki 109 * \wikiexample{Registration/ImageRegistrationMethodBSpline,A global registration of two images} 110 * \endwiki 111 */ 112 template<typename TParametersValueType=double, 113 unsigned int NDimensions = 3, 114 unsigned int VSplineOrder = 3> 115 class ITK_TEMPLATE_EXPORT BSplineDeformableTransform : 116 public BSplineBaseTransform<TParametersValueType,NDimensions,VSplineOrder> 117 { 118 public: 119 ITK_DISALLOW_COPY_AND_ASSIGN(BSplineDeformableTransform); 120 121 /** Standard class type aliases. */ 122 using Self = BSplineDeformableTransform; 123 using Superclass = BSplineBaseTransform<TParametersValueType,NDimensions,VSplineOrder>; 124 using Pointer = SmartPointer<Self>; 125 using ConstPointer = SmartPointer<const Self>; 126 127 /** New macro for creation of through the object factory. */ 128 // Explicit New() method, used here because we need to split the itkNewMacro() 129 // in order to overload the CreateAnother() method so that we can copy the m_BulkTransform 130 // explicitly. 131 // TODO: shouldn't it be done with the Clone() method? 132 itkSimpleNewMacro(Self); CreateAnother()133 ::itk::LightObject::Pointer CreateAnother() const override 134 { 135 ::itk::LightObject::Pointer smartPtr; 136 Pointer copyPtr = Self::New().GetPointer(); 137 //THE FOLLOWING LINE IS DIFFERENT FROM THE DEFAULT MACRO! 138 copyPtr->m_BulkTransform = this->GetBulkTransform(); 139 smartPtr = static_cast<Pointer>( copyPtr ); 140 return smartPtr; 141 } 142 143 /** implement type-specific clone method*/ 144 itkCloneMacro(Self); 145 146 /** Run-time type information (and related methods). */ 147 itkTypeMacro( BSplineDeformableTransform, BSplineBaseTransform ); 148 149 /** Dimension of the domain space. */ 150 static constexpr unsigned int SpaceDimension = NDimensions; 151 152 /** The BSpline order. */ 153 static constexpr unsigned int SplineOrder = VSplineOrder; 154 155 /** Standard scalar type for this class. */ 156 using ScalarType = TParametersValueType; 157 158 /** Standard parameters container. */ 159 using ParametersType = typename Superclass::ParametersType; 160 using ParametersValueType = typename Superclass::ParametersValueType; 161 using FixedParametersType = typename Superclass::FixedParametersType; 162 using FixedParametersValueType = typename Superclass::FixedParametersValueType; 163 164 /** Standard Jacobian container. */ 165 using JacobianType = typename Superclass::JacobianType; 166 using JacobianPositionType = typename Superclass::JacobianPositionType; 167 using InverseJacobianPositionType = typename Superclass::InverseJacobianPositionType; 168 169 /** The number of parameters defininig this transform. */ 170 using NumberOfParametersType = typename Superclass::NumberOfParametersType; 171 172 /** Standard vector type for this class. */ 173 using InputVectorType = typename Superclass::InputVectorType; 174 using OutputVectorType = typename Superclass::OutputVectorType; 175 176 /** Standard covariant vector type for this class. */ 177 using InputCovariantVectorType = typename Superclass::InputCovariantVectorType; 178 using OutputCovariantVectorType = typename Superclass::OutputCovariantVectorType; 179 180 /** Standard vnl_vector type for this class. */ 181 using InputVnlVectorType = typename Superclass::InputVnlVectorType; 182 using OutputVnlVectorType = typename Superclass::OutputVnlVectorType; 183 184 /** Standard coordinate point type for this class. */ 185 using InputPointType = Point <TParametersValueType, Self::SpaceDimension >; 186 using OutputPointType = Point <TParametersValueType, Self::SpaceDimension >; 187 188 189 /** This method sets the fixed parameters of the transform. 190 * For a BSpline deformation transform, the parameters are the following: 191 * Grid Size, Grid Origin, and Grid Spacing 192 * 193 * The fixed parameters are the three times the size of the templated 194 * dimensions. 195 * This function has the effect of make the following calls: 196 * transform->SetGridSpacing( spacing ); 197 * transform->SetGridOrigin( origin ); 198 * transform->SetGridDirection( direction ); 199 * transform->SetGridRegion( bsplineRegion ); 200 * 201 * This function was added to allow the transform to work with the 202 * itkTransformReader/Writer I/O filters. 203 * 204 */ 205 void SetFixedParameters( const FixedParametersType & parameters ) override; 206 207 /** Parameters as SpaceDimension number of images. */ 208 using ImageType = typename Superclass::ImageType; 209 using ImagePointer = typename Superclass::ImagePointer; 210 using CoefficientImageArray = typename Superclass::CoefficientImageArray; 211 212 /** Set the array of coefficient images. 213 * 214 * This is an alternative API for setting the BSpline coefficients 215 * as an array of SpaceDimension images. The fixed parameters are 216 * taken from the first image. It is assumed that 217 * the buffered region of all the subsequent images are the same 218 * as the first image. Note that no error checking is done. 219 * 220 * Warning: use either the SetParameters() or SetCoefficientImages() 221 * API. Mixing the two modes may results in unexpected results. 222 */ 223 void SetCoefficientImages( const CoefficientImageArray & images ) override; 224 225 /** Typedefs for specifying the extent of the grid. */ 226 using RegionType = typename Superclass::RegionType; 227 228 using IndexType = typename Superclass::IndexType; 229 using SizeType = typename Superclass::SizeType; 230 using SpacingType = typename Superclass::SpacingType; 231 using DirectionType = typename Superclass::DirectionType; 232 using OriginType = typename Superclass::OriginType; 233 234 /** Interpolation weights function type. */ 235 using WeightsFunctionType = typename Superclass::WeightsFunctionType; 236 237 using WeightsType = typename Superclass::WeightsType; 238 using ContinuousIndexType = typename Superclass::ContinuousIndexType; 239 240 /** Parameter index array type. */ 241 using ParameterIndexArrayType = typename Superclass::ParameterIndexArrayType; 242 243 /** 244 * Transform points by a BSpline deformable transformation. 245 * On return, weights contains the interpolation weights used to compute the 246 * deformation and indices of the x (zeroth) dimension coefficient parameters 247 * in the support region used to compute the deformation. 248 * Parameter indices for the i-th dimension can be obtained by adding 249 * ( i * this->GetNumberOfParametersPerDimension() ) to the indices array. 250 */ 251 using Superclass::TransformPoint; 252 void TransformPoint( const InputPointType & inputPoint, OutputPointType & outputPoint, 253 WeightsType & weights, ParameterIndexArrayType & indices, bool & inside ) const override; 254 255 void ComputeJacobianWithRespectToParameters( const InputPointType &, JacobianType & ) const override; 256 257 /** Return the number of parameters that completely define the Transfom */ 258 NumberOfParametersType GetNumberOfParameters() const override; 259 260 /** Return the number of parameters per dimension */ 261 NumberOfParametersType GetNumberOfParametersPerDimension() const override; 262 263 using PhysicalDimensionsType = typename Superclass::SpacingType; 264 using PixelType = typename Superclass::PixelType; 265 266 using MeshSizeType = typename Superclass::MeshSizeType; 267 268 /** Function to specify the transform domain origin. */ 269 virtual void SetGridOrigin( const OriginType & ); 270 271 /** Function to retrieve the transform domain origin. */ 272 itkGetConstMacro( GridOrigin, OriginType ); 273 274 /** This method specifies the grid spacing or resolution. */ 275 virtual void SetGridSpacing( const SpacingType & ); 276 277 /** This method retrieve the grid spacing or resolution. */ 278 itkGetConstMacro( GridSpacing, SpacingType ); 279 280 /** Function to specify the transform domain direction. */ 281 virtual void SetGridDirection( const DirectionType & ); 282 283 /** Function to retrieve the transform domain direction. */ 284 itkGetConstMacro( GridDirection, DirectionType ); 285 286 /** Function to specify the transform domain mesh size. */ 287 virtual void SetGridRegion( const RegionType & ); 288 289 /** Function to retrieve the transform domain mesh size. */ 290 itkGetConstMacro( GridRegion, RegionType ); 291 292 using BulkTransformType = Transform<TParametersValueType, 293 Self::SpaceDimension, 294 Self::SpaceDimension>; 295 using BulkTransformPointer = typename BulkTransformType::ConstPointer; 296 /** This method specifies the bulk transform to be applied. 297 * The default is the identity transform. 298 */ 299 itkSetConstObjectMacro(BulkTransform, BulkTransformType); 300 itkGetConstObjectMacro(BulkTransform, BulkTransformType); 301 302 /** Return the region of the grid wholly within the support region */ 303 itkGetConstReferenceMacro(ValidRegion, RegionType); 304 305 protected: 306 /** Print contents of an BSplineDeformableTransform. */ 307 void PrintSelf( std::ostream & os, Indent indent ) const override; 308 309 BSplineDeformableTransform(); 310 ~BSplineDeformableTransform() override = default; 311 312 private: 313 314 /** Construct control point grid size from transform domain information */ 315 void SetFixedParametersGridSizeFromTransformDomainInformation() const override; 316 317 /** Construct control point grid origin from transform domain information */ 318 void SetFixedParametersGridOriginFromTransformDomainInformation() const override; 319 320 /** Construct control point grid spacing from transform domain information */ 321 void SetFixedParametersGridSpacingFromTransformDomainInformation() const override; 322 323 /** Construct control point grid direction from transform domain information */ 324 void SetFixedParametersGridDirectionFromTransformDomainInformation() const override; 325 326 /** Construct control point grid size from transform domain information */ 327 void SetCoefficientImageInformationFromFixedParameters() override; 328 329 /** Check if a continuous index is inside the valid region. */ 330 bool InsideValidRegion( ContinuousIndexType & ) const override; 331 332 /** The variables defining the coefficient grid domain for the 333 * InternalParametersBuffer are taken from the m_CoefficientImages[0] 334 * image, and must be kept in sync with them. by using 335 * references to that instance, this is more naturally enforced 336 * and does not introduce a speed penalty of dereferencing 337 * through the pointers (although it does enforce some 338 * internal class synchronization). 339 */ 340 const RegionType & m_GridRegion; 341 const OriginType & m_GridOrigin; 342 const SpacingType & m_GridSpacing; 343 const DirectionType & m_GridDirection; 344 345 /** The bulk transform. */ 346 BulkTransformPointer m_BulkTransform; 347 348 RegionType m_ValidRegion; 349 350 /** Variables defining the interpolation support region. */ 351 unsigned long m_Offset; 352 bool m_SplineOrderOdd; 353 IndexType m_ValidRegionLast; 354 IndexType m_ValidRegionFirst; 355 356 void UpdateValidGridRegion(); 357 358 }; // class BSplineDeformableTransform 359 } // namespace itk 360 361 #ifndef ITK_MANUAL_INSTANTIATION 362 #include "itkBSplineDeformableTransform.hxx" 363 #endif 364 365 #endif /* itkBSplineDeformableTransform_h */ 366