MeVisLabToolboxReference
|
00001 // **InsertLicense** code 00002 //---------------------------------------------------------------------------------- 00005 00010 //---------------------------------------------------------------------------------- 00011 #ifndef __mlITKSupportToolFunctions_H 00012 #define __mlITKSupportToolFunctions_H 00013 00015 // Include dll-specific settings. 00016 #include "mlInitSystemITKSupport.h" 00017 00019 #ifndef __mlModuleIncludes_H 00020 #include "mlModuleIncludes.h" 00021 #endif 00022 00024 #ifndef __mlPointList_H 00025 #include "mlPointList.h" 00026 #endif 00027 #ifndef __mlVectorList_H 00028 #include "mlVectorList.h" 00029 #endif 00030 #ifndef __mlXMarkerList_H 00031 #include "mlXMarkerList.h" 00032 #endif 00033 00034 00036 #include <itkImage.h> 00037 #include <itkImportImageFilter.h> 00038 #include <itkMatrix.h> 00039 #include <itkPointSet.h> 00040 00041 ML_START_NAMESPACE 00042 00043 //--------------------------------------------------------------------------- 00053 //--------------------------------------------------------------------------- 00054 extern MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e, 00055 const Module *module, 00056 MLMessageType messageType, 00057 const std::string &handling=""); 00058 00059 00060 00061 //--------------------------------------------------------------------------- 00067 //------------------------------------------------------------------------------------ 00068 extern MLITK_SUPPORT_EXPORT void copyITKDataBufferToMLSubImg(void *itkData, 00069 size_t itkDataTypeSize, 00070 const SubImageBox &itkBox, 00071 SubImage &outSubImg); 00072 00073 00074 //--------------------------------------------------------------------------- 00084 //--------------------------------------------------------------------------- 00085 template<typename SIZE_TYPE> 00086 SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec) 00087 { 00088 ML_TRACE_IN("template ITKSizeFromMLVector()"); 00089 00090 SIZE_TYPE sizeObj; 00091 if (sizeObj.GetSizeDimension() > static_cast<unsigned int>(vec.dim())){ 00092 ML_PRINT_FATAL_ERROR("ITKSizeFromMLVector", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions."); 00093 } 00094 else{ 00095 for (unsigned int i=0; i<sizeObj.GetSizeDimension(); i++){ sizeObj[i] = vec[i]; } 00096 } 00097 return sizeObj; 00098 } 00099 00100 //--------------------------------------------------------------------------- 00110 //--------------------------------------------------------------------------- 00111 template<typename INDEX_TYPE> 00112 INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec) 00113 { 00114 ML_TRACE_IN("template ITKIndexFromMLVector()"); 00115 00116 INDEX_TYPE sizeObj; 00117 if (sizeObj.GetIndexDimension() > static_cast<unsigned int>(vec.dim())){ 00118 ML_PRINT_FATAL_ERROR("ITKIndexFromMLVector", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions."); 00119 } 00120 else{ 00121 for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; } 00122 } 00123 return sizeObj; 00124 } 00125 00126 //--------------------------------------------------------------------------- 00135 //--------------------------------------------------------------------------- 00136 template<typename INDEX_TYPE> 00137 ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal) 00138 { 00139 ML_TRACE_IN("template MLVectorFromITKSize()"); 00140 00141 ImageVector vec(0); 00142 unsigned int sizeDim = sizeObj.GetSizeDimension(); 00143 unsigned int vecDim = static_cast<unsigned int>(vec.dim()); 00144 if (sizeDim > vecDim){ 00145 sizeDim = vecDim; 00146 ML_PRINT_WARNING("MLVectorFromITKSize", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored."); 00147 } 00148 00149 for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < sizeDim) ? sizeObj[i] : defaultVal; } 00150 return vec; 00151 } 00152 00153 //--------------------------------------------------------------------------- 00164 //--------------------------------------------------------------------------- 00165 template<typename INDEX_TYPE> 00166 ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal) 00167 { 00168 ML_TRACE_IN("template MLVectorFromITKIndex()"); 00169 00170 ImageVector vec(0); 00171 unsigned int idxDim = indexObj.GetIndexDimension(); 00172 unsigned int vecDim = static_cast<unsigned int>(vec.dim()); 00173 if (idxDim > vecDim){ 00174 idxDim = vecDim; 00175 ML_PRINT_WARNING("MLVectorFromITKIndex", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored."); 00176 } 00177 00178 for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < idxDim) ? indexObj[i] : defaultVal; } 00179 return vec; 00180 } 00181 00182 //--------------------------------------------------------------------------- 00194 //--------------------------------------------------------------------------- 00195 template<typename VECTOR_TYPE> 00196 VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp) 00197 { 00198 ML_TRACE_IN("template ITKVectorFromMLVec3()"); 00199 00200 VECTOR_TYPE sizeObj; 00201 for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){ 00202 sizeObj[i] = i < 3 ? vec[i] : defaultComp; 00203 } 00204 return sizeObj; 00205 } 00206 00207 //--------------------------------------------------------------------------- 00219 //--------------------------------------------------------------------------- 00220 template<typename VECTOR_TYPE> 00221 VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp) 00222 { 00223 ML_TRACE_IN("template ITKVectorFromMLVec4()"); 00224 00225 VECTOR_TYPE sizeObj; 00226 for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){ 00227 sizeObj[i] = i < 4 ? vec[i] : defaultComp; 00228 } 00229 return sizeObj; 00230 } 00231 00232 //--------------------------------------------------------------------------- 00244 //--------------------------------------------------------------------------- 00245 template<typename POINT_TYPE> 00246 POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp) 00247 { 00248 ML_TRACE_IN("template ITKPointFromMLVec3()"); 00249 00250 POINT_TYPE sizeObj; 00251 for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){ 00252 sizeObj[i] = i < 3 ? vec[i] : defaultComp; 00253 } 00254 return sizeObj; 00255 } 00256 00257 //--------------------------------------------------------------------------- 00269 //--------------------------------------------------------------------------- 00270 template<typename POINT_TYPE> 00271 POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp) 00272 { 00273 ML_TRACE_IN("template ITKPointFromMLVec4()"); 00274 00275 POINT_TYPE sizeObj; 00276 for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){ 00277 sizeObj[i] = i < 4 ? vec[i] : defaultComp; 00278 } 00279 return sizeObj; 00280 } 00281 00282 00283 //--------------------------------------------------------------------------- 00293 //--------------------------------------------------------------------------- 00294 template<typename REGION_PARENT_TYPE> 00295 typename REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox) 00296 { 00297 ML_TRACE_IN("template ITKRegionFromMLSubImgBox()"); 00298 00299 typename REGION_PARENT_TYPE::RegionType region; 00300 00301 // Set ITK region origin to the ML SubImageBox origin. 00302 region.SetIndex(ITKIndexFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::IndexType>(subImgBox.v1)); 00303 00304 // Set ITK region extent to the ML SubImageBox extent. 00305 region.SetSize(ITKSizeFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::SizeType>(subImgBox.getExtent())); 00306 return region; 00307 } 00308 00309 //--------------------------------------------------------------------------- 00317 //--------------------------------------------------------------------------- 00318 template<typename REGION_PARENT_TYPE> 00319 SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType ®ion) 00320 { 00321 ML_TRACE_IN("template MLSubImgBoxFromITKRegion()"); 00322 00323 // Get ITK region origin into the ML SubImageBox origin. 00324 // For dimensions not specified by ITK use coordinate 0. 00325 SubImageBox box; 00326 box.v1 = MLVectorFromITKIndex(region.GetIndex(), 0); 00327 00328 // Get ITK region extent into the ML SubImageBox extent. 00329 // For dimensions not specified by ITK use extent 1. 00330 ImageVector ext = MLVectorFromITKSize(region.GetSize(), 1); 00331 00332 // Return the constructed SubImageBox. 00333 box.v2 = box.v1 + (ext - ImageVector(1)); 00334 return box; 00335 } 00336 00337 //--------------------------------------------------------------------------- 00340 //--------------------------------------------------------------------------- 00341 template<typename ARRAY_TYPE, typename STL_VECTOR> 00342 ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec) 00343 { 00344 ML_TRACE_IN("template ITKArrayFromSTLVector()"); 00345 00346 const size_t mFieldSize = stlVec.size(); 00347 ARRAY_TYPE retArray(mFieldSize); 00348 for (size_t i=0; i<mFieldSize; ++i){ retArray[i] = stlVec[i]; } 00349 return retArray; 00350 } 00351 00352 //--------------------------------------------------------------------------- 00356 //--------------------------------------------------------------------------- 00357 template<typename STL_CONTAINER, typename ITK_ARRAY_TYPE> 00358 const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray) 00359 { 00360 ML_TRACE_IN("template STLVectorFromITKArray()"); 00361 00362 const size_t itkFieldSize = itkArray.size(); 00363 STL_CONTAINER stlVector; 00364 for (size_t i=0; i<itkFieldSize; ++i){ stlVector.push_back(itkArray[i]); } 00365 return stlVector; 00366 } 00367 00368 //--------------------------------------------------------------------------- 00380 //--------------------------------------------------------------------------- 00381 template<typename INDEX_TYPE> 00382 INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec) 00383 { 00384 ML_TRACE_IN("template ITKIndexFromMLVector()"); 00385 00386 INDEX_TYPE sizeObj; 00387 if (sizeObj.GetIndexDimension() > 6){ 00388 ML_PRINT_FATAL_ERROR("ITKIndexFromMLVec6", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions."); 00389 } 00390 else{ 00391 for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; } 00392 } 00393 return sizeObj; 00394 } 00395 00396 00397 //--------------------------------------------------------------------------- 00403 //--------------------------------------------------------------------------- 00404 template<class FilterType> 00405 typename FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal) 00406 { 00407 ML_TRACE_IN("ITKNodeContainerFromBasePointer()"); 00408 00409 XMarkerListContainer *xmlc = NULL; 00410 XMarkerList *xml = NULL; 00411 PointList *pl = NULL; 00412 VectorList *vl = NULL; 00413 00414 // Get base field. 00415 if (baseVal){ 00416 // Check for different base object types. 00417 if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ 00418 xmlc = static_cast<XMarkerListContainer*>(baseVal); 00419 } 00420 else if (ML_BASE_IS_A(baseVal, XMarkerList)){ 00421 xml = static_cast<XMarkerList*>(baseVal); 00422 } 00423 else if (ML_BASE_IS_A(baseVal, PointList)){ 00424 pl = static_cast<PointList*>(baseVal); 00425 } 00426 else if (ML_BASE_IS_A(baseVal, VectorList)){ 00427 vl = static_cast<VectorList*>(baseVal); 00428 } 00429 else{ 00430 // No valid type in base field. That can happen. 00431 } 00432 } 00433 00434 // Get number of points from list. 00435 MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) : 00436 (xml ? static_cast<MLssize_t>(xml->size()) : 00437 (pl ? pl->getNum() : 00438 (vl ? vl->getNum() : 0)))); 00439 00440 00441 if (numVals > 0){ 00442 // Create a NodeContainer and initialize it. 00443 typename FilterType::NodeContainer::Pointer nc = FilterType::NodeContainer::New(); 00444 nc->Initialize(); 00445 00446 // Insert all list elements into the NodeContainer. 00447 for (MLssize_t c=0; c < numVals; ++c){ 00448 // Get point list value if we have such a list. 00449 Vector6 plVal(0); 00450 if (pl){ 00451 float px=0, py=0, pz=0; 00452 pl->getValue(c, px, py, pz); 00453 plVal[0] = px; 00454 plVal[1] = py; 00455 plVal[2] = pz; 00456 } 00457 00458 // Get point list value if we have such a list. 00459 Vector6 vlVal(0); 00460 int vecType=0; 00461 if (vl){ 00462 float px=0, py=0, pz=0; 00463 vl->getPoint(c, vecType, px, py, pz); 00464 vlVal[0]=px; 00465 vlVal[1]=py; 00466 vlVal[2]=pz; 00467 } 00468 00469 // get position from any of the lists. 00470 Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos : 00471 (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos : 00472 (pl ? plVal : 00473 (vl ? vlVal : Vector6(0)))))); 00474 00475 typename FilterType::NodeType pnt; 00476 pnt.SetValue(0); 00477 pnt.SetIndex(ITKIndexFromMLVec6<ITKML_TYPENAME FilterType::NodeType::IndexType>(mlVec)); 00478 nc->InsertElement(c, pnt); 00479 } 00480 00481 return nc; 00482 } 00483 else{ 00484 return NULL; 00485 } 00486 } 00487 00488 //--------------------------------------------------------------------------- 00495 //--------------------------------------------------------------------------- 00496 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM> 00497 typename itk::Matrix<DTYPE, ROW_DIM, COL_DIM> ITKMatrixFromMLMatrix(const Matrix4 &mat) 00498 { 00499 ML_TRACE_IN("ITKMatrixFromMLMatrix()"); 00500 00501 // Create default matrix. 00502 itk::Matrix<DTYPE, ROW_DIM, COL_DIM> retMat; 00503 retMat.SetIdentity(); 00504 00505 // Do not allow more than four dimensions. 00506 int maxRowDim = ROW_DIM; 00507 if (maxRowDim > 4){ 00508 maxRowDim = 4; 00509 ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION, "Too high row dimension of ITK matrix. Only 4 dimensions will be converted."); 00510 } 00511 int maxColDim = COL_DIM; 00512 if (maxColDim > 4){ 00513 maxColDim = 4; 00514 ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION, "Too high col dimension of ITK matrix. Only 4 dimensions will be converted."); 00515 } 00516 00517 // Copy elements. 00518 for (int row=0; row < maxRowDim; ++row){ 00519 for (int col=0; col < maxColDim; ++col){ 00520 retMat[row][col] = mat[row][col]; 00521 } 00522 } 00523 00524 return retMat; 00525 } 00526 00527 //--------------------------------------------------------------------------- 00535 //--------------------------------------------------------------------------- 00536 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM> 00537 Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix<DTYPE, ROW_DIM, COL_DIM> &mat, bool fillWithID=false) 00538 { 00539 ML_TRACE_IN("MLMatrixFromITKMatrix()"); 00540 00541 // Do not allow more than four dimensions. 00542 int maxRowDim = ROW_DIM; 00543 if (maxRowDim > 4){ 00544 maxRowDim = 4; 00545 ML_PRINT_WARNING("MLMatrixFromITKMatrix", ML_BAD_DIMENSION, "Too high row dimension of ITK matrix. Only 4 dimensions will be converted."); 00546 } 00547 int maxColDim = COL_DIM; 00548 if (maxColDim > 4){ 00549 maxColDim = 4; 00550 ML_PRINT_WARNING("MLMatrixFromITKMatrix", ML_BAD_DIMENSION, "Too high col dimension of ITK matrix. Only 4 dimensions will be converted."); 00551 } 00552 00553 // Copy elements. 00554 Matrix4 retMat; 00555 if (fillWithID){ retMat = Matrix4::getIdentity(); } else { retMat.set(0); } 00556 for (int row=0; row < maxRowDim; ++row){ 00557 for (int col=0; col < maxColDim; ++col){ 00558 retMat[row][col] = mat[row][col]; 00559 } 00560 } 00561 00562 return retMat; 00563 } 00564 00565 //--------------------------------------------------------------------------- 00571 //--------------------------------------------------------------------------- 00572 template<class POINTSETTYPE> 00573 typename POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal) 00574 { 00575 ML_TRACE_IN("ITKPointSetFromBasePointer()"); 00576 00577 XMarkerListContainer *xmlc = NULL; 00578 XMarkerList *xml = NULL; 00579 PointList *pl = NULL; 00580 VectorList *vl = NULL; 00581 00582 // Get base field. 00583 if (baseVal){ 00584 // Check for different base object types. 00585 if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ xmlc = static_cast<XMarkerListContainer*>(baseVal); } 00586 else if (ML_BASE_IS_A(baseVal, XMarkerList)) { xml = static_cast<XMarkerList*>(baseVal); } 00587 else if (ML_BASE_IS_A(baseVal, PointList)) { pl = static_cast<PointList*>(baseVal); } 00588 else if (ML_BASE_IS_A(baseVal, VectorList)) { vl = static_cast<VectorList*>(baseVal); } 00589 else{ /* No valid type in base field. That can happen. */ } 00590 } 00591 00592 // Get number of points from list. 00593 MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) : 00594 (xml ? static_cast<MLssize_t>(xml->size()) : 00595 (pl ? pl->getNum() : 00596 (vl ? vl->getNum() : 0)))); 00597 00598 00599 // Determine maximum point dimension, clamp it to 6. 00600 int maxDim = POINTSETTYPE::PointDimension; 00601 if (maxDim > 6){ 00602 maxDim = 6; 00603 ML_PRINT_WARNING("ITKPointSetFromBasePointer", 00604 ML_BAD_DIMENSION, 00605 "Too high dimension of ITK PointSet. Only 6 dimensions will be converted."); 00606 } 00607 00608 if (numVals > 0){ 00609 00610 // Create point set object. 00611 typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New(); 00612 00613 typedef typename POINTSETTYPE::PointDataContainer DataContainer; 00614 outputPointSet->SetPointData( DataContainer::New()); 00615 outputPointSet->GetPoints()->Reserve( numVals ); 00616 outputPointSet->GetPointData()->Reserve( numVals ); 00617 00618 typename POINTSETTYPE::PointIdentifier pointId = 0; 00619 typename POINTSETTYPE::PointType point; 00620 00621 // Insert all list elements into the NodeContainer. 00622 for (MLssize_t c=0; c < numVals; ++c){ 00623 // Get point list value if we have such a list. 00624 Vector6 plVal(0); 00625 if (pl){ 00626 float px=0, py=0, pz=0; 00627 pl->getValue(c, px, py, pz); 00628 plVal[0] = px; 00629 plVal[1] = py; 00630 plVal[2] = pz; 00631 } 00632 00633 // Get point list value if we have such a list. 00634 Vector6 vlVal(0); 00635 int vecType=0; 00636 if (vl){ 00637 float px=0, py=0, pz=0; 00638 vl->getPoint(c, vecType, px, py, pz); 00639 vlVal[0]=px; 00640 vlVal[1]=py; 00641 vlVal[2]=pz; 00642 } 00643 00644 // get position from any of the lists. 00645 Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos : 00646 (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos : 00647 (pl ? plVal : 00648 (vl ? vlVal : Vector6(0)))))); 00649 00650 // Copy point components. 00651 for (int j=0; j < maxDim ;j++){ point[j] = mlVec[j]; } 00652 outputPointSet->SetPoint(pointId++, point ); 00653 } 00654 00655 return outputPointSet; 00656 } 00657 else{ 00658 // Create and return default (empty) point set object. 00659 typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New(); 00660 return outputPointSet; 00661 } 00662 } 00663 00664 //--------------------------------------------------------------------------- 00668 //--------------------------------------------------------------------------- 00669 template <typename ITK_IMPORT_IMAGE_FILTER_TYPE> 00670 void ITKSetOriginFromVec3(itk::ImportImageFilter<typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType, 00671 ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension>* importImageFilter, 00672 const Vector3 &orig) 00673 { 00674 importImageFilter->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMPORT_IMAGE_FILTER_TYPE::OriginType>(orig,0)); 00675 } 00676 00677 //--------------------------------------------------------------------------- 00681 //--------------------------------------------------------------------------- 00682 template <typename ITK_IMAGE_TYPE> 00683 void ITKSetOriginFromVec3(itk::Image<typename ITK_IMAGE_TYPE::PixelType, 00684 ITK_IMAGE_TYPE::ImageDimension>* image, 00685 const Vector3 &orig) 00686 { 00687 image->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMAGE_TYPE::PointType>(orig,0)); 00688 } 00689 00690 //--------------------------------------------------------------------------- 00709 //--------------------------------------------------------------------------- 00710 template <typename ITK_CLASS_TYPE> 00711 void setITKWorldFromMedicalImageProperty(MedicalImageProperties props, 00712 ITK_CLASS_TYPE *image, 00713 bool correctSVS=true) 00714 { 00715 ML_TRACE_IN("template setITKWorldFromMedicalImageProperty()"); 00716 00717 if (!image){ return; } 00718 00719 // Get ML voxel size/scaling. 00720 const Vector3 scales(props.getVoxelSize()); 00721 00722 // Set voxel spacing, origin and direction cosines of output image and use 1 for unknown higher dimensional components. 00723 image->SetSpacing(ITKVectorFromMLVec3<ITKML_TYPENAME ITK_CLASS_TYPE::SpacingType>(scales, 1)); 00724 00725 // Correct the sub voxel position by translating it to the center. 00726 // In the ML the voxel coordinate is in the corner, in itk and vtk 00727 // it is in the center. 00728 if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3( 0.5, 0.5, 0.5)); } 00729 00730 Matrix4 mat = props.getVoxelToWorldMatrix(); 00731 00732 // Determine image origin for itk image: 00733 // Extract (sub voxel) corrected translation vector. 00734 const Vector3 orig(mat[0][3], mat[1][3], mat[2][3]); 00735 ITKSetOriginFromVec3<ITK_CLASS_TYPE>(image, orig); 00736 00737 // Image direction/orientation: 00738 // Multiply mat with inverse voxel scale factor to get normalized direction cosines/orientation matrix. 00739 const Vector3 invScales(MLValueIs0WOM(scales[0]) ? 1 : 1/scales[0], 00740 MLValueIs0WOM(scales[1]) ? 1 : 1/scales[1], 00741 MLValueIs0WOM(scales[2]) ? 1 : 1/scales[2]); 00742 00743 mat[0][0] = mat[0][0]*invScales[0]; 00744 mat[1][0] = mat[1][0]*invScales[0]; 00745 mat[2][0] = mat[2][0]*invScales[0]; 00746 mat[3][0] = 0; 00747 00748 mat[0][1] = mat[0][1]*invScales[1]; 00749 mat[1][1] = mat[1][1]*invScales[1]; 00750 mat[2][1] = mat[2][1]*invScales[1]; 00751 mat[3][1] = 0; 00752 00753 mat[0][2] = mat[0][2]*invScales[2]; 00754 mat[1][2] = mat[1][2]*invScales[2]; 00755 mat[2][2] = mat[2][2]*invScales[2]; 00756 mat[3][2] = 0; 00757 00758 mat[0][3] = 0; 00759 mat[1][3] = 0; 00760 mat[2][3] = 0; 00761 mat[3][3] = 1; 00762 00763 typename ITK_CLASS_TYPE::DirectionType dirCosines = ITKMatrixFromMLMatrix<MLdouble, 00764 ITK_CLASS_TYPE::DirectionType::RowDimensions, 00765 ITK_CLASS_TYPE::DirectionType::ColumnDimensions>(mat); 00766 image->SetDirection(dirCosines); 00767 } 00768 00769 00770 //--------------------------------------------------------------------------- 00791 //--------------------------------------------------------------------------- 00792 template <typename ITK_CLASS_TYPE> 00793 void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image, 00794 MedicalImageProperties &props, 00795 bool correctSVS=true) 00796 { 00797 ML_TRACE_IN("template setMLWorldFromITKScaleOriginAndOrientation()"); 00798 00799 if (!image){ return; } 00800 if (ITK_CLASS_TYPE::ImageDimension < 2){ 00801 ML_PRINT_ERROR("setMLWorldFromITKScaleOriginAndOrientation", 00802 ML_BAD_PARAMETER, 00803 "1 D itk world matrix conversion is not supported; " 00804 "using identity as return value."); 00805 props.setVoxelToWorldMatrix(Matrix4::getIdentity()); 00806 } 00807 00808 // Get location, voxel scaling and orientation of itk image or importer. 00809 const typename ITK_CLASS_TYPE::SpacingType spacing = image->GetSpacing(); 00810 const typename ITK_CLASS_TYPE::PointType origin = image->GetOrigin(); 00811 const typename ITK_CLASS_TYPE::DirectionType direction = image->GetDirection(); 00812 00813 // Copy 3x3 itk matrix components to corresponding ones in id ML matrix. 00814 const Matrix4 dirCosines = MLMatrixFromITKMatrix<double, 00815 ITK_CLASS_TYPE::ImageDimension, 00816 ITK_CLASS_TYPE::ImageDimension>(direction, true); 00817 00818 // Create the ML world matrix as id and set up scaling, orientation and origin provided by the itk image or importer. 00819 Matrix4 mat = Matrix4::getIdentity(); 00820 00821 // Compose scale, directionCosines and translation to the new ML world matrix. 00822 mat[0][0] = dirCosines[0][0]*spacing[0]; 00823 mat[1][0] = dirCosines[1][0]*spacing[0]; 00824 mat[2][0] = dirCosines[2][0]*spacing[0]; 00825 mat[3][0] = 0; 00826 00827 mat[0][1] = dirCosines[0][1]*spacing[1]; 00828 mat[1][1] = dirCosines[1][1]*spacing[1]; 00829 mat[2][1] = dirCosines[2][1]*spacing[1]; 00830 mat[3][1] = 0; 00831 00832 // Avoid invalid accesses to spacing if we operate on 2D images. 00833 const double spacing2 = (ITK_CLASS_TYPE::ImageDimension > 2) ? spacing[2] : 1; 00834 mat[0][2] = dirCosines[0][2]*spacing2; 00835 mat[1][2] = dirCosines[1][2]*spacing2; 00836 mat[2][2] = dirCosines[2][2]*spacing2; 00837 mat[3][2] = 0; 00838 00839 mat[0][3] = origin[0]; 00840 mat[1][3] = origin[1]; 00841 mat[2][3] = (ITK_CLASS_TYPE::ImageDimension > 2) ? origin[2] : 0; 00842 mat[3][3] = 1; 00843 00844 props.setVoxelToWorldMatrix(mat); 00845 00846 // Subtract half voxel shift - in MedicalImageProperties the matrix considers 00847 // voxel positions at the corner and not in the center. 00848 if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3(-0.5, -0.5, -0.5)); } 00849 } 00850 00851 00852 //--------------------------------------------------------------------------- 00873 //--------------------------------------------------------------------------- 00874 template <typename ITK_INDATATYPE, unsigned int DIM> 00875 typename itk::ImportImageFilter<ITK_INDATATYPE, DIM>::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg, 00876 const MedicalImageProperties &props, 00877 bool correctSVS=true) 00878 { 00879 ML_TRACE_IN("template getITKImageFromSubImg()"); 00880 00881 // Create a new ImportImageFilter. 00882 typedef itk::ImportImageFilter<ITK_INDATATYPE, DIM> ImportFilterType; 00883 typedef typename ImportFilterType::Pointer ImportFilterPointerType; 00884 00885 ImportFilterPointerType importer = ImportFilterType::New(); 00886 00887 // Get box from the input subimage, convert it to a ITK region and 00888 // set it as output image region of the image import filter. 00889 SubImageBox inSubImgBox(inSubImg.getBox()); 00890 importer->SetRegion(ITKRegionFromMLSubImgBox<ImportFilterType>(inSubImgBox)); 00891 00892 // Set voxel spacing, origin and orientation of itk image. 00893 setITKWorldFromMedicalImageProperty<ImportFilterType>(props, &(*importer), correctSVS); 00894 00895 // Set pointer to the data to be imported by the image import filter. 00896 importer->SetImportPointer(static_cast<ITK_INDATATYPE*>(inSubImg.getData()), 00897 inSubImgBox.getNumVoxels(), 00898 false); // we don't want to let ITK managing memory 00899 importer->Update(); 00900 00901 // Return the importer object. 00902 return importer; 00903 } 00904 00905 00906 //---------------------------------------------------------------------------------- 00922 //---------------------------------------------------------------------------------- 00923 template <typename RETURN_TYPE_PTR, typename FILTER_TYPE, typename VOXEL_TYPE> 00924 RETURN_TYPE_PTR getInputAsItkImportImageAndSubImg(Module &op, 00925 int inIdx, 00926 TSubImage<VOXEL_TYPE> &dataSubImg, 00927 bool correctSVS=true) 00928 { 00929 // Get and load connected image only if it's valid and not a a redirected one 00930 // (which may occur in cases of optional mask image inputs). 00931 PagedImage* pInImg = op.getUpdatedInputImage(inIdx); 00932 if (pInImg){ 00933 // Get 3D box input image. 00934 const ImageVector _inImgExt = pInImg->getImageExtent(); 00935 const SubImageBox inImgBox(ImageVector(_inImgExt.x, _inImgExt.y, _inImgExt.z,1,1,1)); 00936 00937 // Check whether TSubImage contains enough memory, if not we need to free and reallocate it. 00938 if (dataSubImg.getData() && (dataSubImg.getBox().getExtent() != inImgBox.getExtent())){ 00939 dataSubImg.free(); 00940 } 00941 // Set up data box and allocate data if still not there. 00942 dataSubImg.setBox(inImgBox); 00943 if (!dataSubImg.getData()){ 00944 dataSubImg.allocateAsMemoryBlockHandle(ML_FATAL_MEMORY_ERROR); 00945 } 00946 if (!dataSubImg.getData()){ 00947 return NULL; 00948 } 00949 00950 // Get image data from input. 00951 MLErrorCode err = pInImg->getTile(dataSubImg); 00952 if (ML_RESULT_OK == err){ 00953 // Create a new ImportImageFilter. 00954 typename FILTER_TYPE::Pointer importer = FILTER_TYPE::New(); 00955 00956 // Get box from the input subimage, convert it to a ITK region and 00957 // set it as output image region of the image import filter. 00958 importer->SetRegion(ITKRegionFromMLSubImgBox<FILTER_TYPE>(inImgBox)); 00959 00960 // Pass world transformation of ML image to world transformation of itk image or importer. 00961 setITKWorldFromMedicalImageProperty<FILTER_TYPE>(*pInImg, &(*importer), correctSVS); 00962 00963 // Set pointer to the data to be imported by the image import filter. 00964 // Pass true to make ITK manage the memory, i.e. if the last import object 00965 // disappears the data also disappears. 00966 importer->SetImportPointer(static_cast<VOXEL_TYPE*>(dataSubImg.getData()), inImgBox.getNumVoxels(), false); 00967 importer->Update(); 00968 return importer->GetOutput(); 00969 } 00970 else{ 00971 ML_PRINT_ERROR("mlITKSupportToolFunctions::getInputAsItkImportImageAndSubImg()", 00972 err, 00973 "Failed to request input image data, probably subsequent operations will fail"); 00974 } 00975 } 00976 00977 // Error, no image could be loaded. 00978 return NULL; 00979 } 00980 00981 00982 ML_END_NAMESPACE 00983 00984 #endif 00985