MeVisLab Toolbox Reference
mlITKSupportToolFunctions.h
Go to the documentation of this file.
1/*************************************************************************************
2**
3** Copyright 2007, MeVis Medical Solutions AG
4**
5** The user may use this file in accordance with the license agreement provided with
6** the Software or, alternatively, in accordance with the terms contained in a
7** written agreement between the user and MeVis Medical Solutions AG.
8**
9** For further information use the contact form at https://www.mevislab.de/contact
10**
11**************************************************************************************/
12
13#pragma once
14
16// Include dll-specific settings.
18
20#include "mlModuleIncludes.h"
21
23#include "mlPointList.h"
24#include "mlVectorList.h"
25#include "mlXMarkerList.h"
26
28#include <itkImage.h>
29#include <itkImportImageFilter.h>
30#include <itkMatrix.h>
31#include <itkPointSet.h>
32#include <itkArray.h>
33#include <itkFixedArray.h>
34
35ML_START_NAMESPACE
36
37//---------------------------------------------------------------------------
47//---------------------------------------------------------------------------
48extern MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e,
49 const Module *module,
50 MLMessageType messageType,
51 const std::string &handling="");
52
53
54
55//---------------------------------------------------------------------------
61//------------------------------------------------------------------------------------
63 size_t itkDataTypeSize,
64 const SubImageBox &itkBox,
65 SubImage &outSubImg);
66
67
68//---------------------------------------------------------------------------
78//---------------------------------------------------------------------------
79template<typename SIZE_TYPE>
80SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec)
81{
82 SIZE_TYPE sizeObj;
83 if (sizeObj.GetSizeDimension() > static_cast<unsigned int>(vec.dim())){
84 ML_PRINT_FATAL_ERROR("ITKSizeFromMLVector",
86 "Too high ITK dimension. The ML can handle only 6 dimensions.");
87 }
88 else{
89 for (unsigned int i=0; i<sizeObj.GetSizeDimension(); i++){
90 sizeObj[i] = static_cast<typename SIZE_TYPE::SizeValueType>(vec[i]);
91 }
92 }
93 return sizeObj;
94}
95
96//---------------------------------------------------------------------------
106//---------------------------------------------------------------------------
107template<typename INDEX_TYPE>
108INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec)
109{
110 INDEX_TYPE sizeObj;
111 if (sizeObj.GetIndexDimension() > static_cast<unsigned int>(vec.dim())){
112 ML_PRINT_FATAL_ERROR("ITKIndexFromMLVector",
114 "Too high ITK dimension. The ML can handle only 6 dimensions.");
115 }
116 else{
117 for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){
118 sizeObj[i] = vec[i];
119 }
120 }
121 return sizeObj;
122}
123
124//---------------------------------------------------------------------------
133//---------------------------------------------------------------------------
134template<typename INDEX_TYPE>
135ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal)
136{
137 ImageVector vec(0);
138 unsigned int sizeDim = sizeObj.GetSizeDimension();
139 unsigned int vecDim = static_cast<unsigned int>(vec.dim());
140 if (sizeDim > vecDim){
141 sizeDim = vecDim;
142 ML_PRINT_WARNING("MLVectorFromITKSize", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
143 }
144
145 for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < sizeDim) ? static_cast<MLint>(sizeObj[i]) : defaultVal; }
146 return vec;
147}
148
149//---------------------------------------------------------------------------
160//---------------------------------------------------------------------------
161template<typename INDEX_TYPE>
162ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal)
163{
164 ImageVector vec(0);
165 unsigned int idxDim = indexObj.GetIndexDimension();
166 unsigned int vecDim = static_cast<unsigned int>(vec.dim());
167 if (idxDim > vecDim){
168 idxDim = vecDim;
169 ML_PRINT_WARNING("MLVectorFromITKIndex", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
170 }
171
172 for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < idxDim) ? indexObj[i] : defaultVal; }
173 return vec;
174}
175
176//---------------------------------------------------------------------------
188//---------------------------------------------------------------------------
189template<typename VECTOR_TYPE>
190VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
191{
192 VECTOR_TYPE sizeObj;
193 for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
194 sizeObj[i] = i < 3 ? vec[i] : defaultComp;
195 }
196 return sizeObj;
197}
198
199//---------------------------------------------------------------------------
211//---------------------------------------------------------------------------
212template<typename VECTOR_TYPE>
213VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
214{
215 VECTOR_TYPE sizeObj;
216 for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
217 sizeObj[i] = i < 4 ? vec[i] : defaultComp;
218 }
219 return sizeObj;
220}
221
222//---------------------------------------------------------------------------
234//---------------------------------------------------------------------------
235template<typename POINT_TYPE>
236POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
237{
238 POINT_TYPE sizeObj;
239 for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
240 sizeObj[i] = i < 3 ? vec[i] : defaultComp;
241 }
242 return sizeObj;
243}
244
245//---------------------------------------------------------------------------
257//---------------------------------------------------------------------------
258template<typename POINT_TYPE>
259POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
260{
261 POINT_TYPE sizeObj;
262 for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
263 sizeObj[i] = i < 4 ? vec[i] : defaultComp;
264 }
265 return sizeObj;
266}
267
268
269//---------------------------------------------------------------------------
279//---------------------------------------------------------------------------
280template<typename REGION_PARENT_TYPE>
281typename REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox)
282{
283 typename REGION_PARENT_TYPE::RegionType region;
284
285 // Set ITK region origin to the ML SubImageBox origin.
287
288 // Set ITK region extent to the ML SubImageBox extent.
290 return region;
291}
292
293//---------------------------------------------------------------------------
301//---------------------------------------------------------------------------
302template<typename REGION_PARENT_TYPE>
303SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType &region)
304{
305 // Get ITK region origin into the ML SubImageBox origin.
306 // For dimensions not specified by ITK use coordinate 0.
307 SubImageBox box;
308 box.v1 = MLVectorFromITKIndex(region.GetIndex(), 0);
309
310 // Get ITK region extent into the ML SubImageBox extent.
311 // For dimensions not specified by ITK use extent 1.
312 ImageVector ext = MLVectorFromITKSize(region.GetSize(), 1);
313
314 // Return the constructed SubImageBox.
315 box.v2 = box.v1 + (ext - ImageVector(1));
316 return box;
317}
318
319//---------------------------------------------------------------------------
322//---------------------------------------------------------------------------
323template<typename ARRAY_TYPE, typename STL_VECTOR>
324ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec)
325{
326 const size_t mFieldSize = stlVec.size();
327 ARRAY_TYPE retArray(mFieldSize);
328 for (size_t i=0; i<mFieldSize; ++i){ retArray[i] = stlVec[i]; }
329 return retArray;
330}
331
332//---------------------------------------------------------------------------
335//---------------------------------------------------------------------------
336template<typename VERSOR_TYPE>
337VERSOR_TYPE ITKVersorFromMLVector(const ml::Vector4 &mlVec)
338{
339 VERSOR_TYPE Rotation;
340 Rotation.Set(mlVec[0], mlVec[1], mlVec[2], mlVec[3]);
341 return Rotation;
342}
343
344//---------------------------------------------------------------------------
346//---------------------------------------------------------------------------
347template<typename ARR_TYP, unsigned int ARR_SIZE>
348size_t GetSizeOfAnITKArray(const itk::FixedArray<ARR_TYP, ARR_SIZE> &itkArray)
349{
350 return itkArray.Length;
351}
352
353//---------------------------------------------------------------------------
355//---------------------------------------------------------------------------
356template<typename ITK_ARRAY_TYPE>
357size_t GetSizeOfAnITKArray(const ITK_ARRAY_TYPE &itkArray)
358{
359 return itkArray.size();
360}
361
362//---------------------------------------------------------------------------
366//---------------------------------------------------------------------------
367template<typename STL_CONTAINER, typename ITK_ARRAY_TYPE>
368const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
369{
370 const size_t itkFieldSize = GetSizeOfAnITKArray(itkArray);
371 STL_CONTAINER stlVector;
372 for (size_t i=0; i<itkFieldSize; ++i){ stlVector.push_back(itkArray[i]); }
373 return stlVector;
374}
375
376//---------------------------------------------------------------------------
380//---------------------------------------------------------------------------
381template<typename ITK_VERSOR_TYPE>
382const ml::Vector4 MLVectorFromITKVersor(const ITK_VERSOR_TYPE &itkVersor)
383{
384 ml::Vector4 mlVector(itkVersor.GetX(), itkVersor.GetY(), itkVersor.GetZ(), itkVersor.GetW());
385 return mlVector;
386}
387
388//---------------------------------------------------------------------------
400//---------------------------------------------------------------------------
401template<typename INDEX_TYPE>
402INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
403{
404 INDEX_TYPE sizeObj;
405 if (sizeObj.GetIndexDimension() > 6){
406 ML_PRINT_FATAL_ERROR("ITKIndexFromMLVec6", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
407 }
408 else{
409 for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; }
410 }
411 return sizeObj;
412}
413
414
415//---------------------------------------------------------------------------
421//---------------------------------------------------------------------------
422template<class FilterType>
423typename FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
424{
425 XMarkerListContainer *xmlc = nullptr;
426 XMarkerList *xml = nullptr;
427 PointList *pl = nullptr;
428 VectorList *vl = nullptr;
429
430 // Get base field.
431 if (baseVal){
432 // Check for different base object types.
433 if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){
434 xmlc = static_cast<XMarkerListContainer*>(baseVal);
435 }
436 else if (ML_BASE_IS_A(baseVal, XMarkerList)){
437 xml = static_cast<XMarkerList*>(baseVal);
438 }
439 else if (ML_BASE_IS_A(baseVal, PointList)){
440 pl = static_cast<PointList*>(baseVal);
441 }
442 else if (ML_BASE_IS_A(baseVal, VectorList)){
443 vl = static_cast<VectorList*>(baseVal);
444 }
445 else{
446 // No valid type in base field. That can happen.
447 }
448 }
449
450 // Get number of points from list.
451 MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
452 (xml ? static_cast<MLssize_t>(xml->size()) :
453 (pl ? pl->getNum() :
454 (vl ? vl->getNum() : 0))));
455
456
457 if (numVals > 0){
458 // Create a NodeContainer and initialize it.
459 typename FilterType::NodeContainer::Pointer nc = FilterType::NodeContainer::New();
460 nc->Initialize();
461
462 // Insert all list elements into the NodeContainer.
463 for (MLssize_t c=0; c < numVals; ++c){
464 // Get point list value if we have such a list.
465 Vector6 plVal(0);
466 if (pl){
467 float px=0, py=0, pz=0;
468 pl->getValue(c, px, py, pz);
469 plVal[0] = px;
470 plVal[1] = py;
471 plVal[2] = pz;
472 }
473
474 // Get point list value if we have such a list.
475 Vector6 vlVal(0);
476 int vecType=0;
477 if (vl){
478 float px=0, py=0, pz=0;
479 vl->getPoint(c, vecType, px, py, pz);
480 vlVal[0]=px;
481 vlVal[1]=py;
482 vlVal[2]=pz;
483 }
484
485 // get position from any of the lists.
486 Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
487 (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
488 (pl ? plVal :
489 (vl ? vlVal : Vector6(0))))));
490
491 typename FilterType::NodeType pnt;
492 pnt.SetValue(0);
494 nc->InsertElement(c, pnt);
495 }
496
497 return nc;
498 }
499 else{
500 return nullptr;
501 }
502}
503
504//---------------------------------------------------------------------------
507//---------------------------------------------------------------------------
509
510//---------------------------------------------------------------------------
517//---------------------------------------------------------------------------
518template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
519typename itk::Matrix<DTYPE, ROW_DIM, COL_DIM> ITKMatrixFromMLMatrix(const Matrix4 &mat)
520{
521 // Create default matrix.
522 itk::Matrix<DTYPE, ROW_DIM, COL_DIM> retMat;
523 retMat.SetIdentity();
524
525 // Do not allow more than four dimensions.
526 unsigned int maxRowDim = ROW_DIM;
527 if (maxRowDim > 4){
528 maxRowDim = 4;
529 ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
530 "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
531 }
532 unsigned int maxColDim = COL_DIM;
533 if (maxColDim > 4){
534 maxColDim = 4;
535 ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
536 "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
537 }
538
539 // Copy elements.
540 for (unsigned int row=0; row < maxRowDim; ++row){
541 for (unsigned int col=0; col < maxColDim; ++col){
542 retMat[row][col] = mat[row][col];
543 }
544 }
545
546 return retMat;
547}
548
549//---------------------------------------------------------------------------
559//---------------------------------------------------------------------------
560template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
561Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix<DTYPE, ROW_DIM, COL_DIM> &mat,
562 bool fillWithID=false,
563 bool suppressDimensionWarning=false)
564{
565 // Do not allow more than four dimensions.
566 unsigned int maxRowDim = ROW_DIM;
567 if (maxRowDim > 4){
568 maxRowDim = 4;
569 if (!suppressDimensionWarning){
570 ML_PRINT_WARNING("MLMatrixFromITKMatrix",
572 "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
573 }
574 }
575 unsigned int maxColDim = COL_DIM;
576 if (maxColDim > 4){
577 maxColDim = 4;
578 if (!suppressDimensionWarning){
579 ML_PRINT_WARNING("MLMatrixFromITKMatrix",
581 "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
582 }
583 }
584
585 // Copy elements.
586 Matrix4 retMat;
587 if (fillWithID){ retMat = Matrix4::getIdentity(); } else { retMat.set(0); }
588 for (unsigned int row=0; row < maxRowDim; ++row){
589 for (unsigned int col=0; col < maxColDim; ++col){
590 retMat[row][col] = mat[row][col];
591 }
592 }
593
594 return retMat;
595}
596
597//---------------------------------------------------------------------------
603//---------------------------------------------------------------------------
604template<class POINTSETTYPE>
605typename POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
606{
607 XMarkerListContainer *xmlc = nullptr;
608 XMarkerList *xml = nullptr;
609 PointList *pl = nullptr;
610 VectorList *vl = nullptr;
611
612 // Get base field.
613 if (baseVal){
614 // Check for different base object types.
615 if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ xmlc = static_cast<XMarkerListContainer*>(baseVal); }
616 else if (ML_BASE_IS_A(baseVal, XMarkerList)) { xml = static_cast<XMarkerList*>(baseVal); }
617 else if (ML_BASE_IS_A(baseVal, PointList)) { pl = static_cast<PointList*>(baseVal); }
618 else if (ML_BASE_IS_A(baseVal, VectorList)) { vl = static_cast<VectorList*>(baseVal); }
619 else{ /* No valid type in base field. That can happen. */ }
620 }
621
622 // Get number of points from list.
623 MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
624 (xml ? static_cast<MLssize_t>(xml->size()) :
625 (pl ? pl->getNum() :
626 (vl ? vl->getNum() : 0))));
627
628
629 // Determine maximum point dimension, clamp it to 6.
630 int maxDim = POINTSETTYPE::PointDimension;
631 if (maxDim > 6){
632 maxDim = 6;
633 ML_PRINT_WARNING("ITKPointSetFromBasePointer",
635 "Too high dimension of ITK PointSet. Only 6 dimensions will be converted.");
636 }
637
638 if (numVals > 0){
639
640 // Create point set object.
641 typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
642
643 typedef typename POINTSETTYPE::PointDataContainer DataContainer;
644 outputPointSet->SetPointData( DataContainer::New());
645 outputPointSet->GetPoints()->Reserve( numVals );
646 outputPointSet->GetPointData()->Reserve( numVals );
647
648 typename POINTSETTYPE::PointIdentifier pointId = 0;
649 typename POINTSETTYPE::PointType point;
650
651 // Insert all list elements into the NodeContainer.
652 for (MLssize_t c=0; c < numVals; ++c){
653 // Get point list value if we have such a list.
654 Vector6 plVal(0);
655 if (pl){
656 float px=0, py=0, pz=0;
657 pl->getValue(c, px, py, pz);
658 plVal[0] = px;
659 plVal[1] = py;
660 plVal[2] = pz;
661 }
662
663 // Get point list value if we have such a list.
664 Vector6 vlVal(0);
665 int vecType=0;
666 if (vl){
667 float px=0, py=0, pz=0;
668 vl->getPoint(c, vecType, px, py, pz);
669 vlVal[0]=px;
670 vlVal[1]=py;
671 vlVal[2]=pz;
672 }
673
674 // get position from any of the lists.
675 Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
676 (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
677 (pl ? plVal :
678 (vl ? vlVal : Vector6(0))))));
679
680 // Copy point components.
681 for (int j=0; j < maxDim ;j++){ point[j] = mlVec[j]; }
682 outputPointSet->SetPoint(pointId++, point );
683 }
684
685 return outputPointSet;
686 }
687 else{
688 // Create and return default (empty) point set object.
689 typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
690 return outputPointSet;
691 }
692}
693
694//---------------------------------------------------------------------------
698//---------------------------------------------------------------------------
699template <typename ITK_IMPORT_IMAGE_FILTER_TYPE>
700void ITKSetOriginFromVec3(itk::ImportImageFilter<typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType,
701 ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension>* importImageFilter,
702 const Vector3 &orig)
703{
705}
706
707//---------------------------------------------------------------------------
711//---------------------------------------------------------------------------
712template <typename ITK_IMAGE_TYPE>
713void ITKSetOriginFromVec3(itk::Image<typename ITK_IMAGE_TYPE::PixelType,
714 ITK_IMAGE_TYPE::ImageDimension>* image,
715 const Vector3 &orig)
716{
718}
719
720//---------------------------------------------------------------------------
739//---------------------------------------------------------------------------
740template <typename ITK_CLASS_TYPE>
742 ITK_CLASS_TYPE *image,
743 bool correctSVS=true)
744{
745 if (!image){ return; }
746
747 // Get ML voxel size/scaling.
748 const Vector3 scales(props.getVoxelSize());
749
750 // Set voxel spacing, origin and direction cosines of output image and use 1 for unknown higher dimensional components.
752
753 // Correct the sub voxel position by translating it to the center.
754 // In the ML the voxel coordinate is in the corner, in itk and vtk
755 // it is in the center.
756 if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3( 0.5, 0.5, 0.5)); }
757
758 Matrix4 mat = props.getVoxelToWorldMatrix();
759
760 // Determine image origin for itk image:
761 // Extract (sub voxel) corrected translation vector.
762 const Vector3 orig(mat[0][3], mat[1][3], mat[2][3]);
764
765 // Image direction/orientation:
766 // Multiply mat with inverse voxel scale factor to get normalized direction cosines/orientation matrix.
767 const Vector3 invScales(MLValueIs0WOM(scales[0]) ? 1 : 1/scales[0],
768 MLValueIs0WOM(scales[1]) ? 1 : 1/scales[1],
769 MLValueIs0WOM(scales[2]) ? 1 : 1/scales[2]);
770
771 mat[0][0] = mat[0][0]*invScales[0];
772 mat[1][0] = mat[1][0]*invScales[0];
773 mat[2][0] = mat[2][0]*invScales[0];
774 mat[3][0] = 0;
775
776 mat[0][1] = mat[0][1]*invScales[1];
777 mat[1][1] = mat[1][1]*invScales[1];
778 mat[2][1] = mat[2][1]*invScales[1];
779 mat[3][1] = 0;
780
781 mat[0][2] = mat[0][2]*invScales[2];
782 mat[1][2] = mat[1][2]*invScales[2];
783 mat[2][2] = mat[2][2]*invScales[2];
784 mat[3][2] = 0;
785
786 mat[0][3] = 0;
787 mat[1][3] = 0;
788 mat[2][3] = 0;
789 mat[3][3] = 1;
790
791 typename ITK_CLASS_TYPE::DirectionType dirCosines = ITKMatrixFromMLMatrix<MLdouble,
792 ITK_CLASS_TYPE::DirectionType::RowDimensions,
793 ITK_CLASS_TYPE::DirectionType::ColumnDimensions>(mat);
794 image->SetDirection(dirCosines);
795}
796
797
798//---------------------------------------------------------------------------
823//---------------------------------------------------------------------------
824template <typename ITK_CLASS_TYPE>
825void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image,
827 bool correctSVS=true,
828 bool suppressDimensionWarning=false)
829{
830 if (!image){ return; }
831 if (ITK_CLASS_TYPE::ImageDimension < 2){
832 ML_PRINT_ERROR("setMLWorldFromITKScaleOriginAndOrientation",
834 "1 D itk world matrix conversion is not supported; "
835 "using identity as return value.");
837 }
838
839 // Get location, voxel scaling and orientation of itk image or importer.
840 const typename ITK_CLASS_TYPE::SpacingType spacing = image->GetSpacing();
841 const typename ITK_CLASS_TYPE::PointType origin = image->GetOrigin();
842 const typename ITK_CLASS_TYPE::DirectionType direction = image->GetDirection();
843
844 // Copy 3x3 itk matrix components to corresponding ones in id ML matrix.
845 const Matrix4 dirCosines = MLMatrixFromITKMatrix<double,
846 ITK_CLASS_TYPE::ImageDimension,
847 ITK_CLASS_TYPE::ImageDimension>(direction, true, suppressDimensionWarning);
848
849 // Create the ML world matrix as id and set up scaling, orientation and origin provided by the itk image or importer.
851
852 // Compose scale, directionCosines and translation to the new ML world matrix.
853 mat[0][0] = dirCosines[0][0]*spacing[0];
854 mat[1][0] = dirCosines[1][0]*spacing[0];
855 mat[2][0] = dirCosines[2][0]*spacing[0];
856 mat[3][0] = 0;
857
858 mat[0][1] = dirCosines[0][1]*spacing[1];
859 mat[1][1] = dirCosines[1][1]*spacing[1];
860 mat[2][1] = dirCosines[2][1]*spacing[1];
861 mat[3][1] = 0;
862
863 // Avoid invalid accesses to spacing if we operate on 2D images.
864 const double spacing2 = (ITK_CLASS_TYPE::ImageDimension > 2) ? spacing[2] : 1;
865 mat[0][2] = dirCosines[0][2]*spacing2;
866 mat[1][2] = dirCosines[1][2]*spacing2;
867 mat[2][2] = dirCosines[2][2]*spacing2;
868 mat[3][2] = 0;
869
870 mat[0][3] = origin[0];
871 mat[1][3] = origin[1];
872 mat[2][3] = (ITK_CLASS_TYPE::ImageDimension > 2) ? origin[2] : 0;
873 mat[3][3] = 1;
874
875 props.setVoxelToWorldMatrix(mat);
876
877 // Subtract half voxel shift - in MedicalImageProperties the matrix considers
878 // voxel positions at the corner and not in the center.
879 if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3(-0.5, -0.5, -0.5)); }
880}
881
882
883//---------------------------------------------------------------------------
904//---------------------------------------------------------------------------
905template <typename ITK_INDATATYPE, unsigned int DIM>
906typename itk::ImportImageFilter<ITK_INDATATYPE, DIM>::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg,
907 const MedicalImageProperties &props,
908 bool correctSVS=true)
909{
910 // Create a new ImportImageFilter.
911 typedef itk::ImportImageFilter<ITK_INDATATYPE, DIM> ImportFilterType;
912 typedef typename ImportFilterType::Pointer ImportFilterPointerType;
913
914 ImportFilterPointerType importer = ImportFilterType::New();
915
916 // Get box from the input subimage, convert it to a ITK region and
917 // set it as output image region of the image import filter.
918 SubImageBox inSubImgBox(inSubImg.getBox());
919 importer->SetRegion(ITKRegionFromMLSubImgBox<ImportFilterType>(inSubImgBox));
920
921 // Set voxel spacing, origin and orientation of itk image.
922 setITKWorldFromMedicalImageProperty<ImportFilterType>(props, &(*importer), correctSVS);
923
924 // Set pointer to the data to be imported by the image import filter.
925 importer->SetImportPointer(static_cast<ITK_INDATATYPE*>(inSubImg.getData()),
926 static_cast<itk::SizeValueType>(inSubImgBox.getNumVoxels()),
927 false); // we don't want to let ITK managing memory
928 importer->Update();
929
930 // Return the importer object.
931 return importer;
932}
933
934
935 //----------------------------------------------------------------------------------
951 //----------------------------------------------------------------------------------
952 template <typename RETURN_TYPE_PTR, typename FILTER_TYPE, typename VOXEL_TYPE>
954 int inIdx,
955 TSubImage<VOXEL_TYPE> &dataSubImg,
956 bool correctSVS=true)
957 {
958 // Get and load connected image only if it's valid and not a a redirected one
959 // (which may occur in cases of optional mask image inputs).
960 PagedImage* pInImg = op.getUpdatedInputImage(inIdx);
961 if (pInImg){
962 // Get 3D box input image.
963 const ImageVector _inImgExt = pInImg->getImageExtent();
964 const SubImageBox inImgBox(ImageVector(_inImgExt.x, _inImgExt.y, _inImgExt.z,1,1,1));
965
966 // Check whether TSubImage contains enough memory, if not we need to free and reallocate it.
967 if (dataSubImg.getData() && (dataSubImg.getBox().getExtent() != inImgBox.getExtent())){
968 dataSubImg.free();
969 }
970 // Set up data box and allocate data if still not there.
971 dataSubImg.setBox(inImgBox);
972 if (!dataSubImg.getData()){
974 }
975 if (!dataSubImg.getData()){
976 return nullptr;
977 }
978
979 // Get image data from input.
980 MLErrorCode err = pInImg->getTile(dataSubImg);
981 if (ML_RESULT_OK == err){
982 // Create a new ImportImageFilter.
983 typename FILTER_TYPE::Pointer importer = FILTER_TYPE::New();
984
985 // Get box from the input subimage, convert it to a ITK region and
986 // set it as output image region of the image import filter.
987 importer->SetRegion(ITKRegionFromMLSubImgBox<FILTER_TYPE>(inImgBox));
988
989 // Pass world transformation of ML image to world transformation of itk image or importer.
990 setITKWorldFromMedicalImageProperty<FILTER_TYPE>(*pInImg, &(*importer), correctSVS);
991
992 // Set pointer to the data to be imported by the image import filter.
993 // Pass true to make ITK manage the memory, i.e. if the last import object
994 // disappears the data also disappears.
995 importer->SetImportPointer(static_cast<VOXEL_TYPE*>(dataSubImg.getData()), inImgBox.getNumVoxels(), false);
996 importer->Update();
997 return importer->GetOutput();
998 }
999 else{
1000 ML_PRINT_ERROR("mlITKSupportToolFunctions::getInputAsItkImportImageAndSubImg()",
1001 err,
1002 "Failed to request input image data, probably subsequent operations will fail");
1003 }
1004 }
1005
1006 // Error, no image could be loaded.
1007 return nullptr;
1008 }
1009
1010ML_END_NAMESPACE
BaseItem * getItemAt(MLssize_t index) override
Definition mlListBase.h:693
ImageVector getImageExtent() const
Returns the extent of the (sub)image.
Vector3 getVoxelSize() const
Returns the voxel size.
void setVoxelToWorldMatrix(const Matrix4 &matrix)
Sets the matrix that transforms voxel to world coordinates to matrix.
void translateVoxelToWorldMatrix(const Vector3 &offsetVector)
Translates the voxelToWorld matrix by the offsetVector.
const Matrix4 & getVoxelToWorldMatrix() const
Returns the voxelToWorld matrix.
PagedImage * getUpdatedInputImage(MLint inputIndex, bool getReal=false) const
MLEXPORT MLErrorCode getTile(SubImageBox location, MLDataType dataType, void **data, const ScaleShiftData &scaleShiftData=ScaleShiftData(), MLRequestProgressCB *progressCallback=nullptr, void *progressCallbackUserData=nullptr)
Base object class PointList managing a list of points.
Definition mlPointList.h:29
void getValue(MLssize_t index, Vector3 &vec) const
get point at given index
MLssize_t getNum() const
returns the number of contained points
Class to handle Rotations (internally, the rotation is stored as a unit quaternion).
Definition mlRotation.h:38
void setBox(const SubImageBox &subImageBox)
Definition mlSubImage.h:163
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition mlSubImage.h:230
MLEXPORT void allocateAsMemoryBlockHandle(MLMemoryErrorHandling handleFailure=ML_RETURN_NULL)
Allocates data using the ML memory manager. For failure handing, see SubImage::allocate().
MLEXPORT void free()
void * getData() const
Returns the memory address of the memory managed by the subimage.
Definition mlSubImage.h:372
static MLint dim()
Returns the dimension the ML calculates with.
intT getNumVoxels() const
VectorType getExtent() const
const DATATYPE * getData() const
Returns the memory address of the image region. Overloads methods from SubImage.
ComponentType z
Z component of the vector.
ComponentType x
X component of the vector.
ComponentType y
Y component of the vector.
void set(const DT val)
Sets all values to val.
Definition mlMatrix4.h:265
static Tmat4< MLdouble > getIdentity()
Base object representing a list of vectors given as Vector4's.
void getPoint(MLssize_t index, int &type, float &x1, float &y1, float &z1) const
returns point of vectors at given point index (NOTE: (0,1 = first vector , 2,3 = second vector))
MLssize_t getNum() const
returns the number of contained points
#define ML_BASE_IS_A(base, type)
bool MLValueIs0WOM(MLint8 a)
#define ML_BAD_PARAMETER
Definition mlTypeDefs.h:822
#define ML_BAD_DIMENSION
The image or data structure has wrong extent or dimensions.
Definition mlTypeDefs.h:834
MLint32 MLErrorCode
Type of an ML Error code.
Definition mlTypeDefs.h:715
#define ML_RESULT_OK
No error. Everything seems to be okay.
Definition mlTypeDefs.h:723
#define ML_PRINT_FATAL_ERROR(FUNC_NAME, REASON, HANDLING)
#define ML_PRINT_WARNING(FUNC_NAME, REASON, HANDLING)
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
#define MLITK_SUPPORT_EXPORT
#define ITKML_TYPENAME
@ ML_FATAL_MEMORY_ERROR
On allocation failure, a fatal error print is done and NULL is returned.
Definition mlTypeDefs.h:676
double MLdouble
Definition mlTypeDefs.h:216
MLint64 MLint
Definition mlTypeDefs.h:489
SSIZE_T MLssize_t
The signed ML size type that is a signed 32-bit size_t on 32-bit platforms and 64-bit one on 64-bit p...
Definition mlTypeDefs.h:565
MLMessageType
Message types handled by the ErrorOutput class.
Definition mlTypeDefs.h:695
ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal)
void setITKWorldFromMedicalImageProperty(MedicalImageProperties props, ITK_CLASS_TYPE *image, bool correctSVS=true)
const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
MLITK_SUPPORT_EXPORT void setAllowedTypesForITKNodeContainer(BaseField *field)
FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox)
POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
Tvec4< MLdouble > Vector4
A vector with four components of type double.
Definition mlVector4.h:162
Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix< DTYPE, ROW_DIM, COL_DIM > &mat, bool fillWithID=false, bool suppressDimensionWarning=false)
POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
const ml::Vector4 MLVectorFromITKVersor(const ITK_VERSOR_TYPE &itkVersor)
void ITKSetOriginFromVec3(itk::ImportImageFilter< typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType, ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension > *importImageFilter, const Vector3 &orig)
Tmat4< MLdouble > Matrix4
The standard 4x4 matrix of type double.
Definition mlMatrix4.h:713
VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
Tvec3< MLdouble > Vector3
A vector with three components of type double.
Definition mlVector3.h:286
POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
size_t GetSizeOfAnITKArray(const itk::FixedArray< ARR_TYP, ARR_SIZE > &itkArray)
Returns the size of an itk::FixedArray.
Tvec6< MLdouble > Vector6
A vector with six components of type double.
Definition mlVector6.h:194
MLITK_SUPPORT_EXPORT void copyITKDataBufferToMLSubImg(void *itkData, size_t itkDataTypeSize, const SubImageBox &itkBox, SubImage &outSubImg)
SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec)
TSubImageBox< MLint > SubImageBox
Defines the standard SubImageBox type used in the ML. Its size varies with the size of the MLint type...
RETURN_TYPE_PTR getInputAsItkImportImageAndSubImg(Module &op, int inIdx, TSubImage< VOXEL_TYPE > &dataSubImg, bool correctSVS=true)
itk::Matrix< DTYPE, ROW_DIM, COL_DIM > ITKMatrixFromMLMatrix(const Matrix4 &mat)
VERSOR_TYPE ITKVersorFromMLVector(const ml::Vector4 &mlVec)
SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType &region)
ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal)
INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec)
INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image, MedicalImageProperties &props, bool correctSVS=true, bool suppressDimensionWarning=false)
ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec)
itk::ImportImageFilter< ITK_INDATATYPE, DIM >::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg, const MedicalImageProperties &props, bool correctSVS=true)
MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e, const Module *module, MLMessageType messageType, const std::string &handling="")
TImageVector< MLint > ImageVector
Defines the standard ImageVector type that is used by the ML for indexing and coordinates.
VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp)