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),
46 this->SetNumberOfRequiredOutputs(10);
49 this->SetNthOutput(0, OutputImageType::New());
50 this->SetNthOutput(1, OutputImageType::New());
51 this->SetNthOutput(2, OutputImageType::New());
52 this->SetNthOutput(3, OutputImageType::New());
53 this->SetNthOutput(4, OutputImageType::New());
54 this->SetNthOutput(5, OutputImageType::New());
55 this->SetNthOutput(6, OutputImageType::New());
56 this->SetNthOutput(7, OutputImageType::New());
57 this->SetNthOutput(8, OutputImageType::New());
58 this->SetNthOutput(9, OutputImageType::New());
64 template <
class TInputImage,
class TOutputImage>
68 template <
class TInputImage,
class TOutputImage>
72 if (this->GetNumberOfOutputs() < 1)
79 template <
class TInputImage,
class TOutputImage>
83 if (this->GetNumberOfOutputs() < 2)
90 template <
class TInputImage,
class TOutputImage>
94 if (this->GetNumberOfOutputs() < 3)
101 template <
class TInputImage,
class TOutputImage>
105 if (this->GetNumberOfOutputs() < 4)
112 template <
class TInputImage,
class TOutputImage>
116 if (this->GetNumberOfOutputs() < 5)
123 template <
class TInputImage,
class TOutputImage>
127 if (this->GetNumberOfOutputs() < 6)
134 template <
class TInputImage,
class TOutputImage>
138 if (this->GetNumberOfOutputs() < 7)
145 template <
class TInputImage,
class TOutputImage>
149 if (this->GetNumberOfOutputs() < 8)
156 template <
class TInputImage,
class TOutputImage>
160 if (this->GetNumberOfOutputs() < 9)
167 template <
class TInputImage,
class TOutputImage>
171 if (this->GetNumberOfOutputs() < 10)
178 template <
class TInputImage,
class TOutputImage>
182 Superclass::GenerateOutputInformation();
185 InputRegionType inputRegion = this->GetInput()->GetLargestPossibleRegion();
187 outputRegion.SetIndex(0, 0);
188 outputRegion.SetIndex(1, 0);
189 outputRegion.SetSize(0, 1 + (inputRegion.GetSize(0) - 1 - m_SubsampleOffset[0]) / m_SubsampleFactor[0]);
190 outputRegion.SetSize(1, 1 + (inputRegion.GetSize(1) - 1 - m_SubsampleOffset[1]) / m_SubsampleFactor[1]);
192 typename OutputImageType::SpacingType outSpacing = this->GetInput()->GetSignedSpacing();
193 outSpacing[0] *= m_SubsampleFactor[0];
194 outSpacing[1] *= m_SubsampleFactor[1];
196 typename OutputImageType::PointType outOrigin;
197 this->GetInput()->TransformIndexToPhysicalPoint(inputRegion.GetIndex() + m_SubsampleOffset, outOrigin);
199 for (
unsigned int i = 0; i < this->GetNumberOfOutputs(); i++)
202 outputPtr->SetLargestPossibleRegion(outputRegion);
203 outputPtr->SetOrigin(outOrigin);
204 outputPtr->SetSignedSpacing(outSpacing);
208 template <
class TInputImage,
class TOutputImage>
212 Superclass::GenerateInputRequestedRegion();
218 if (!inputPtr || !outputPtr)
229 typename OutputRegionType::IndexType outputIndex = outputRequestedRegion.GetIndex();
230 typename OutputRegionType::SizeType outputSize = outputRequestedRegion.GetSize();
231 typename InputRegionType::IndexType inputIndex;
232 typename InputRegionType::SizeType inputSize;
235 outputIndex[0] = outputIndex[0] * m_SubsampleFactor[0] + m_SubsampleOffset[0] + inputLargest.GetIndex(0);
236 outputIndex[1] = outputIndex[1] * m_SubsampleFactor[1] + m_SubsampleOffset[1] + inputLargest.GetIndex(1);
237 outputSize[0] = 1 + (outputSize[0] - 1) * m_SubsampleFactor[0];
238 outputSize[1] = 1 + (outputSize[1] - 1) * m_SubsampleFactor[1];
241 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
243 inputIndex[dim] = std::min(outputIndex[dim], outputIndex[dim] + m_Offset[dim]);
244 inputSize[dim] = std::max(outputIndex[dim] + outputSize[dim], outputIndex[dim] + outputSize[dim] + m_Offset[dim]) - inputIndex[dim];
249 inputRequestedRegion.SetIndex(inputIndex);
250 inputRequestedRegion.SetSize(inputSize);
253 inputRequestedRegion.PadByRadius(m_Radius);
256 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
258 inputPtr->SetRequestedRegion(inputRequestedRegion);
263 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
264 e.SetLocation(ITK_LOCATION);
265 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
266 e.SetDataObject(inputPtr);
271 template <
class TInputImage,
class TOutputImage>
274 unsigned int minRadius = 0;
275 for (
unsigned int i = 0; i < m_Offset.GetOffsetDimension(); i++)
277 unsigned int distance = std::abs(m_Offset[i]);
278 if (distance > minRadius)
280 minRadius = distance;
283 m_NeighborhoodRadius.Fill(minRadius);
286 template <
class TInputImage,
class TOutputImage>
288 itk::ThreadIdType threadId)
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 itk::ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels());
337 while (!varianceIt.IsAtEnd() && !meanIt.IsAtEnd() && !dissimilarityIt.IsAtEnd() && !sumAverageIt.IsAtEnd() && !sumVarianceIt.IsAtEnd() &&
338 !sumEntropytIt.IsAtEnd() && !differenceEntropyIt.IsAtEnd() && !differenceVarianceIt.IsAtEnd() && !ic1It.IsAtEnd() && !ic2It.IsAtEnd())
341 typename InputRegionType::IndexType inputIndex;
342 typename InputRegionType::SizeType inputSize;
345 typename OutputImageType::IndexType outIndex;
349 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
351 outIndex[dim] = varianceIt.GetIndex()[dim] * m_SubsampleFactor[dim] + m_SubsampleOffset[dim] + inputLargest.GetIndex(dim);
352 inputIndex[dim] = outIndex[dim] - m_Radius[dim];
353 inputSize[dim] = 2 * m_Radius[dim] + 1;
358 inputRegion.SetIndex(inputIndex);
359 inputRegion.SetSize(inputSize);
360 inputRegion.Crop(inputPtr->GetRequestedRegion());
363 GLCIList->Initialize(m_NumberOfBinsPerAxis, m_InputImageMinimum, m_InputImageMaximum);
365 typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIteratorType;
366 NeighborhoodIteratorType neighborIt;
367 neighborIt = NeighborhoodIteratorType(m_NeighborhoodRadius, inputPtr, inputRegion);
368 for (neighborIt.GoToBegin(); !neighborIt.IsAtEnd(); ++neighborIt)
370 const InputPixelType centerPixelIntensity = neighborIt.GetCenterPixel();
372 const InputPixelType pixelIntensity = neighborIt.GetPixel(m_Offset, pixelInBounds);
378 GLCIList->AddPixelPair(centerPixelIntensity, pixelIntensity);
382 PixelValueType m_Variance = itk::NumericTraits<PixelValueType>::Zero;
383 PixelValueType m_Dissimilarity = itk::NumericTraits<PixelValueType>::Zero;
384 PixelValueType m_SumAverage = itk::NumericTraits<PixelValueType>::Zero;
385 PixelValueType m_SumEntropy = itk::NumericTraits<PixelValueType>::Zero;
386 PixelValueType m_SumVariance = itk::NumericTraits<PixelValueType>::Zero;
387 PixelValueType m_DifferenceEntropy = itk::NumericTraits<PixelValueType>::Zero;
388 PixelValueType m_DifferenceVariance = itk::NumericTraits<PixelValueType>::Zero;
394 typedef itk::Array<double> DoubleArrayType;
395 DoubleArrayType hx(histSize);
396 DoubleArrayType hy(histSize);
397 DoubleArrayType pdxy(twiceHistSize);
399 for (
long unsigned int i = 0; i < histSize; i++)
405 for (
long unsigned int i = histSize; i < twiceHistSize; i++)
415 double totalFrequency =
static_cast<double>(GLCIList->GetTotalFrequency());
420 constVectorIt = glcVector.begin();
421 while (constVectorIt != glcVector.end())
424 double frequency = (*constVectorIt).second / totalFrequency;
425 m_Mean +=
static_cast<double>(index[0]) * frequency;
426 Entropy -= (frequency > 0.0001) ? frequency * std::log(frequency) / log2 : 0.;
427 unsigned int i = index[1];
428 unsigned int j = index[0];
432 if (i + j > histSize - 1)
434 pdxy[i + j] += frequency;
438 pdxy[j - i] += frequency;
445 constVectorIt = glcVector.begin();
446 while (constVectorIt != glcVector.end())
448 double frequency = (*constVectorIt).second / totalFrequency;
450 unsigned int i = index[1];
451 unsigned int j = index[0];
452 double index0 =
static_cast<double>(index[0]);
453 m_Variance += ((index0 - m_Mean) * (index0 - m_Mean)) * frequency;
454 double pipj = hx[j] * hy[i];
455 hxy1 -= (pipj > 0.0001) ? frequency * std::log(pipj) : 0.;
460 double PSSquareCumul = 0;
461 for (
long unsigned int k = histSize; k < twiceHistSize; k++)
463 m_SumAverage += k * pdxy[k];
464 m_SumEntropy -= (pdxy[k] > 0.0001) ? pdxy[k] * std::log(pdxy[k]) / log2 : 0;
465 PSSquareCumul += k * k * pdxy[k];
467 m_SumVariance = PSSquareCumul - m_SumAverage * m_SumAverage;
469 double PDSquareCumul = 0;
474 for (
long unsigned int i = 0; i < histSize; ++i)
476 double pdTmp = pdxy[i];
477 PDCumul += i * pdTmp;
478 m_DifferenceEntropy -= (pdTmp > 0.0001) ? pdTmp * std::log(pdTmp) / log2 : 0;
479 PDSquareCumul += i * i * pdTmp;
482 double marginalfreq = hx[i];
483 hxCumul += (marginalfreq > 0.0001) ? std::log(marginalfreq) * marginalfreq : 0;
485 marginalfreq = hy[i];
486 hyCumul += (marginalfreq > 0.0001) ? std::log(marginalfreq) * marginalfreq : 0;
488 m_DifferenceVariance = PDSquareCumul - PDCumul * PDCumul;
493 for (
unsigned int i = 0; i < histSize; ++i)
495 for (
unsigned int j = 0; j < histSize; ++j)
497 double pipj = hx[j] * hy[i];
498 hxy2 -= (pipj > 0.0001) ? pipj * std::log(pipj) : 0.;
499 double frequency = GLCIList->GetFrequency(i, j, glcVector) / totalFrequency;
500 m_Dissimilarity += (
static_cast<double>(j) -
static_cast<double>(i)) * (frequency * frequency);
505 m_IC1 = (std::abs(std::max(hxCumul, hyCumul)) > 0.0001) ? (Entropy - hxy1) / (std::max(hxCumul, hyCumul)) : 0;
506 m_IC2 = 1 - std::exp(-2. * std::abs(hxy2 - Entropy));
507 m_IC2 = (m_IC2 >= 0) ? std::sqrt(m_IC2) : 0;
511 varianceIt.Set(m_Variance);
512 dissimilarityIt.Set(m_Dissimilarity);
513 sumAverageIt.Set(m_SumAverage);
514 sumVarianceIt.Set(m_SumVariance);
515 sumEntropytIt.Set(m_SumEntropy);
516 differenceEntropyIt.Set(m_DifferenceEntropy);
517 differenceVarianceIt.Set(m_DifferenceVariance);
522 progress.CompletedPixel();
531 ++differenceEntropyIt;
532 ++differenceVarianceIt;