21 #ifndef otbDifferenceImageFilter_hxx
22 #define otbDifferenceImageFilter_hxx
26 #include "itkConstNeighborhoodIterator.h"
27 #include "itkImageRegionIterator.h"
28 #include "itkNeighborhoodAlgorithm.h"
29 #include "itkProgressReporter.h"
30 #include "itkDefaultConvertPixelTraits.h"
36 template <
class TInputImage,
class TOutputImage>
39 this->DynamicMultiThreadingOff();
41 this->SetNumberOfRequiredInputs(2);
44 m_DifferenceThreshold = itk::NumericTraits<ScalarRealType>::Zero;
47 m_ToleranceRadius = 0;
52 m_MeanDifference = itk::NumericTraits<RealType>::ZeroValue(m_MeanDifference);
53 m_TotalDifference = itk::NumericTraits<AccumulateType>::ZeroValue(m_TotalDifference);
54 m_NumberOfPixelsWithDifferences = 0;
59 template <
class TInputImage,
class TOutputImage>
62 this->Superclass::PrintSelf(os, indent);
63 os << indent <<
"ToleranceRadius: " << m_ToleranceRadius <<
"\n";
64 os << indent <<
"DifferenceThreshold: " << m_DifferenceThreshold <<
"\n";
65 os << indent <<
"MeanDifference: " << m_MeanDifference <<
"\n";
66 os << indent <<
"TotalDifference: " << m_TotalDifference <<
"\n";
67 os << indent <<
"NumberOfPixelsWithDifferences: " << m_NumberOfPixelsWithDifferences <<
"\n";
71 template <
class TInputImage,
class TOutputImage>
75 this->SetInput(0, validImage);
79 template <
class TInputImage,
class TOutputImage>
83 this->SetInput(1, testImage);
86 template <
class TInputImage,
class TOutputImage>
89 Superclass::GenerateOutputInformation();
90 if (this->GetInput(0)->GetNumberOfComponentsPerPixel() != this->GetInput(1)->GetNumberOfComponentsPerPixel())
92 itkExceptionMacro(<<
"Image 1 has " << this->GetInput(0)->GetNumberOfComponentsPerPixel() <<
" bands, whereas image 2 has "
93 << this->GetInput(1)->GetNumberOfComponentsPerPixel());
95 this->GetOutput()->SetNumberOfComponentsPerPixel(this->GetInput(0)->GetNumberOfComponentsPerPixel());
98 template <
class TInputImage,
class TOutputImage>
101 this->UpdateOutputInformation();
103 int numberOfThreads = this->GetNumberOfWorkUnits();
105 itk::NumericTraits<RealType>::SetLength(m_MeanDifference, this->GetInput(0)->GetNumberOfComponentsPerPixel());
106 itk::NumericTraits<AccumulateType>::SetLength(m_TotalDifference, this->GetInput(0)->GetNumberOfComponentsPerPixel());
109 m_MeanDifference = itk::NumericTraits<RealType>::ZeroValue(m_MeanDifference);
110 m_TotalDifference = itk::NumericTraits<AccumulateType>::ZeroValue(m_TotalDifference);
111 m_NumberOfPixelsWithDifferences = 0;
114 m_ThreadDifferenceSum.reserve(numberOfThreads);
115 m_ThreadNumberOfPixels.SetSize(numberOfThreads);
118 for (
int i = 0; i < numberOfThreads; ++i)
120 m_ThreadDifferenceSum.push_back(m_TotalDifference);
122 m_ThreadNumberOfPixels.Fill(0);
126 template <
class TInputImage,
class TOutputImage>
129 typedef itk::ConstNeighborhoodIterator<InputImageType> SmartIterator;
130 typedef itk::ImageRegionConstIterator<InputImageType> InputIterator;
131 typedef itk::ImageRegionIterator<OutputImageType> OutputIterator;
132 typedef itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> FacesCalculator;
133 typedef typename FacesCalculator::RadiusType RadiusType;
134 typedef typename FacesCalculator::FaceListType FaceListType;
135 typedef typename FaceListType::iterator FaceListIterator;
136 typedef typename InputImageType::PixelType InputPixelType;
139 itk::ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
148 radius.Fill(std::max(0, m_ToleranceRadius));
151 FacesCalculator boundaryCalculator;
152 FaceListType faceList = boundaryCalculator(testImage, threadRegion, radius);
155 itk::ProgressReporter progress(
this, threadId, threadRegion.GetNumberOfPixels());
158 itk::NumericTraits<AccumulateType>::SetLength(threadDifferenceSum, this->GetInput(0)->GetNumberOfComponentsPerPixel());
159 unsigned long threadNumberOfPixels = 0;
162 for (FaceListIterator face = faceList.begin(); face != faceList.end(); ++face)
164 SmartIterator test(radius, testImage, *face);
165 InputIterator valid(validImage, *face);
166 OutputIterator out(outputPtr, *face);
167 test.OverrideBoundaryCondition(&nbc);
172 InputPixelType t = valid.Get();
174 const auto pixel_size = itk::NumericTraits<InputPixelType>::GetLength(t);
175 const auto out_max = itk::NumericTraits<OutputPixelType>::max(t);
176 const auto zero = itk::NumericTraits<OutputPixelType>::ZeroValue(t);
180 for (valid.GoToBegin(), test.GoToBegin(), out.GoToBegin(); !valid.IsAtEnd(); ++valid, ++test, ++out)
187 minimumDifference = out_max;
188 unsigned int neighborhoodSize = test.Size();
189 for (
unsigned int i = 0; i < neighborhoodSize; ++i)
192 for (
unsigned int j = 0; j < pixel_size; ++j)
199 itk::DefaultConvertPixelTraits<InputPixelType>::GetNthComponent(j, test.GetPixel(i)));
204 itk::DefaultConvertPixelTraits<OutputPixelType>::SetNthComponent(j, minimumDifference, d);
217 for (
unsigned int j = 0; j < pixel_size; ++j)
220 tMax = std::max(std::abs(tc), tMax);
225 bool isDifferent =
false;
227 for (
unsigned int j = 0; j < pixel_size; ++j)
230 if (m > m_DifferenceThreshold * tMax)
241 out.Set(minimumDifference);
244 threadDifferenceSum += minimumDifference;
245 threadNumberOfPixels++;
254 progress.CompletedPixel();
259 m_ThreadDifferenceSum[threadId] += threadDifferenceSum;
260 m_ThreadNumberOfPixels[threadId] += threadNumberOfPixels;
263 template <
class TInputImage,
class TOutputImage>
267 int numberOfThreads = this->GetNumberOfWorkUnits();
268 for (
int i = 0; i < numberOfThreads; ++i)
270 m_TotalDifference += m_ThreadDifferenceSum[i];
271 m_NumberOfPixelsWithDifferences += m_ThreadNumberOfPixels[i];
279 unsigned int numberOfPixels = region.GetNumberOfPixels();
282 m_MeanDifference = m_TotalDifference / numberOfPixels;
void PrintSelf(std::ostream &os, itk::Indent indent) const override
void Synthetize(void) override
void Reset(void) override
void ThreadedGenerateData(const OutputImageRegionType &threadRegion, itk::ThreadIdType threadId) override
OutputImageType::PixelType OutputPixelType
itk::NumericTraits< OutputPixelType >::ScalarRealType ScalarRealType
void GenerateOutputInformation() override
OutputImageType::RegionType OutputImageRegionType
itk::NumericTraits< RealType >::AccumulateType AccumulateType
virtual void SetValidInput(const InputImageType *validImage)
virtual void SetTestInput(const InputImageType *testImage)
TInputImage InputImageType
TOutputImage OutputImageType
unsigned int GetNumberOfComponents(PixelType const &pix)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.