21 #ifndef otbScalarImageToAdvancedTexturesFilter_hxx
22 #define otbScalarImageToAdvancedTexturesFilter_hxx
25 #include "itkImageRegionIteratorWithIndex.h"
26 #include "itkConstNeighborhoodIterator.h"
27 #include "itkImageRegionIterator.h"
28 #include "itkProgressReporter.h"
29 #include "itkNumericTraits.h"
34 template <
class TInputImage,
class TOutputImage>
38 m_NeighborhoodRadius(),
39 m_NumberOfBinsPerAxis(8),
40 m_InputImageMinimum(0),
41 m_InputImageMaximum(255),
45 this->DynamicMultiThreadingOn();
47 this->SetNumberOfRequiredOutputs(10);
50 this->SetNthOutput(0, OutputImageType::New());
51 this->SetNthOutput(1, OutputImageType::New());
52 this->SetNthOutput(2, OutputImageType::New());
53 this->SetNthOutput(3, OutputImageType::New());
54 this->SetNthOutput(4, OutputImageType::New());
55 this->SetNthOutput(5, OutputImageType::New());
56 this->SetNthOutput(6, OutputImageType::New());
57 this->SetNthOutput(7, OutputImageType::New());
58 this->SetNthOutput(8, OutputImageType::New());
59 this->SetNthOutput(9, OutputImageType::New());
65 template <
class TInputImage,
class TOutputImage>
69 template <
class TInputImage,
class TOutputImage>
73 if (this->GetNumberOfOutputs() < 1)
80 template <
class TInputImage,
class TOutputImage>
84 if (this->GetNumberOfOutputs() < 2)
91 template <
class TInputImage,
class TOutputImage>
95 if (this->GetNumberOfOutputs() < 3)
102 template <
class TInputImage,
class TOutputImage>
106 if (this->GetNumberOfOutputs() < 4)
113 template <
class TInputImage,
class TOutputImage>
117 if (this->GetNumberOfOutputs() < 5)
124 template <
class TInputImage,
class TOutputImage>
128 if (this->GetNumberOfOutputs() < 6)
135 template <
class TInputImage,
class TOutputImage>
139 if (this->GetNumberOfOutputs() < 7)
146 template <
class TInputImage,
class TOutputImage>
150 if (this->GetNumberOfOutputs() < 8)
157 template <
class TInputImage,
class TOutputImage>
161 if (this->GetNumberOfOutputs() < 9)
168 template <
class TInputImage,
class TOutputImage>
172 if (this->GetNumberOfOutputs() < 10)
179 template <
class TInputImage,
class TOutputImage>
183 Superclass::GenerateOutputInformation();
186 InputRegionType inputRegion = this->GetInput()->GetLargestPossibleRegion();
188 outputRegion.SetIndex(0, 0);
189 outputRegion.SetIndex(1, 0);
190 outputRegion.SetSize(0, 1 + (inputRegion.GetSize(0) - 1 - m_SubsampleOffset[0]) / m_SubsampleFactor[0]);
191 outputRegion.SetSize(1, 1 + (inputRegion.GetSize(1) - 1 - m_SubsampleOffset[1]) / m_SubsampleFactor[1]);
193 typename OutputImageType::SpacingType outSpacing = this->GetInput()->GetSignedSpacing();
194 outSpacing[0] *= m_SubsampleFactor[0];
195 outSpacing[1] *= m_SubsampleFactor[1];
197 typename OutputImageType::PointType outOrigin;
198 this->GetInput()->TransformIndexToPhysicalPoint(inputRegion.GetIndex() + m_SubsampleOffset, outOrigin);
200 for (
unsigned int i = 0; i < this->GetNumberOfOutputs(); i++)
203 outputPtr->SetLargestPossibleRegion(outputRegion);
204 outputPtr->SetOrigin(outOrigin);
205 outputPtr->SetSignedSpacing(outSpacing);
209 template <
class TInputImage,
class TOutputImage>
213 Superclass::GenerateInputRequestedRegion();
219 if (!inputPtr || !outputPtr)
230 typename OutputRegionType::IndexType outputIndex = outputRequestedRegion.GetIndex();
231 typename OutputRegionType::SizeType outputSize = outputRequestedRegion.GetSize();
232 typename InputRegionType::IndexType inputIndex;
233 typename InputRegionType::SizeType inputSize;
236 outputIndex[0] = outputIndex[0] * m_SubsampleFactor[0] + m_SubsampleOffset[0] + inputLargest.GetIndex(0);
237 outputIndex[1] = outputIndex[1] * m_SubsampleFactor[1] + m_SubsampleOffset[1] + inputLargest.GetIndex(1);
238 outputSize[0] = 1 + (outputSize[0] - 1) * m_SubsampleFactor[0];
239 outputSize[1] = 1 + (outputSize[1] - 1) * m_SubsampleFactor[1];
242 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
244 inputIndex[dim] = std::min(outputIndex[dim], outputIndex[dim] + m_Offset[dim]);
245 inputSize[dim] = std::max(outputIndex[dim] + outputSize[dim], outputIndex[dim] + outputSize[dim] + m_Offset[dim]) - inputIndex[dim];
250 inputRequestedRegion.SetIndex(inputIndex);
251 inputRequestedRegion.SetSize(inputSize);
254 inputRequestedRegion.PadByRadius(m_Radius);
257 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
259 inputPtr->SetRequestedRegion(inputRequestedRegion);
264 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
265 e.SetLocation(ITK_LOCATION);
266 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
267 e.SetDataObject(inputPtr);
272 template <
class TInputImage,
class TOutputImage>
275 unsigned int minRadius = 0;
276 for (
unsigned int i = 0; i < m_Offset.GetOffsetDimension(); i++)
278 unsigned int distance = std::abs(m_Offset[i]);
279 if (distance > minRadius)
281 minRadius = distance;
284 m_NeighborhoodRadius.Fill(minRadius);
287 template <
class TInputImage,
class TOutputImage>
304 itk::ImageRegionIteratorWithIndex<OutputImageType> varianceIt(variancePtr, outputRegionForThread);
305 itk::ImageRegionIterator<OutputImageType> meanIt(meanPtr, outputRegionForThread);
306 itk::ImageRegionIterator<OutputImageType> dissimilarityIt(dissimilarityPtr, outputRegionForThread);
307 itk::ImageRegionIterator<OutputImageType> sumAverageIt(sumAveragePtr, outputRegionForThread);
308 itk::ImageRegionIterator<OutputImageType> sumVarianceIt(sumVariancePtr, outputRegionForThread);
309 itk::ImageRegionIterator<OutputImageType> sumEntropytIt(sumEntropytPtr, outputRegionForThread);
310 itk::ImageRegionIterator<OutputImageType> differenceEntropyIt(differenceEntropyPtr, outputRegionForThread);
311 itk::ImageRegionIterator<OutputImageType> differenceVarianceIt(differenceVariancePtr, outputRegionForThread);
312 itk::ImageRegionIterator<OutputImageType> ic1It(ic1Ptr, outputRegionForThread);
313 itk::ImageRegionIterator<OutputImageType> ic2It(ic2Ptr, outputRegionForThread);
316 varianceIt.GoToBegin();
318 dissimilarityIt.GoToBegin();
319 sumAverageIt.GoToBegin();
320 sumVarianceIt.GoToBegin();
321 sumEntropytIt.GoToBegin();
322 differenceEntropyIt.GoToBegin();
323 differenceVarianceIt.GoToBegin();
327 const double log2 = std::log(2.0);
328 const unsigned int histSize = m_NumberOfBinsPerAxis;
329 const long unsigned int twiceHistSize = 2 * m_NumberOfBinsPerAxis;
334 while (!varianceIt.IsAtEnd() && !meanIt.IsAtEnd() && !dissimilarityIt.IsAtEnd() && !sumAverageIt.IsAtEnd() && !sumVarianceIt.IsAtEnd() &&
335 !sumEntropytIt.IsAtEnd() && !differenceEntropyIt.IsAtEnd() && !differenceVarianceIt.IsAtEnd() && !ic1It.IsAtEnd() && !ic2It.IsAtEnd())
338 typename InputRegionType::IndexType inputIndex;
339 typename InputRegionType::SizeType inputSize;
342 typename OutputImageType::IndexType outIndex;
346 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
348 outIndex[dim] = varianceIt.GetIndex()[dim] * m_SubsampleFactor[dim] + m_SubsampleOffset[dim] + inputLargest.GetIndex(dim);
349 inputIndex[dim] = outIndex[dim] - m_Radius[dim];
350 inputSize[dim] = 2 * m_Radius[dim] + 1;
355 inputRegion.SetIndex(inputIndex);
356 inputRegion.SetSize(inputSize);
357 inputRegion.Crop(inputPtr->GetRequestedRegion());
360 GLCIList->Initialize(m_NumberOfBinsPerAxis, m_InputImageMinimum, m_InputImageMaximum);
362 typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIteratorType;
363 NeighborhoodIteratorType neighborIt;
364 neighborIt = NeighborhoodIteratorType(m_NeighborhoodRadius, inputPtr, inputRegion);
365 for (neighborIt.GoToBegin(); !neighborIt.IsAtEnd(); ++neighborIt)
367 const InputPixelType centerPixelIntensity = neighborIt.GetCenterPixel();
369 const InputPixelType pixelIntensity = neighborIt.GetPixel(m_Offset, pixelInBounds);
375 GLCIList->AddPixelPair(centerPixelIntensity, pixelIntensity);
379 PixelValueType m_Variance = itk::NumericTraits<PixelValueType>::Zero;
380 PixelValueType m_Dissimilarity = itk::NumericTraits<PixelValueType>::Zero;
381 PixelValueType m_SumAverage = itk::NumericTraits<PixelValueType>::Zero;
382 PixelValueType m_SumEntropy = itk::NumericTraits<PixelValueType>::Zero;
383 PixelValueType m_SumVariance = itk::NumericTraits<PixelValueType>::Zero;
384 PixelValueType m_DifferenceEntropy = itk::NumericTraits<PixelValueType>::Zero;
385 PixelValueType m_DifferenceVariance = itk::NumericTraits<PixelValueType>::Zero;
391 typedef itk::Array<double> DoubleArrayType;
392 DoubleArrayType hx(histSize);
393 DoubleArrayType hy(histSize);
394 DoubleArrayType pdxy(twiceHistSize);
396 for (
long unsigned int i = 0; i < histSize; i++)
402 for (
long unsigned int i = histSize; i < twiceHistSize; i++)
412 double totalFrequency =
static_cast<double>(GLCIList->GetTotalFrequency());
417 constVectorIt = glcVector.begin();
418 while (constVectorIt != glcVector.end())
421 double frequency = (*constVectorIt).second / totalFrequency;
422 m_Mean +=
static_cast<double>(index[0]) * frequency;
423 Entropy -= (frequency > 0.0001) ? frequency * std::log(frequency) / log2 : 0.;
424 unsigned int i = index[1];
425 unsigned int j = index[0];
429 if (i + j > histSize - 1)
431 pdxy[i + j] += frequency;
435 pdxy[j - i] += frequency;
442 constVectorIt = glcVector.begin();
443 while (constVectorIt != glcVector.end())
445 double frequency = (*constVectorIt).second / totalFrequency;
447 unsigned int i = index[1];
448 unsigned int j = index[0];
449 double index0 =
static_cast<double>(index[0]);
450 m_Variance += ((index0 - m_Mean) * (index0 - m_Mean)) * frequency;
451 double pipj = hx[j] * hy[i];
452 hxy1 -= (pipj > 0.0001) ? frequency * std::log(pipj) : 0.;
457 double PSSquareCumul = 0;
458 for (
long unsigned int k = histSize; k < twiceHistSize; k++)
460 m_SumAverage += k * pdxy[k];
461 m_SumEntropy -= (pdxy[k] > 0.0001) ? pdxy[k] * std::log(pdxy[k]) / log2 : 0;
462 PSSquareCumul += k * k * pdxy[k];
464 m_SumVariance = PSSquareCumul - m_SumAverage * m_SumAverage;
466 double PDSquareCumul = 0;
471 for (
long unsigned int i = 0; i < histSize; ++i)
473 double pdTmp = pdxy[i];
474 PDCumul += i * pdTmp;
475 m_DifferenceEntropy -= (pdTmp > 0.0001) ? pdTmp * std::log(pdTmp) / log2 : 0;
476 PDSquareCumul += i * i * pdTmp;
479 double marginalfreq = hx[i];
480 hxCumul += (marginalfreq > 0.0001) ? std::log(marginalfreq) * marginalfreq : 0;
482 marginalfreq = hy[i];
483 hyCumul += (marginalfreq > 0.0001) ? std::log(marginalfreq) * marginalfreq : 0;
485 m_DifferenceVariance = PDSquareCumul - PDCumul * PDCumul;
490 for (
unsigned int i = 0; i < histSize; ++i)
492 for (
unsigned int j = 0; j < histSize; ++j)
494 double pipj = hx[j] * hy[i];
495 hxy2 -= (pipj > 0.0001) ? pipj * std::log(pipj) : 0.;
496 double frequency = GLCIList->GetFrequency(i, j, glcVector) / totalFrequency;
497 m_Dissimilarity += (
static_cast<double>(j) -
static_cast<double>(i)) * (frequency * frequency);
502 m_IC1 = (std::abs(std::max(hxCumul, hyCumul)) > 0.0001) ? (Entropy - hxy1) / (std::max(hxCumul, hyCumul)) : 0;
503 m_IC2 = 1 - std::exp(-2. * std::abs(hxy2 - Entropy));
504 m_IC2 = (m_IC2 >= 0) ? std::sqrt(m_IC2) : 0;
508 varianceIt.Set(m_Variance);
509 dissimilarityIt.Set(m_Dissimilarity);
510 sumAverageIt.Set(m_SumAverage);
511 sumVarianceIt.Set(m_SumVariance);
512 sumEntropytIt.Set(m_SumEntropy);
513 differenceEntropyIt.Set(m_DifferenceEntropy);
514 differenceVarianceIt.Set(m_DifferenceVariance);
525 ++differenceEntropyIt;
526 ++differenceVarianceIt;
InputImageType::PixelType InputPixelType
CooccurrenceIndexedListType::Pointer CooccurrenceIndexedListPointerType
ScalarImageToAdvancedTexturesFilter()
CooccurrenceIndexedListType::IndexType CooccurrenceIndexType
OffsetType m_SubsampleOffset
TInpuImage InputImageType
~ScalarImageToAdvancedTexturesFilter() override
CooccurrenceIndexedListType::VectorType VectorType
void GenerateOutputInformation() override
CooccurrenceIndexedListType::PixelValueType PixelValueType
OutputImageType::Pointer OutputImagePointerType
InputImageType::Pointer InputImagePointerType
OutputImageType * GetIC2Output()
OutputImageType * GetIC1Output()
void GenerateInputRequestedRegion() override
OutputImageType * GetDifferenceEntropyOutput()
OutputImageType * GetDifferenceVarianceOutput()
OutputImageType * GetSumEntropyOutput()
void DynamicThreadedGenerateData(const OutputRegionType &outputRegion) override
OutputImageType * GetDissimilarityOutput()
InputImageType::RegionType InputRegionType
OutputImageType * GetSumVarianceOutput()
void BeforeThreadedGenerateData() override
OutputImageType * GetVarianceOutput()
OutputImageType::RegionType OutputRegionType
OutputImageType * GetMeanOutput()
OutputImageType * GetSumAverageOutput()
SizeType m_SubsampleFactor
VectorType::const_iterator VectorConstIteratorType
TOutputImage OutputImageType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.