1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
19 #ifndef CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
20 #define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
22 #include "clitkCommon.h"
23 #include "clitkBooleanOperatorLabelImageFilter.h"
24 #include "clitkSegmentationUtils.h"
28 //--------------------------------------------------------------------
29 template <class TInputImage1, class TInputImage2, class TOutputImage>
30 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
31 BooleanOperatorLabelImageFilter():itk::InPlaceImageFilter<TInputImage1, TOutputImage>() {
32 this->SetNumberOfRequiredInputs( 2 );
34 mBackgroundValue1 = 0;
35 mBackgroundValue2 = 0;
38 m_OperationType = AndNot;
40 //--------------------------------------------------------------------
43 //--------------------------------------------------------------------
44 template <class TInputImage1, class TInputImage2, class TOutputImage>
46 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
47 SetInput1(const TInputImage1 * image1) {
48 // Process object is not const-correct so the const casting is required.
49 this->SetNthInput(0, const_cast<TInputImage1 *>( image1 ));
51 //--------------------------------------------------------------------
54 //--------------------------------------------------------------------
55 template <class TInputImage1, class TInputImage2, class TOutputImage>
57 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
58 SetBackgroundValue1(Input1ImagePixelType p) {
59 mBackgroundValue1 = p;
61 //--------------------------------------------------------------------
64 //--------------------------------------------------------------------
65 template <class TInputImage1, class TInputImage2, class TOutputImage>
67 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
68 SetBackgroundValue2(Input2ImagePixelType p) {
69 mBackgroundValue2 = p;
71 //--------------------------------------------------------------------
74 //--------------------------------------------------------------------
75 template <class TInputImage1, class TInputImage2, class TOutputImage>
77 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
78 SetBackgroundValue(OutputImagePixelType p) {
81 //--------------------------------------------------------------------
84 //--------------------------------------------------------------------
85 template <class TInputImage1, class TInputImage2, class TOutputImage>
87 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
88 SetForegroundValue(OutputImagePixelType p) {
91 //--------------------------------------------------------------------
94 //--------------------------------------------------------------------
95 template <class TInputImage1, class TInputImage2, class TOutputImage>
97 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
98 SetInput2(const TInputImage2 * image2) {
99 // Process object is not const-correct so the const casting is required.
100 this->SetNthInput(1, const_cast<TInputImage1 *>( image2 ));
102 //--------------------------------------------------------------------
105 //--------------------------------------------------------------------
106 template <class TInputImage1, class TInputImage2, class TOutputImage>
108 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
109 GenerateOutputInformation() {
111 // Get input pointers
112 Input1ImagePointer input1 = dynamic_cast<TInputImage1*>(itk::ProcessObject::GetInput(0));
113 Input2ImagePointer input2 = dynamic_cast<TInputImage2*>(itk::ProcessObject::GetInput(1));
116 static const unsigned int Dim = Input1ImageType::ImageDimension;
117 for(unsigned int i=0; i<Dim; i++) {
118 if (input1->GetSpacing()[i] != input2->GetSpacing()[i]) {
119 clitkExceptionMacro("Input 1&2 must have the same spacing. " << std::endl
120 << "\t input1 = " << input1->GetSpacing() << std::endl
121 << "\t input2 = " << input2->GetSpacing() << std::endl);
123 // if (input1->GetLargestPossibleRegion().GetSize()[i] != input2->GetLargestPossibleRegion().GetSize()[i]) {
124 // itkExceptionMacro(<< "Input 1&2 must have the same size. " << std::endl
125 // << "\t input1 = " << input1->GetLargestPossibleRegion().GetSize() << std::endl
126 // << "\t input2 = " << input2->GetLargestPossibleRegion().GetSize() << std::endl);
130 // Perform default implementation
131 Superclass::GenerateOutputInformation();
133 // Get output pointer
134 OutputImagePointer outputImage = this->GetOutput(0);
136 // If InPlace, do not create output
137 // DD(this->GetInPlace());
138 if (this->GetInPlace() && this->CanRunInPlace()) {
139 OutputImagePointer inputAsOutput
140 = dynamic_cast<TOutputImage *>(const_cast<TInputImage1 *>(this->GetInput()));
141 inputAsOutput->SetRequestedRegion(outputImage->GetLargestPossibleRegion());
142 inputAsOutput->SetBufferedRegion(outputImage->GetLargestPossibleRegion());
143 // inputAsOutput->SetRegions(outputImage->GetLargestPossibleRegion());
144 this->GraftOutput( inputAsOutput );
147 outputImage->SetRequestedRegion(outputImage->GetLargestPossibleRegion());
148 outputImage->SetBufferedRegion(outputImage->GetLargestPossibleRegion());
149 outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
150 outputImage->Allocate();
151 OutputImagePointer inputAsOutput
152 = dynamic_cast<TOutputImage *>(const_cast<TInputImage1 *>(this->GetInput()));
153 CopyValues<OutputImageType>(inputAsOutput, outputImage);
156 // Compute intersection bounding box (in physical coordinate) and regions (in pixel coordinate)
157 // DD(input1->GetLargestPossibleRegion());
158 // DD(input2->GetLargestPossibleRegion());
159 // DD(outputImage->GetLargestPossibleRegion());
160 typedef itk::BoundingBox<unsigned long, Dim> BBType;
161 typename BBType::Pointer bbInput1 = BBType::New();
162 ComputeBBFromImageRegion<Input1ImageType>(input1, input1->GetLargestPossibleRegion(), bbInput1);
163 typename BBType::Pointer bbInput2 = BBType::New();
164 ComputeBBFromImageRegion<Input2ImageType>(input2, input2->GetLargestPossibleRegion(), bbInput2);
165 typename BBType::Pointer bbOutput = BBType::New();
166 ComputeBBFromImageRegion<OutputImageType>(outputImage, outputImage->GetLargestPossibleRegion(), bbOutput);
172 typename BBType::Pointer bb = BBType::New();
173 ComputeBBIntersection<Dim>(bb, bbInput1, bbInput2);
175 ComputeBBIntersection<Dim>(bb, bb, bbOutput);
178 ComputeRegionFromBB<Input1ImageType>(input1, bb, input1Region);
179 ComputeRegionFromBB<Input2ImageType>(input2, bb, input2Region);
180 ComputeRegionFromBB<OutputImageType>(outputImage, bb, outputRegion);
183 //--------------------------------------------------------------------
186 //--------------------------------------------------------------------
187 template <class TInputImage1, class TInputImage2, class TOutputImage>
189 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
190 GenerateInputRequestedRegion() {
192 itk::InPlaceImageFilter<TInputImage1, TOutputImage>::GenerateInputRequestedRegion();
193 // Get input pointers and set requested region to common region
194 Input1ImagePointer input1 = dynamic_cast<TInputImage1*>(itk::ProcessObject::GetInput(0));
195 Input2ImagePointer input2 = dynamic_cast<TInputImage2*>(itk::ProcessObject::GetInput(1));
196 input1->SetRequestedRegion(input1Region);
197 input2->SetRequestedRegion(input2Region);
199 //--------------------------------------------------------------------
202 //--------------------------------------------------------------------
203 template <class TInputImage1, class TInputImage2, class TOutputImage>
205 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
207 // Get input pointers
208 Input1ImageConstPointer input1 = dynamic_cast<const TInputImage1*>(itk::ProcessObject::GetInput(0));
209 Input2ImageConstPointer input2 = dynamic_cast<const TInputImage2*>(itk::ProcessObject::GetInput(1));
211 // Get output pointer
212 OutputImagePointer output = this->GetOutput(0);
214 // Get Region iterators
218 itk::ImageRegionConstIterator<Input1ImageType> it1(input1, input1Region);
219 itk::ImageRegionConstIterator<Input2ImageType> it2(input2, input2Region);
220 itk::ImageRegionIterator<OutputImageType> ot (output, outputRegion);
225 switch (m_OperationType) {
226 case AndNot: LoopAndNot(it1, it2, ot); break;
227 case And: LoopAnd(it1, it2, ot); break;
230 //--------------------------------------------------------------------
233 //--------------------------------------------------------------------
234 #define LOOP_BEGIN(FUNCTION_NAME) \
235 template <class TInputImage1, class TInputImage2, class TOutputImage> \
236 template <class Iter1, class Iter2> \
238 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>:: \
239 FUNCTION_NAME(Iter1 it1, Iter1 it2, Iter2 ot) { \
240 while (!ot.IsAtEnd()) {
242 #define LOOP_END ++it1; ++it2; ++ot; }}
243 //--------------------------------------------------------------------
246 //--------------------------------------------------------------------
247 LOOP_BEGIN(LoopAndNot)
248 if ((it1.Get() != mBackgroundValue1) && (it2.Get() == mBackgroundValue2)) { ot.Set(mForegroundValue); }
249 else { ot.Set(mBackgroundValue); }
251 //--------------------------------------------------------------------
254 //--------------------------------------------------------------------
256 if ((it1.Get() != mBackgroundValue1) && (it2.Get() != mBackgroundValue2)) { ot.Set(mForegroundValue); }
257 else { ot.Set(mBackgroundValue); }
259 //--------------------------------------------------------------------
264 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX