21 #ifndef otbHaralickTexturesImageFunction_hxx
22 #define otbHaralickTexturesImageFunction_hxx
25 #include "itkImageRegionIteratorWithIndex.h"
26 #include "itkConstNeighborhoodIterator.h"
27 #include "itkNumericTraits.h"
37 template <
class TInputImage,
class TCoordRep>
39 : m_NeighborhoodRadius(10), m_Offset(), m_NumberOfBinsPerAxis(8), m_InputImageMinimum(0), m_InputImageMaximum(255)
43 template <
class TInputImage,
class TCoordRep>
46 this->Superclass::PrintSelf(os, indent);
47 os << indent <<
" Neighborhood radius value : " << m_NeighborhoodRadius << std::endl;
48 os << indent <<
" Input image minimum value : " << m_InputImageMinimum << std::endl;
49 os << indent <<
" Input Image maximum value : " << m_InputImageMaximum << std::endl;
50 os << indent <<
" Number of bins per axis : " << m_NumberOfBinsPerAxis << std::endl;
51 os << indent <<
" Offset : " << m_Offset << std::endl;
54 template <
class TInputImage,
class TCoordRep>
62 textures.Fill(itk::NumericTraits<ScalarRealType>::Zero);
65 if (!this->GetInputImage())
71 if (!this->IsInsideBuffer(index))
76 const double log2 = std::log(2.0);
81 typename InputRegionType::IndexType inputIndex;
82 typename InputRegionType::SizeType inputSize;
84 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
86 inputIndex[dim] = index[dim] - m_NeighborhoodRadius;
87 inputSize[dim] = 2 * m_NeighborhoodRadius + 1;
92 inputRegion.SetIndex(inputIndex);
93 inputRegion.SetSize(inputSize);
94 inputRegion.Crop(inputPtr->GetRequestedRegion());
97 GLCIList->Initialize(m_NumberOfBinsPerAxis, m_InputImageMinimum, m_InputImageMaximum);
100 unsigned int minRadius = 0;
101 for (
unsigned int i = 0; i < m_Offset.GetOffsetDimension(); i++)
103 unsigned int distance = std::abs(m_Offset[i]);
104 if (distance > minRadius)
106 minRadius = distance;
110 radius.Fill(minRadius);
113 typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIteratorType;
114 NeighborhoodIteratorType neighborIt;
115 neighborIt = NeighborhoodIteratorType(radius, inputPtr, inputRegion);
116 for (neighborIt.GoToBegin(); !neighborIt.IsAtEnd(); ++neighborIt)
118 const InputPixelType centerPixelIntensity = neighborIt.GetCenterPixel();
120 const InputPixelType pixelIntensity = neighborIt.GetPixel(m_Offset, pixelInBounds);
125 GLCIList->AddPixelPair(centerPixelIntensity, pixelIntensity);
129 double pixelMean = 0.;
131 double marginalDevSquared = 0.;
132 double pixelVariance = 0.;
135 std::vector<double> marginalSums(m_NumberOfBinsPerAxis, 0);
139 double totalFrequency =
static_cast<double>(GLCIList->GetTotalFrequency());
142 typename VectorType::iterator it = glcVector.begin();
143 while (it != glcVector.end())
145 double frequency = (*it).second / totalFrequency;
147 pixelMean += index2[0] * frequency;
148 marginalSums[index2[0]] += frequency;
162 std::vector<double>::const_iterator msIt = marginalSums.begin();
163 marginalMean = *msIt;
166 for (
int k = 2; msIt != marginalSums.end(); ++k, ++msIt)
168 double M_k_minus_1 = marginalMean;
169 double S_k_minus_1 = marginalDevSquared;
171 double M_k = M_k_minus_1 + (x_k - M_k_minus_1) / k;
172 double S_k = S_k_minus_1 + (x_k - M_k_minus_1) * (x_k - M_k);
174 marginalDevSquared = S_k;
176 marginalDevSquared = marginalDevSquared / m_NumberOfBinsPerAxis;
179 constVectorIt = glcVector.begin();
180 while (constVectorIt != glcVector.end())
184 pixelVariance += (index2[0] - pixelMean) * (index2[0] - pixelMean) * frequency;
188 double pixelVarianceSquared = pixelVariance * pixelVariance;
192 if (pixelVarianceSquared < GetPixelValueTolerance())
194 pixelVarianceSquared = 1.;
198 constVectorIt = glcVector.begin();
199 while (constVectorIt != glcVector.end())
203 textures[0] += frequency * frequency;
204 textures[1] -= (frequency > GetPixelValueTolerance()) ? frequency * std::log(frequency) / log2 : 0;
205 textures[2] += ((index2[0] - pixelMean) * (index2[1] - pixelMean) * frequency) / pixelVarianceSquared;
206 textures[3] += frequency / (1.0 + (index2[0] - index2[1]) * (index2[0] - index2[1]));
207 textures[4] += (index2[0] - index2[1]) * (index2[0] - index2[1]) * frequency;
208 textures[5] += std::pow((index2[0] - pixelMean) + (index2[1] - pixelMean), 3) * frequency;
209 textures[6] += std::pow((index2[0] - pixelMean) + (index2[1] - pixelMean), 4) * frequency;
210 textures[7] += index2[0] * index2[1] * frequency;
213 textures[7] = (fabs(marginalDevSquared) > 1E-8) ? (textures[7] - marginalMean * marginalMean) / marginalDevSquared : 0;