]> Creatis software - clitk.git/blob - tools/clitkImageStatisticsGenericFilter.txx
support for new pixel types
[clitk.git] / tools / clitkImageStatisticsGenericFilter.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef clitkImageStatisticsGenericFilter_txx
19 #define clitkImageStatisticsGenericFilter_txx
20
21 #include "itkNthElementImageAdaptor.h"
22 #include "itkJoinSeriesImageFilter.h"
23
24 /* =================================================
25  * @file   clitkImageStatisticsGenericFilter.txx
26  * @author 
27  * @date   
28  * 
29  * @brief 
30  * 
31  ===================================================*/
32 #include "clitkImageStatisticsGenericFilter.h"
33
34
35 namespace clitk
36 {
37
38   //-------------------------------------------------------------------
39   // Update with the number of dimensions
40   //-------------------------------------------------------------------
41   template<unsigned int Dimension, unsigned int Components>
42   void 
43   ImageStatisticsGenericFilter::UpdateWithDim(std::string PixelType)
44   {
45     if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<" with " << Components << " channel(s)..."<<std::endl;
46
47     if(PixelType == "short"){  
48       if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
49       UpdateWithDimAndPixelType<Dimension, signed short, Components>(); 
50     }
51     else if(PixelType == "unsigned_short"){  
52       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
53       UpdateWithDimAndPixelType<Dimension, unsigned short, Components>(); 
54     }
55     
56     else if (PixelType == "unsigned_char"){ 
57       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
58       UpdateWithDimAndPixelType<Dimension, unsigned char, Components>();
59     }
60     
61 //     else if (PixelType == "unsigned_int"){ 
62 //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_int..." << std::endl;
63 //       UpdateWithDimAndPixelType<Dimension, unsigned int, Components>();
64 //     }
65     //     else if (PixelType == "char"){ 
66     //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
67     //       UpdateWithDimAndPixelType<Dimension, signed char>();
68     //     }
69     else if(PixelType == "double"){  
70       if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and double..." << std::endl;
71       UpdateWithDimAndPixelType<Dimension, double, Components>(); 
72     }
73     else {
74       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
75       UpdateWithDimAndPixelType<Dimension, float, Components>();
76     }
77   }
78
79
80   //-------------------------------------------------------------------
81   // Update with the number of dimensions and the pixeltype
82   //-------------------------------------------------------------------
83   template <unsigned int Dimension, class  PixelType, unsigned int Components> 
84   void 
85   ImageStatisticsGenericFilter::UpdateWithDimAndPixelType()
86   {
87
88     // ImageTypes
89     typedef unsigned char LabelPixelType;
90     typedef itk::Image<itk::Vector<PixelType, Components>, Dimension> InputImageType;
91     typedef itk::Image<LabelPixelType, Dimension> LabelImageType;
92     
93     // Read the input
94     typedef itk::ImageFileReader<InputImageType> InputReaderType;
95     typename InputReaderType::Pointer reader = InputReaderType::New();
96     reader->SetFileName( m_InputFileName);
97     reader->Update();
98     typename InputImageType::Pointer input= reader->GetOutput();
99     
100     typedef itk::NthElementImageAdaptor<InputImageType, PixelType> InputImageAdaptorType;
101     typedef itk::Image<PixelType, Dimension> OutputImageType;
102
103     typename InputImageAdaptorType::Pointer input_adaptor = InputImageAdaptorType::New();
104     input_adaptor->SetImage(input);
105     
106     // Filter
107     typedef itk::LabelStatisticsImageFilter<InputImageAdaptorType, LabelImageType> StatisticsImageFilterType;
108     typename StatisticsImageFilterType::Pointer statisticsFilter=StatisticsImageFilterType::New();
109     statisticsFilter->SetInput(input_adaptor);
110
111     // Label image
112     typename LabelImageType::Pointer labelImage;
113     if (m_ArgsInfo.mask_given) {
114       int maskDimension, maskComponents;
115       std::string maskPixelType;
116       ReadImageDimensionAndPixelType(m_ArgsInfo.mask_arg, maskDimension, maskPixelType, maskComponents);
117       if (maskDimension == Dimension - 1) {
118         // Due to a limitation of filter itk::LabelStatisticsImageFilter, InputImageType and LabelImageType
119         // must have the same image dimension. However, we want to support label images with Dl = Di - 1,
120         // so we need to replicate the label image as many times as the size along dimension Di.
121         if (m_Verbose) 
122           std::cout << "Replicating label image to match input image's dimension... " << std::endl;
123         
124         typedef itk::Image<LabelPixelType, Dimension - 1> ReducedLabelImageType;
125         typedef itk::ImageFileReader<ReducedLabelImageType> LabelImageReaderType;
126         typedef itk::JoinSeriesImageFilter<ReducedLabelImageType, LabelImageType> JoinImageFilterType;
127         
128         typename LabelImageReaderType::Pointer labelImageReader=LabelImageReaderType::New();
129         labelImageReader->SetFileName(m_ArgsInfo.mask_arg);
130         labelImageReader->Update();
131
132         typename JoinImageFilterType::Pointer joinFilter = JoinImageFilterType::New();
133         typename InputImageType::SizeType size = input->GetLargestPossibleRegion().GetSize();
134         for (unsigned int i = 0; i < size[Dimension - 1]; i++)
135           joinFilter->PushBackInput(labelImageReader->GetOutput());
136         
137         joinFilter->Update();
138         labelImage = joinFilter->GetOutput();
139       }
140       else {
141         typedef itk::ImageFileReader<LabelImageType> LabelImageReaderType;
142         typename LabelImageReaderType::Pointer labelImageReader=LabelImageReaderType::New();
143         labelImageReader->SetFileName(m_ArgsInfo.mask_arg);
144         labelImageReader->Update();
145         labelImage= labelImageReader->GetOutput();
146       }
147
148     }
149     else { 
150       labelImage=LabelImageType::New();
151       labelImage->SetRegions(input->GetLargestPossibleRegion());
152       labelImage->SetOrigin(input->GetOrigin());
153       labelImage->SetSpacing(input->GetSpacing());
154       labelImage->Allocate();
155       labelImage->FillBuffer(m_ArgsInfo.label_arg[0]);
156     }
157     statisticsFilter->SetLabelInput(labelImage);
158
159     // For each Label
160     typename LabelImageType::PixelType label;
161     unsigned int numberOfLabels;
162     if (m_ArgsInfo.label_given)
163       numberOfLabels=m_ArgsInfo.label_given;
164     else
165       numberOfLabels=1;
166
167     unsigned int firstComponent = 0, lastComponent = 0;
168     if (m_ArgsInfo.channel_arg == -1) {
169       firstComponent = 0; 
170       lastComponent = Components - 1;
171     }
172     else {
173       firstComponent = m_ArgsInfo.channel_arg;
174       lastComponent = m_ArgsInfo.channel_arg;
175     }
176     
177     for (unsigned int c=firstComponent; c<=lastComponent; c++) {
178       if (m_Verbose) std::cout << std::endl << "Processing channel " << c << std::endl;
179       
180       input_adaptor->SelectNthElement(c);
181       input_adaptor->Update();
182       
183       for (unsigned int k=0; k< numberOfLabels; k++) {
184         label=m_ArgsInfo.label_arg[k];
185
186         std::cout<<std::endl;
187         if (m_Verbose) std::cout<<"-------------"<<std::endl;
188         if (m_Verbose) std::cout<<"| Label: "<<label<<"  |"<<std::endl;
189         if (m_Verbose) std::cout<<"-------------"<<std::endl;
190
191         // Histograms
192         if (m_ArgsInfo.histogram_given) {
193           statisticsFilter->SetUseHistograms(true);
194           statisticsFilter->SetHistogramParameters(m_ArgsInfo.bins_arg, m_ArgsInfo.lower_arg, m_ArgsInfo.upper_arg);
195         }
196         statisticsFilter->Update();
197
198         // Output
199         if (m_Verbose) std::cout<<"N° of pixels: ";
200           std::cout<<statisticsFilter->GetCount(label)<<std::endl;
201
202         if (m_Verbose) std::cout<<"Mean: ";
203           std::cout<<statisticsFilter->GetMean(label)<<std::endl;
204
205         if (m_Verbose) std::cout<<"SD: ";
206           std::cout<<statisticsFilter->GetSigma(label)<<std::endl;
207
208         if (m_Verbose) std::cout<<"Variance: ";
209           std::cout<<statisticsFilter->GetVariance(label)<<std::endl;
210
211         if (m_Verbose) std::cout<<"Min: ";
212           std::cout<<statisticsFilter->GetMinimum(label)<<std::endl;
213
214         if (m_Verbose) std::cout<<"Max: ";
215           std::cout<<statisticsFilter->GetMaximum(label)<<std::endl;
216
217         if (m_Verbose) std::cout<<"Sum: ";
218           std::cout<<statisticsFilter->GetSum(label)<<std::endl;
219
220         if (m_Verbose) std::cout<<"Bounding box: ";
221         
222         for(unsigned int i =0; i <statisticsFilter->GetBoundingBox(label).size(); i++)
223           std::cout<<statisticsFilter->GetBoundingBox(label)[i]<<" ";
224         std::cout<<std::endl;
225
226         // Histogram
227         if (m_ArgsInfo.histogram_given)
228         {
229           if (m_Verbose) std::cout<<"Median: ";
230           std::cout<<statisticsFilter->GetMedian(label)<<std::endl;
231
232           typename StatisticsImageFilterType::HistogramPointer histogram =statisticsFilter->GetHistogram(label);
233
234           // Screen
235           if (m_Verbose) std::cout<<"Histogram: "<<std::endl;
236             std::cout<<"# MinBin\tMidBin\tMaxBin\tFrequency"<<std::endl;
237           for( int i =0; i <m_ArgsInfo.bins_arg; i++)
238             std::cout<<histogram->GetBinMin(0,i)<<"\t"<<histogram->GetMeasurement(i,0)<<"\t"<<histogram->GetBinMax(0,i)<<"\t"<<histogram->GetFrequency(i)<<std::endl;
239
240           // Add to the file
241           std::ofstream histogramFile(m_ArgsInfo.histogram_arg);
242           histogramFile<<"#Histogram: "<<std::endl;
243           histogramFile<<"#MinBin\tMidBin\tMaxBin\tFrequency"<<std::endl;
244           for( int i =0; i <m_ArgsInfo.bins_arg; i++)
245             histogramFile<<histogram->GetBinMin(0,i)<<"\t"<<histogram->GetMeasurement(i,0)<<"\t"<<histogram->GetBinMax(0,i)<<"\t"<<histogram->GetFrequency(i)<<std::endl;
246         }
247       }
248     }
249
250     return;
251
252   }
253   
254   
255 }//end clitk
256
257 #endif //#define clitkImageStatisticsGenericFilter_txx