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://www.centreleonberard.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 typedef itk::BoundingBox<unsigned long, Dim> BBType;
158 typename BBType::Pointer bbInput1 = BBType::New();
159 ComputeBBFromImageRegion<Input1ImageType>(input1, input1->GetLargestPossibleRegion(), bbInput1);
160 typename BBType::Pointer bbInput2 = BBType::New();
161 ComputeBBFromImageRegion<Input2ImageType>(input2, input2->GetLargestPossibleRegion(), bbInput2);
162 typename BBType::Pointer bbOutput = BBType::New();
163 ComputeBBFromImageRegion<OutputImageType>(outputImage, outputImage->GetLargestPossibleRegion(), bbOutput);
165 typename BBType::Pointer bb = BBType::New();
166 ComputeBBIntersection<Dim>(bb, bbInput1, bbInput2);
167 ComputeBBIntersection<Dim>(bb, bb, bbOutput);
169 ComputeRegionFromBB<Input1ImageType>(input1, bb, input1Region);
170 ComputeRegionFromBB<Input2ImageType>(input2, bb, input2Region);
171 ComputeRegionFromBB<OutputImageType>(outputImage, bb, outputRegion);
173 //--------------------------------------------------------------------
176 //--------------------------------------------------------------------
177 template <class TInputImage1, class TInputImage2, class TOutputImage>
179 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
180 GenerateInputRequestedRegion() {
182 itk::InPlaceImageFilter<TInputImage1, TOutputImage>::GenerateInputRequestedRegion();
183 // Get input pointers and set requested region to common region
184 Input1ImagePointer input1 = dynamic_cast<TInputImage1*>(itk::ProcessObject::GetInput(0));
185 Input2ImagePointer input2 = dynamic_cast<TInputImage2*>(itk::ProcessObject::GetInput(1));
186 input1->SetRequestedRegion(input1Region);
187 input2->SetRequestedRegion(input2Region);
189 //--------------------------------------------------------------------
192 //--------------------------------------------------------------------
193 template <class TInputImage1, class TInputImage2, class TOutputImage>
195 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>::
197 // Get input pointers
198 Input1ImageConstPointer input1 = dynamic_cast<const TInputImage1*>(itk::ProcessObject::GetInput(0));
199 Input2ImageConstPointer input2 = dynamic_cast<const TInputImage2*>(itk::ProcessObject::GetInput(1));
201 // Get output pointer
202 OutputImagePointer output = this->GetOutput(0);
204 // Get Region iterators
205 itk::ImageRegionConstIterator<Input1ImageType> it1(input1, input1Region);
206 itk::ImageRegionConstIterator<Input2ImageType> it2(input2, input2Region);
207 itk::ImageRegionIterator<OutputImageType> ot (output, outputRegion);
212 switch (m_OperationType) {
213 case AndNot: LoopAndNot(it1, it2, ot); break;
214 case And: LoopAnd(it1, it2, ot); break;
215 case Or: LoopOr(it1, it2, ot); break;
218 //--------------------------------------------------------------------
221 //--------------------------------------------------------------------
222 #define LOOP_BEGIN(FUNCTION_NAME) \
223 template <class TInputImage1, class TInputImage2, class TOutputImage> \
224 template <class Iter1, class Iter2> \
226 BooleanOperatorLabelImageFilter<TInputImage1, TInputImage2, TOutputImage>:: \
227 FUNCTION_NAME(Iter1 it1, Iter1 it2, Iter2 ot) { \
228 while (!ot.IsAtEnd()) {
230 #define LOOP_END ++it1; ++it2; ++ot; }}
231 //--------------------------------------------------------------------
234 //--------------------------------------------------------------------
235 LOOP_BEGIN(LoopAndNot)
236 if ((it1.Get() != mBackgroundValue1) && (it2.Get() == mBackgroundValue2))
237 { ot.Set(mForegroundValue); }
238 else { ot.Set(mBackgroundValue); }
240 //--------------------------------------------------------------------
243 //--------------------------------------------------------------------
245 if ((it1.Get() != mBackgroundValue1) && (it2.Get() != mBackgroundValue2))
246 { ot.Set(mForegroundValue); }
247 else { ot.Set(mBackgroundValue); }
249 //--------------------------------------------------------------------
252 //--------------------------------------------------------------------
254 if ((it1.Get() != mBackgroundValue1) || (it2.Get() != mBackgroundValue2))
255 { ot.Set(mForegroundValue); }
256 else { ot.Set(mBackgroundValue); }
258 //--------------------------------------------------------------------
263 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX