12 #ifndef mitkCLPolyToNrrd_cpp 13 #define mitkCLPolyToNrrd_cpp 52 #include <itkImageDuplicator.h> 53 #include <itkImageRegionIterator.h> 56 #include "itkNearestNeighborInterpolateImageFunction.h" 57 #include "itkResampleImageFilter.h" 59 #include <QApplication> 63 #include "vtkRenderLargeImage.h" 64 #include "vtkPNGWriter.h" 71 template <
class charT>
72 class punct_facet :
public std::numpunct<charT> {
74 punct_facet(charT sep) :
80 charT do_decimal_point()
const override {
return m_Sep; }
85 template<
typename TPixel,
unsigned int VImageDimension>
89 typedef itk::Image<TPixel, VImageDimension>
ImageType;
90 typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilterType;
92 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
93 auto spacing = itkImage->GetSpacing();
94 auto size = itkImage->GetLargestPossibleRegion().GetSize();
96 for (
unsigned int i = 0; i < VImageDimension; ++i)
98 size[i] = size[i] / (1.0*resolution)*(1.0*spacing[i])+1.0;
100 spacing.Fill(resolution);
102 resampler->SetInput(itkImage);
103 resampler->SetSize(size);
104 resampler->SetOutputSpacing(spacing);
105 resampler->SetOutputOrigin(itkImage->GetOrigin());
106 resampler->SetOutputDirection(itkImage->GetDirection());
109 newImage->InitializeByItk(resampler->GetOutput());
114 template<
typename TPixel,
unsigned int VImageDimension>
118 typedef itk::Image< TPixel, VImageDimension> LFloatImageType;
119 typedef itk::Image< unsigned short, VImageDimension> LMaskImageType;
120 typename LMaskImageType::Pointer itkMask = LMaskImageType::New();
124 typedef itk::ImageDuplicator< LMaskImageType > DuplicatorType;
125 typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
126 duplicator->SetInputImage(itkMask);
127 duplicator->Update();
129 auto tmpMask = duplicator->GetOutput();
131 itk::ImageRegionIterator<LMaskImageType> mask1Iter(itkMask, itkMask->GetLargestPossibleRegion());
132 itk::ImageRegionIterator<LMaskImageType> mask2Iter(tmpMask, tmpMask->GetLargestPossibleRegion());
133 itk::ImageRegionIterator<LFloatImageType> imageIter(itkValue, itkValue->GetLargestPossibleRegion());
134 while (!mask1Iter.IsAtEnd())
137 if (mask1Iter.Value() > 0)
140 if (imageIter.Value() == imageIter.Value())
150 newMask->InitializeByItk(tmpMask);
154 template<
typename TPixel,
unsigned int VImageDimension>
158 typedef itk::Image< TPixel, VImageDimension> LMaskImageType;
159 typedef itk::NearestNeighborInterpolateImageFunction< LMaskImageType> NearestNeighborInterpolateImageFunctionType;
160 typedef itk::ResampleImageFilter<LMaskImageType, LMaskImageType> ResampleFilterType;
162 typename NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New();
163 typename LMaskImageType::Pointer itkRef = LMaskImageType::New();
167 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
168 resampler->SetInput(itkMoving);
169 resampler->SetReferenceImage(itkRef);
170 resampler->UseReferenceImageOn();
171 resampler->SetInterpolator(nn_interpolator);
174 newMask->InitializeByItk(resampler->GetOutput());
182 std::vector<mitk::Image::Pointer> &imageVector,
183 std::vector<mitk::Image::Pointer> &maskVector,
184 std::vector<mitk::Image::Pointer> &maskNoNaNVector,
185 std::vector<mitk::Image::Pointer> &morphMaskVector)
187 typedef itk::Image< double, 2 > FloatImage2DType;
188 typedef itk::Image< unsigned short, 2 > MaskImage2DType;
190 FloatImageType::Pointer itkFloat = FloatImageType::New();
191 MaskImageType::Pointer itkMask = MaskImageType::New();
192 MaskImageType::Pointer itkMaskNoNaN = MaskImageType::New();
193 MaskImageType::Pointer itkMorphMask = MaskImageType::New();
199 int idxA, idxB, idxC;
203 idxA = 1; idxB = 2; idxC = 0;
206 idxA = 0; idxB = 2; idxC = 1;
209 idxA = 0; idxB = 1; idxC = 2;
212 idxA = 1; idxB = 2; idxC = 0;
216 auto imageSize = image->GetLargestPossibleRegion().GetSize();
217 FloatImageType::IndexType index3D;
218 FloatImage2DType::IndexType index2D;
219 FloatImage2DType::SpacingType spacing2D;
220 spacing2D[0] = itkFloat->GetSpacing()[idxA];
221 spacing2D[1] = itkFloat->GetSpacing()[idxB];
223 for (
unsigned int i = 0; i < imageSize[idxC]; ++i)
225 FloatImage2DType::RegionType region;
226 FloatImage2DType::IndexType start;
227 FloatImage2DType::SizeType size;
228 start[0] = 0; start[1] = 0;
229 size[0] = imageSize[idxA];
230 size[1] = imageSize[idxB];
231 region.SetIndex(start);
232 region.SetSize(size);
234 FloatImage2DType::Pointer image2D = FloatImage2DType::New();
235 image2D->SetRegions(region);
238 MaskImage2DType::Pointer mask2D = MaskImage2DType::New();
239 mask2D->SetRegions(region);
242 MaskImage2DType::Pointer masnNoNaN2D = MaskImage2DType::New();
243 masnNoNaN2D->SetRegions(region);
244 masnNoNaN2D->Allocate();
246 MaskImage2DType::Pointer morph2D = MaskImage2DType::New();
247 morph2D->SetRegions(region);
251 unsigned long voxelsInMask = 0;
253 for (
unsigned int a = 0; a < imageSize[idxA]; ++a)
255 for (
unsigned int b = 0; b < imageSize[idxB]; ++b)
262 image2D->SetPixel(index2D, itkFloat->GetPixel(index3D));
263 mask2D->SetPixel(index2D, itkMask->GetPixel(index3D));
264 masnNoNaN2D->SetPixel(index2D, itkMaskNoNaN->GetPixel(index3D));
265 morph2D->SetPixel(index2D, itkMorphMask->GetPixel(index3D));
266 voxelsInMask += (itkMask->GetPixel(index3D) > 0) ? 1 : 0;
271 image2D->SetSpacing(spacing2D);
272 mask2D->SetSpacing(spacing2D);
273 masnNoNaN2D->SetSpacing(spacing2D);
274 morph2D->SetSpacing(spacing2D);
277 tmpFloatImage->InitializeByItk(image2D.GetPointer());
281 tmpMaskImage->InitializeByItk(mask2D.GetPointer());
285 tmpMaskNoNaNImage->InitializeByItk(masnNoNaN2D.GetPointer());
289 tmpMorphMaskImage->InitializeByItk(morph2D.GetPointer());
292 if (voxelsInMask > 0)
294 imageVector.push_back(tmpFloatImage);
295 maskVector.push_back(tmpMaskImage);
296 maskNoNaNVector.push_back(tmpMaskNoNaNImage);
297 morphMaskVector.push_back(tmpMorphMaskImage);
311 nodeI->SetData(image);
313 nodeM->SetData(mask);
317 auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll());
321 unsigned int numberOfSteps = 1;
322 if (sliceNaviController)
324 numberOfSteps = sliceNaviController->GetSlice()->GetSteps();
325 sliceNaviController->GetSlice()->SetPos(0);
329 renderWindow.resize(256, 256);
331 for (
unsigned int currentStep = 0; currentStep < numberOfSteps; ++currentStep)
333 if (sliceNaviController)
335 sliceNaviController->GetSlice()->SetPos(currentStep);
343 vtkRender->GetRenderWindow()->WaitForCompletion();
345 vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New();
346 magnifier->SetInput(vtkRender);
347 magnifier->SetMagnification(3.0);
349 std::stringstream ss;
350 ss << path <<
"_Idx-" << index <<
"_Step-"<<currentStep<<
".png";
351 std::string tmpImageName;
353 auto fileWriter = vtkPNGWriter::New();
354 fileWriter->SetInputConnection(magnifier->GetOutputPort());
355 fileWriter->SetFileName(tmpImageName.c_str());
357 fileWriter->Delete();
361 int main(
int argc,
char* argv[])
383 std::vector<mitk::AbstractGlobalImageFeature::Pointer>
features;
384 features.push_back(volCalculator.GetPointer());
385 features.push_back(voldenCalculator.GetPointer());
386 features.push_back(curvCalculator.GetPointer());
387 features.push_back(firstOrderCalculator.GetPointer());
388 features.push_back(firstOrderNumericCalculator.GetPointer());
389 features.push_back(firstOrderHistoCalculator.GetPointer());
390 features.push_back(ivohCalculator.GetPointer());
391 features.push_back(lociCalculator.GetPointer());
392 features.push_back(coocCalculator.GetPointer());
393 features.push_back(cooc2Calculator.GetPointer());
394 features.push_back(ngldCalculator.GetPointer());
395 features.push_back(rlCalculator.GetPointer());
396 features.push_back(glszCalculator.GetPointer());
397 features.push_back(gldzCalculator.GetPointer());
398 features.push_back(ipCalculator.GetPointer());
399 features.push_back(ngtdCalculator.GetPointer());
407 for (
auto cFeature : features)
409 cFeature->AddArguments(parser);
414 parser.
addArgument(
"direction",
"dir",
mitkCommandLineParser::String,
"Int",
"Allows to specify the direction for Cooc and RL. 0: All directions, 1: Only single direction (Test purpose), 2,3,4... Without dimension 0,1,2... ",
us::Any());
416 parser.
addArgument(
"output-mode",
"omode",
mitkCommandLineParser::Int,
"Int",
"Defines if the results of an image / slice are written in a single row (0 , default) or column (1).");
420 parser.
setTitle(
"Global Image Feature calculator");
421 parser.
setDescription(
"Calculates different global statistics for a given segmentation / image combination");
424 std::map<std::string, us::Any> parsedArgs = parser.
parseArguments(argc, argv);
427 if (parsedArgs.size()==0)
431 if ( parsedArgs.count(
"help") || parsedArgs.count(
"h"))
439 std::string version =
"Version: 1.22";
455 std::cout.imbue(std::locale(std::cout.getloc(),
new punct_facet<char>(param.
decimalPoint)));
469 morphMask = mitk::IOUtil::Load<mitk::Image>(param.
morphPath);
472 log <<
" Check for Dimensions -";
473 if ((image->GetDimension() != mask->GetDimension()))
475 MITK_INFO <<
"Dimension of image does not match. ";
476 MITK_INFO <<
"Correct one image, may affect the result";
477 if (image->GetDimension() == 2)
480 multiFilter2->SetInput(tmpImage);
481 multiFilter2->Update();
482 image = multiFilter2->GetOutput();
484 if (mask->GetDimension() == 2)
487 multiFilter3->SetInput(tmpMask);
488 multiFilter3->Update();
489 mask = multiFilter3->GetOutput();
493 int writeDirection = 0;
494 if (parsedArgs.count(
"output-mode"))
496 writeDirection =
us::any_cast<
int>(parsedArgs[
"output-mode"]);
499 log <<
" Check for Resolution -";
506 if ( !
mitk::Equal(mask->GetGeometry(0)->GetOrigin(), image->GetGeometry(0)->GetOrigin()))
512 MITK_INFO <<
"The origin of the input image and the mask do not match. They are";
513 MITK_INFO <<
"now corrected. Please check to make sure that the images still match";
514 image->GetGeometry(0)->SetOrigin(mask->GetGeometry(0)->GetOrigin());
521 log <<
" Resample if required -";
529 log <<
" Check for Equality -";
530 if ( !
mitk::Equal(mask->GetGeometry(0)->GetSpacing(), image->GetGeometry(0)->GetSpacing()))
536 MITK_INFO <<
"The spacing of the mask was set to match the spacing of the input image.";
537 MITK_INFO <<
"This might cause unintended spacing of the mask image";
538 image->GetGeometry(0)->SetSpacing(mask->GetGeometry(0)->GetSpacing());
541 MITK_INFO <<
"The spacing of the mask and the input images is not equal.";
542 MITK_INFO <<
"Terminating the programm. You may use the '-fi' option";
548 if (parsedArgs.count(
"direction"))
553 MITK_INFO <<
"Start creating Mask without NaN";
560 bool sliceWise =
false;
561 int sliceDirection = 0;
562 unsigned int currentSlice = 0;
563 bool imageToProcess =
true;
565 std::vector<mitk::Image::Pointer> floatVector;
566 std::vector<mitk::Image::Pointer> maskVector;
567 std::vector<mitk::Image::Pointer> maskNoNaNVector;
568 std::vector<mitk::Image::Pointer> morphMaskVector;
570 if ((parsedArgs.count(
"slice-wise")) && image->GetDimension() > 2)
576 ExtractSlicesFromImages(image, mask, maskNoNaN, morphMask, sliceDirection, floatVector, maskVector, maskNoNaNVector, morphMaskVector);
580 log <<
" Configure features -";
581 for (
auto cFeature : features)
586 cFeature->SetUseMinimumIntensity(
true);
591 cFeature->SetUseMaximumIntensity(
true);
598 cFeature->SetParameter(parsedArgs);
599 cFeature->SetDirection(direction);
603 bool addDescription = parsedArgs.count(
"description");
611 std::string description =
"";
614 description = parsedArgs[
"description"].ToString();
633 QApplication qtapplication(argc, argv);
636 std::vector<mitk::AbstractGlobalImageFeature::FeatureListType> allStats;
638 log <<
" Begin Processing -";
639 while (imageToProcess)
643 cImage = floatVector[currentSlice];
644 cMask = maskVector[currentSlice];
645 cMaskNoNaN = maskNoNaNVector[currentSlice];
646 cMorphMask = morphMaskVector[currentSlice];
647 imageToProcess = (floatVector.size()-1 > (currentSlice)) ? true : false ;
651 imageToProcess =
false;
669 for (
auto cFeature : features)
671 log <<
" Calculating " << cFeature->GetFeatureClassName() <<
" -";
672 cFeature->SetMorphMask(cMorphMask);
673 cFeature->CalculateFeaturesUsingParameters(cImage, cMask, cMaskNoNaN, stats);
676 for (std::size_t i = 0; i < stats.size(); ++i)
678 std::cout << stats[i].first <<
" - " << stats[i].second << std::endl;
691 allStats.push_back(stats);
695 log <<
" Process Slicewise -";
699 for (std::size_t i = 0; i < allStats[0].size(); ++i)
701 auto cElement1 = allStats[0][i];
702 cElement1.first =
"SliceWise Mean " + cElement1.first;
703 cElement1.second = 0.0;
704 auto cElement2 = allStats[0][i];
705 cElement2.first =
"SliceWise Var. " + cElement2.first;
706 cElement2.second = 0.0;
707 statMean.push_back(cElement1);
708 statStd.push_back(cElement2);
711 for (
auto cStat : allStats)
713 for (std::size_t i = 0; i < cStat.size(); ++i)
715 statMean[i].second += cStat[i].second / (1.0*allStats.size());
719 for (
auto cStat : allStats)
721 for (std::size_t i = 0; i < cStat.size(); ++i)
723 statStd[i].second += (cStat[i].second - statMean[i].second)*(cStat[i].second - statMean[i].second) / (1.0*allStats.size());
727 for (std::size_t i = 0; i < statMean.size(); ++i)
729 std::cout << statMean[i].first <<
" - " << statMean[i].second << std::endl;
730 std::cout << statStd[i].first <<
" - " << statStd[i].second << std::endl;
739 writer.
AddResult(description, currentSlice, statMean, param.
useHeader, addDescription);
747 writer.
AddResult(description, currentSlice, statStd, param.
useHeader, addDescription);
752 log <<
"Finished calculation" << std::endl;
virtual bool InitializeViews(const BaseGeometry *geometry, RequestType type=REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace=false)
bool defineGlobalMinimumIntensity
void AddColumn(std::string value)
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
void ResampleImage(itk::Image< TPixel, VImageDimension > *itkImage, float resolution, mitk::Image::Pointer &newImage)
vtkRenderer * GetVtkRenderer() const
itk::Image< unsigned char, 3 > ImageType
bool defineGlobalMaximumIntensity
void SetDataStorage(mitk::DataStorage *storage) override
set the datastorage that will be used for rendering
Organizes the rendering process.
void setContributor(std::string contributor)
std::string analysisMaskPath
bool resampleToFixIsotropic
MITKQTWIDGETS_EXPORT void QmitkRegisterClasses()
ValueType * any_cast(Any *operand)
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
void AddResult(std::string desc, int slice, mitk::AbstractGlobalImageFeature::FeatureListType stats, bool, bool withDescription)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
double resampleResolution
static void CreateNoNaNMask(itk::Image< TPixel, VImageDimension > *itkValue, mitk::Image::Pointer mask, mitk::Image::Pointer &newMask)
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
std::vector< std::pair< std::string, double > > FeatureListType
void AddSubjectInformation(std::string value)
void AddParameter(mitkCommandLineParser &parser)
static RenderingManager * GetInstance()
void AddHeader(std::string, int slice, mitk::AbstractGlobalImageFeature::FeatureListType stats, bool withHeader, bool withDescription)
std::string anaylsisImagePath
MITK implementation of the QVTKWidget.
itk::Image< unsigned short, 3 > MaskImageType
virtual mitk::VtkPropRenderer * GetRenderer()
static void ResampleMask(itk::Image< TPixel, VImageDimension > *itkMoving, mitk::Image::Pointer ref, mitk::Image::Pointer &newMask)
void setCategory(std::string category)
mitk::Image::Pointer image
double globalMinimumIntensity
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
std::vector< double > MITKCLUTILITIES_EXPORT splitDouble(std::string str, char delimiter)
virtual void PrepareRender()
This methods contains all method neceassary before a VTK Render() call.
void ParseParameter(std::map< std::string, us::Any > parsedArgs)
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
bool defineGlobalNumberOfBins
static void ExtractSlicesFromImages(mitk::Image::Pointer image, mitk::Image::Pointer mask, mitk::Image::Pointer maskNoNaN, mitk::Image::Pointer morphMask, int direction, std::vector< mitk::Image::Pointer > &imageVector, std::vector< mitk::Image::Pointer > &maskVector, std::vector< mitk::Image::Pointer > &maskNoNaNVector, std::vector< mitk::Image::Pointer > &morphMaskVector)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
double globalMaximumIntensity
static void Save(const mitk::BaseData *data, const std::string &path, bool setPathProperty=false)
Save a mitk::BaseData instance.
void SetDecimalPoint(char decimal)
mitk::Image::Pointer mask
virtual mitk::SliceNavigationController * GetSliceNavigationController()
vtkRenderWindow * GetVtkRenderWindow() override
#define AccessByItk_2(mitkImage, itkImageTypeFunction, arg1, arg2)
std::string pngScreenshotsPath
void setTitle(std::string title)
void setDescription(std::string description)
itk::Image< double, 3 > FloatImageType
static void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index)
int main(int argc, char *argv[])