X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=tools%2FclitkImageStatisticsGenericFilter.txx;h=82a11ab5355a86134a3a6cc666ff9136b04dc423;hb=342abd5c807dab47a30d8369aca8f7e5c9242b2b;hp=0f52d866973a739af9dbf0cce69da6044168f89d;hpb=765020625fbc092d283e221e36c83e60a1844cb7;p=clitk.git diff --git a/tools/clitkImageStatisticsGenericFilter.txx b/tools/clitkImageStatisticsGenericFilter.txx old mode 100755 new mode 100644 index 0f52d86..82a11ab --- a/tools/clitkImageStatisticsGenericFilter.txx +++ b/tools/clitkImageStatisticsGenericFilter.txx @@ -1,7 +1,7 @@ /*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv - Authors belong to: + Authors belong to: - University of LYON http://www.universite-lyon.fr/ - Léon Bérard cancer center http://www.centreleonberard.fr - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr @@ -18,15 +18,13 @@ #ifndef clitkImageStatisticsGenericFilter_txx #define clitkImageStatisticsGenericFilter_txx -/* ================================================= - * @file clitkImageStatisticsGenericFilter.txx - * @author - * @date - * - * @brief - * - ===================================================*/ +#include "itkNthElementImageAdaptor.h" +#include "itkJoinSeriesImageFilter.h" +#include "itkImageRegionConstIterator.h" +#include "clitkImageStatisticsGenericFilter.h" +#include "clitkCropLikeImageFilter.h" +#include "clitkResampleImageWithOptionsFilter.h" namespace clitk { @@ -34,33 +32,33 @@ namespace clitk //------------------------------------------------------------------- // Update with the number of dimensions //------------------------------------------------------------------- - template - void + template + void ImageStatisticsGenericFilter::UpdateWithDim(std::string PixelType) { - if (m_Verbose) std::cout << "Image was detected to be "<(); + UpdateWithDimAndPixelType(); } - // else if(PixelType == "unsigned_short"){ - // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl; - // UpdateWithDimAndPixelType(); - // } - - else if (PixelType == "unsigned_char"){ + else if(PixelType == "unsigned_short"){ + if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl; + UpdateWithDimAndPixelType(); + } + + else if (PixelType == "unsigned_char"){ if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl; - UpdateWithDimAndPixelType(); + UpdateWithDimAndPixelType(); + } + + else if(PixelType == "double"){ + if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and double..." << std::endl; + UpdateWithDimAndPixelType(); } - - // else if (PixelType == "char"){ - // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl; - // UpdateWithDimAndPixelType(); - // } else { if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and float..." << std::endl; - UpdateWithDimAndPixelType(); + UpdateWithDimAndPixelType(); } } @@ -68,16 +66,16 @@ namespace clitk //------------------------------------------------------------------- // Update with the number of dimensions and the pixeltype //------------------------------------------------------------------- - template - void + template + void ImageStatisticsGenericFilter::UpdateWithDimAndPixelType() { // ImageTypes - typedef itk::Image InputImageType; - typedef itk::Image LabelImageType; - typedef itk::Image OutputImageType; - + typedef unsigned char LabelPixelType; + typedef itk::Image, Dimension> InputImageType; + typedef itk::Image LabelImageType; + // Read the input typedef itk::ImageFileReader InputReaderType; typename InputReaderType::Pointer reader = InputReaderType::New(); @@ -85,32 +83,109 @@ namespace clitk reader->Update(); typename InputImageType::Pointer input= reader->GetOutput(); + typedef itk::NthElementImageAdaptor InputImageAdaptorType; + typedef itk::Image OutputImageType; + + typename InputImageAdaptorType::Pointer input_adaptor = InputImageAdaptorType::New(); + input_adaptor->SetImage(input); + // Filter - typedef itk::LabelStatisticsImageFilter StatisticsImageFilterType; + typedef itk::LabelStatisticsImageFilter StatisticsImageFilterType; typename StatisticsImageFilterType::Pointer statisticsFilter=StatisticsImageFilterType::New(); - statisticsFilter->SetInput(input); + statisticsFilter->SetInput(input_adaptor); // Label image typename LabelImageType::Pointer labelImage; - if (m_ArgsInfo.mask_given) - { - typedef itk::ImageFileReader LabelImageReaderType; - typename LabelImageReaderType::Pointer labelImageReader=LabelImageReaderType::New(); - labelImageReader->SetFileName(m_ArgsInfo.mask_arg); - labelImageReader->Update(); - labelImage= labelImageReader->GetOutput(); + if (m_ArgsInfo.mask_given) { + int maskDimension, maskComponents; + std::string maskPixelType; + ReadImageDimensionAndPixelType(m_ArgsInfo.mask_arg, maskDimension, maskPixelType, maskComponents); + + if (maskDimension == Dimension - 1) { + // Due to a limitation of filter itk::LabelStatisticsImageFilter, InputImageType and LabelImageType + // must have the same image dimension. However, we want to support label images with Dl = Di - 1, + // so we need to replicate the label image as many times as the size along dimension Di. + if (m_Verbose) + std::cout << "Replicating label image to match input image's dimension... " << std::endl; + + typedef itk::Image ReducedLabelImageType; + typedef itk::ImageFileReader LabelImageReaderType; + typedef itk::JoinSeriesImageFilter JoinImageFilterType; + + typename LabelImageReaderType::Pointer labelImageReader=LabelImageReaderType::New(); + labelImageReader->SetFileName(m_ArgsInfo.mask_arg); + labelImageReader->Update(); + + typename JoinImageFilterType::Pointer joinFilter = JoinImageFilterType::New(); + typename InputImageType::SizeType size = input->GetLargestPossibleRegion().GetSize(); + for (unsigned int i = 0; i < size[Dimension - 1]; i++) + joinFilter->PushBackInput(labelImageReader->GetOutput()); + + joinFilter->Update(); + labelImage = joinFilter->GetOutput(); } - else - { - labelImage=LabelImageType::New(); - labelImage->SetRegions(input->GetLargestPossibleRegion()); - labelImage->SetOrigin(input->GetOrigin()); - labelImage->SetSpacing(input->GetSpacing()); - labelImage->Allocate(); - labelImage->FillBuffer(m_ArgsInfo.label_arg[0]); + else { + typedef itk::ImageFileReader LabelImageReaderType; + typename LabelImageReaderType::Pointer labelImageReader=LabelImageReaderType::New(); + labelImageReader->SetFileName(m_ArgsInfo.mask_arg); + labelImageReader->Update(); + labelImage= labelImageReader->GetOutput(); + + // Check mask sampling/size + if (!HaveSameSizeAndSpacing(labelImage, input)) { + if (m_ArgsInfo.allow_resize_flag) { + if (m_ArgsInfo.verbose_flag) { + std::cout << "Resize mask image like input" << std::endl; + } + typedef clitk::ResampleImageWithOptionsFilter ResamplerType; + typename ResamplerType::Pointer resampler = ResamplerType::New(); + resampler->SetInput(labelImage); + resampler->SetOutputSpacing(input->GetSpacing()); + resampler->SetOutputOrigin(labelImage->GetOrigin()); + resampler->SetGaussianFilteringEnabled(false); + resampler->Update(); + labelImage = resampler->GetOutput(); + //writeImage(labelImage, "test1.mha"); + + typedef clitk::CropLikeImageFilter FilterType; + typename FilterType::Pointer crop = FilterType::New(); + crop->SetInput(labelImage); + crop->SetCropLikeImage(input); + crop->Update(); + labelImage = crop->GetOutput(); + //writeImage(labelImage, "test2.mha"); + + } + else { + std::cerr << "Mask image has a different size/spacing than input. Abort. (Use option to resize)" << std::endl; + exit(-1); + } + } + } + + } + else { + labelImage=LabelImageType::New(); + labelImage->SetDirection(input->GetDirection()); + labelImage->SetRegions(input->GetLargestPossibleRegion()); + labelImage->SetOrigin(input->GetOrigin()); + labelImage->SetSpacing(input->GetSpacing()); + labelImage->SetDirection(input->GetDirection()); + labelImage->Allocate(); + labelImage->FillBuffer(m_ArgsInfo.label_arg[0]); + } statisticsFilter->SetLabelInput(labelImage); + // Check/compute spacing + const typename LabelImageType::SpacingType& spacing = input->GetSpacing(); + double spacing_cc = (spacing[0]*spacing[1]*spacing[2])/1000; + // std::cout<<"Spacing x : " << spacing[0]<SetUseHistograms(true); - statisticsFilter->SetHistogramParameters(m_ArgsInfo.bins_arg, m_ArgsInfo.lower_arg, m_ArgsInfo.upper_arg); - } - statisticsFilter->Update(); - - - // Output - if (m_Verbose) std::cout<<"N° of pixels: "; - std::cout<GetCount(label)<GetMean(label)<GetSigma(label)<GetVariance(label)<GetMinimum(label)<GetMaximum(label)<GetSum(label)<GetBoundingBox(label).size(); i++) - std::cout<GetBoundingBox(label)[i]<<" "; - std::cout<GetMedian(label)<GetHistogram(label); - - // Screen - if (m_Verbose) std::cout<<"Histogram: "<GetBinMin(0,i)<<"\t"<GetMeasurement(i,0)<<"\t"<GetBinMax(0,i)<<"\t"<GetFrequency(i)<GetBinMin(0,i)<<"\t"<GetMeasurement(i,0)<<"\t"<GetBinMax(0,i)<<"\t"<GetFrequency(i)<SelectNthElement(c); + input_adaptor->Update(); + + for (unsigned int k=0; k< numberOfLabels; k++) { + label=m_ArgsInfo.label_arg[k]; + + std::cout<SetUseHistograms(true); + statisticsFilter->SetHistogramParameters(m_ArgsInfo.bins_arg, m_ArgsInfo.lower_arg, m_ArgsInfo.upper_arg); + } + + // DVH + if(m_ArgsInfo.dvhistogram_given) + { + statisticsFilter->SetUseHistograms(true); + statisticsFilter->SetHistogramParameters(m_ArgsInfo.bins_arg, m_ArgsInfo.lower_arg, m_ArgsInfo.upper_arg); + } + + statisticsFilter->Update(); + + //find localization for max and min (the last pixel found) + typename InputImageType::IndexType minIndex, maxIndex; + if (m_Verbose && m_Localize) { + itk::ImageRegionConstIterator imageIterator(input_adaptor,input_adaptor->GetLargestPossibleRegion()); + while(!imageIterator.IsAtEnd()) { + if (imageIterator.Get() == statisticsFilter->GetMinimum(label)) + minIndex = imageIterator.GetIndex(); + if (imageIterator.Get() == statisticsFilter->GetMaximum(label)) + maxIndex = imageIterator.GetIndex(); + ++imageIterator; + } + } + + // Output + if (m_Verbose) std::cout<<"N° of pixels: "; + std::cout<GetCount(label)<GetMean(label)<GetSigma(label)<GetVariance(label)<GetMinimum(label)<GetMaximum(label)<GetSum(label)<GetCount(label)*spacing_cc<GetBoundingBox(label).size(); i++) + std::cout<GetBoundingBox(label)[i]<<" "; + std::cout<GetMedian(label)<GetHistogram(label); + + // Screen + if (m_Verbose) std::cout<<"Histogram: "<GetBinMin(0,i)<<"\t"<GetMeasurement(i,0)<<"\t"<GetBinMax(0,i)<<"\t"<GetFrequency(i)<GetBinMin(0,i)<<"\t"<GetMeasurement(i,0)<<"\t"<GetBinMax(0,i)<<"\t"<GetFrequency(i)<GetHistogram(label); + double totalVolumeCC = ((statisticsFilter->GetCount(label))*spacing_cc); + double totalVolume = statisticsFilter->GetCount(label); + + // Screen + std::cout<<"# Total volume : "; + std::cout<GetMean(label)<<" [Gy]"<GetMinimum(label)<<" [Gy]"<GetMaximum(label)<<" [Gy]"<GetFrequency(j)); + } + double cumulativeVolume = (totalVolume - (popCumulativeVolume + (dvhistogram->GetFrequency(i)))); + double percentCumulativeVolume =(cumulativeVolume*100)/(statisticsFilter->GetCount(label)) ; + double ccCumulativeVolume = (totalVolumeCC -((popCumulativeVolume + (dvhistogram->GetFrequency(i)))*spacing_cc)); + double percentDiffVolume = dvhistogram->GetFrequency(i)*100/(statisticsFilter->GetCount(label)); + std::cout<GetBinMax(0,i)<<"\t "<GetFrequency(i)<<"\t "<GetFrequency(i))*spacing_cc)<<"\t "<<"\t "<GetCount(label)<<" [No. of voxels]"<GetMean(label)<<" [Gy]"<GetMinimum(label)<<" [Gy]"<GetMaximum(label)<<" [Gy]"<GetFrequency(j)); + } + double cumulativeVolume = (totalVolume - (popCumulativeVolume + (dvhistogram->GetFrequency(i)))); + double percentCumulativeVolume =(cumulativeVolume*100)/(statisticsFilter->GetCount(label)); + double ccCumulativeVolume = (totalVolumeCC -((popCumulativeVolume + (dvhistogram->GetFrequency(i)))*spacing_cc)); + double percentDiffVolume = ((dvhistogram->GetFrequency(i))*100)/(statisticsFilter->GetCount(label)); + dvhistogramFile<GetBinMax(0,i)<<"\t "<GetFrequency(i)<<"\t "<GetFrequency(i))*spacing_cc)<<"\t "<