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 itkMINCTransformAdapter_h 19 #define itkMINCTransformAdapter_h 20 21 #include "itkObject.h" 22 #include "itkPoint.h" 23 #include "itkVector.h" 24 #include "itkCovariantVector.h" 25 #include "vnl/vnl_matrix_fixed.h" 26 #include "vnl/vnl_vector_fixed.h" 27 #include "vnl/vnl_det.h" 28 #include "vnl/vnl_vector_fixed_ref.h" 29 #include "vnl/vnl_vector.h" 30 #include "itkTransform.h" 31 #include "itkObjectFactory.h" 32 33 //minc header 34 #include "itk_minc2.h" 35 36 namespace itk 37 { 38 39 /** \class MINCTransformAdapter 40 * \ingroup ITKIOTransformMINC 41 * \brief ITK wrapper around MINC general transform functions, supports all the transformations that MINC XFM supports 42 * 43 * \author Vladimir S. FONOV 44 * Brain Imaging Center, Montreal Neurological Institute, McGill University, Montreal Canada 2012 45 * \ingroup ITKIOTransformMINC 46 */ 47 template<typename TParametersValueType=double, unsigned int NInputDimensions=3,unsigned int NOutputDimensions=3> 48 class MINCTransformAdapter : public Transform<TParametersValueType, NInputDimensions, NOutputDimensions> 49 { 50 public: 51 ITK_DISALLOW_COPY_AND_ASSIGN(MINCTransformAdapter); 52 53 /** Standard class type aliases. */ 54 using Self = MINCTransformAdapter; 55 56 using Superclass = Transform<TParametersValueType, NInputDimensions, NOutputDimensions>; 57 58 using Pointer = SmartPointer<Self>; 59 using ConstPointer = SmartPointer<const Self>; 60 61 using NumberOfParametersType = typename Superclass::NumberOfParametersType; 62 63 /** New method for creating an object using a factory. */ 64 itkNewMacro(Self); 65 66 /** Run-time type information (and related methods). */ 67 itkTypeMacro( MINCTransformAdapter, Transform ); 68 69 /** Dimension of the domain space. */ 70 static constexpr unsigned int InputSpaceDimension = NInputDimensions; 71 static constexpr unsigned int OutputSpaceDimension = NOutputDimensions; 72 73 /** Type of the input parameters. */ 74 using ScalarType = double; 75 76 /** Type of the input parameters. */ 77 using ParametersType = typename Superclass::ParametersType; 78 using FixedParametersType = typename Superclass::FixedParametersType; 79 80 /** Type of the Jacobian matrix. */ 81 using JacobianType = typename Superclass::JacobianType; 82 83 /** Standard vector type for this class. */ 84 using InputVectorType = Vector<TParametersValueType, Self::InputSpaceDimension>; 85 using OutputVectorType = Vector<TParametersValueType, Self::OutputSpaceDimension>; 86 87 /** Standard variable length vector type for this class 88 * this provides an interface for the VectorImage class */ 89 using InputVectorPixelType = VariableLengthVector<TParametersValueType>; 90 using OutputVectorPixelType = VariableLengthVector<TParametersValueType>; 91 92 /** Standard covariant vector type for this class */ 93 using InputCovariantVectorType = CovariantVector<TParametersValueType, Self::InputSpaceDimension>; 94 95 using OutputCovariantVectorType = CovariantVector<TParametersValueType, Self::OutputSpaceDimension>; 96 97 /** Standard coordinate point type for this class */ 98 using InputPointType = Point<TParametersValueType,NInputDimensions >; 99 using OutputPointType = Point<TParametersValueType,NInputDimensions >; 100 101 /** Standard vnl_vector type for this class. */ 102 using InputVnlVectorType = vnl_vector_fixed<TParametersValueType, NInputDimensions>; 103 using OutputVnlVectorType = vnl_vector_fixed<TParametersValueType, NOutputDimensions>; 104 105 /** Method to transform a point. */ TransformPoint(const InputPointType & point)106 OutputPointType TransformPoint(const InputPointType &point ) const override 107 { 108 if(!m_Initialized) 109 { 110 return point; 111 } 112 113 if(m_Invert && !m_Initialized_invert) 114 { 115 return point; 116 } 117 118 OutputPointType pnt; 119 //works only for 3D->3D transforms 120 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm), point[0], point[1], point[2], &pnt[0], &pnt[1], &pnt[2]); 121 122 return pnt; 123 } 124 125 //! use finate element difference to estimate local jacobian estimate_local_jacobian(const InputPointType & orig,vnl_matrix_fixed<double,3,3> & m)126 void estimate_local_jacobian(const InputPointType &orig, vnl_matrix_fixed< double, 3, 3 > &m) 127 { 128 double u1,v1,w1; 129 double u2,v2,w2; 130 const double delta=1e-4; 131 132 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm) , orig[0]-delta, orig[1], orig[2],&u1, &v1, &w1); 133 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm) , orig[0]+delta, orig[1], orig[2],&u2, &v2, &w2); 134 m(0,0)=(u2-u1)/(2*delta); 135 m(0,1)=(v2-v1)/(2*delta); 136 m(0,2)=(w2-w1)/(2*delta); 137 138 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm) , orig[0], orig[1]-delta, orig[2],&u1, &v1, &w1); 139 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm) , orig[0], orig[1]+delta, orig[2],&u2, &v2, &w2); 140 m(1,0)=(u2-u1)/(2*delta); 141 m(1,1)=(v2-v1)/(2*delta); 142 m(1,2)=(w2-w1)/(2*delta); 143 144 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm), orig[0], orig[1], orig[2]-delta,&u1, &v1, &w1); 145 general_transform_point((m_Invert ? &m_Xfm_inv : &m_Xfm), orig[0], orig[1], orig[2]+delta,&u2, &v2, &w2); 146 m(2,0)=(u2-u1)/(2*delta); 147 m(2,1)=(v2-v1)/(2*delta); 148 m(2,2)=(w2-w1)/(2*delta); 149 } 150 151 /** Method to transform a vector. */ TransformVector(const InputVectorType & vector,const InputPointType &)152 OutputVectorType TransformVector( const InputVectorType& vector, const InputPointType & ) const override 153 { 154 itkExceptionMacro( << "Not Implemented" ); 155 return vector; 156 } 157 158 /** Method to transform a vector. */ TransformVector(const InputVnlVectorType & vector,const InputPointType &)159 OutputVnlVectorType TransformVector( const InputVnlVectorType& vector, const InputPointType & ) const override 160 { 161 itkExceptionMacro( << "Not Implemented" ); 162 return vector; 163 } 164 165 /** Method to transform a vector. */ TransformVector(const InputVectorType & vector)166 OutputVectorType TransformVector( const InputVectorType& vector) const override 167 { 168 return Superclass::TransformVector(vector); 169 } 170 171 /** Method to transform a vector. */ TransformVector(const InputVnlVectorType & vector)172 OutputVnlVectorType TransformVector( const InputVnlVectorType& vector) const override 173 { 174 return Superclass::TransformVector(vector); 175 } 176 177 /** Method to transform a vector. */ TransformVector(const InputVectorPixelType & vector)178 OutputVectorPixelType TransformVector( const InputVectorPixelType& vector) const override 179 { 180 return Superclass::TransformVector(vector); 181 } 182 183 /** Method to transform a vector. */ TransformVector(const InputVectorPixelType & vector,const InputPointType &)184 OutputVectorPixelType TransformVector( 185 const InputVectorPixelType& vector, 186 const InputPointType & ) const override 187 { 188 itkExceptionMacro( << "Not Implemented" ); 189 return vector; 190 } 191 192 /** Method to transform a CovariantVector. */ TransformCovariantVector(const InputCovariantVectorType & vector,const InputPointType &)193 OutputCovariantVectorType TransformCovariantVector( 194 const InputCovariantVectorType &vector 195 , const InputPointType & ) const override 196 { 197 itkExceptionMacro( << "Not Implemented" ); 198 return vector; 199 } 200 201 /** Method to transform a CovariantVector. */ TransformCovariantVector(const InputCovariantVectorType & vector)202 OutputCovariantVectorType TransformCovariantVector( 203 const InputCovariantVectorType &vector) const override 204 { 205 return Superclass::TransformCovariantVector(vector); 206 } 207 208 /** Method to transform a CovariantVector. */ TransformCovariantVector(const InputVectorPixelType & vector)209 OutputVectorPixelType TransformCovariantVector( 210 const InputVectorPixelType &vector) const override 211 { 212 return Superclass::TransformCovariantVector(vector); 213 } 214 215 /** Method to transform a CovariantVector. */ TransformCovariantVector(const InputVectorPixelType & vector,const InputPointType &)216 OutputVectorPixelType TransformCovariantVector( 217 const InputVectorPixelType &vector, const InputPointType & ) const override 218 { 219 itkExceptionMacro( << "Not Implemented" ); 220 return vector; 221 } 222 223 /** Set the transformation to an Identity 224 */ SetIdentity()225 virtual void SetIdentity() 226 { 227 cleanup(); 228 } 229 SetFixedParameters(const FixedParametersType &)230 void SetFixedParameters(const FixedParametersType &) override 231 { 232 itkExceptionMacro( << "Not Implemented" ); 233 } 234 ComputeJacobianWithRespectToParameters(const InputPointType &,JacobianType &)235 void ComputeJacobianWithRespectToParameters( 236 const InputPointType &, 237 JacobianType &) const override 238 { 239 itkExceptionMacro( << "Not Implemented" ); 240 } 241 GetNumberOfParameters()242 NumberOfParametersType GetNumberOfParameters() const override 243 { 244 //this transform is defined by XFM file 245 itkExceptionMacro( << "Not Defined" ); 246 return 0; 247 } 248 249 /** Set the Transformation Parameters 250 * and update the internal transformation. */ SetParameters(const ParametersType &)251 void SetParameters(const ParametersType &) override 252 { 253 itkExceptionMacro( << "Not Implemented" ); 254 } 255 GetParameters()256 const ParametersType & GetParameters() const override 257 { 258 itkExceptionMacro( << "Not Implemented" ); 259 return m_Parameters; 260 } 261 OpenXfm(const char * xfm)262 void OpenXfm(const char *xfm) 263 { 264 cleanup(); 265 if(input_transform_file(xfm, &m_Xfm) != VIO_OK) 266 itkExceptionMacro( << "Error reading XFM:" << xfm ); 267 m_Initialized=true; 268 } 269 Invert()270 void Invert() 271 { 272 if(!m_Initialized) 273 itkExceptionMacro( << "XFM not initialized" ); 274 if(!m_Initialized_invert) 275 { 276 create_inverse_general_transform(&m_Xfm,&m_Xfm_inv); 277 m_Initialized_invert=true; 278 } 279 m_Invert= !m_Invert; 280 } 281 282 protected: MINCTransformAdapter()283 MINCTransformAdapter(): 284 Transform<TParametersValueType, NInputDimensions, NOutputDimensions>(0), 285 m_Invert(false), 286 m_Initialized(false), 287 m_Initialized_invert(false) 288 { 289 if(NInputDimensions!=3 || NOutputDimensions!=3) 290 itkExceptionMacro(<< "Sorry, only 3D to 3d minc xfm transform is currently implemented"); 291 } 292 ~MINCTransformAdapter()293 ~MINCTransformAdapter() override 294 { 295 cleanup(); 296 } 297 cleanup()298 void cleanup() 299 { 300 if(m_Initialized) 301 { 302 delete_general_transform(&m_Xfm); 303 } 304 if(m_Initialized_invert) 305 { 306 delete_general_transform(&m_Xfm_inv); 307 } 308 m_Initialized=false; 309 m_Initialized_invert=false; 310 } 311 312 ParametersType m_Parameters; 313 314 mutable VIO_General_transform m_Xfm; 315 mutable VIO_General_transform m_Xfm_inv; 316 317 bool m_Invert; 318 bool m_Initialized; 319 bool m_Initialized_invert; 320 }; 321 322 } 323 #endif //itkMINCTransformAdapter_h 324