22 #ifndef otbKullbackLeiblerProfileImageFilter_hxx
23 #define otbKullbackLeiblerProfileImageFilter_hxx
29 #include "vcl_legacy_aliases.h"
38 template <
class TInput>
41 m_debug = MakeSumAndMoments(input, mask);
47 template <
class TInput>
48 template <
class TInput2>
51 itk::VariableLengthVector<double> resu(fCum.size());
56 for (
unsigned int level = 0; level < resu.GetSize(); level++)
57 resu[level] =
KL_profile((*iter1++), (*iter2++));
64 template <
class TInput>
67 double cum1 = cumulants1[0];
68 double cum2 = cumulants1[1];
69 double cum3 = cumulants1[2];
72 double sqrt_cum2 = sqrt(cum2);
73 double cum2_3 = cum2 * cum2 * cum2;
74 double cum3_2 = cum3 * cum3;
76 double tilde_cum1 = cumulants2[0];
77 double tilde_cum2 = cumulants2[1];
78 double tilde_cum3 = cumulants2[2];
79 double tilde_cum4 = cumulants2[3];
81 double tilde_cum2_2 = cum2 * cum2;
82 double tilde_cum2_3 = cum2 * tilde_cum2_2;
83 double tilde_cum2_6 = tilde_cum2_3 * tilde_cum2_3;
84 double tilde_cum3_2 = tilde_cum3 * tilde_cum3;
86 double beta = sqrt_cum2 / tilde_cum2;
87 double alpha = (cum1 - tilde_cum1) / tilde_cum2;
89 double alpha_2 = alpha * alpha;
90 double alpha_4 = alpha_2 * alpha_2;
91 double alpha_6 = alpha_2 * alpha_4;
93 double beta_2 = beta * beta;
94 double beta_4 = beta_2 * beta_2;
95 double beta_6 = beta_2 * beta_4;
97 double c2 = alpha_2 + beta_2;
98 double c3 = alpha * (alpha_2 + 3.0 * beta_2);
99 double c4 = alpha_4 + 6.0 * alpha_2 * beta_2 + 3.0 * beta_4;
100 double c6 = alpha_6 + 15.0 * alpha_4 * beta_2 + 45.0 * alpha_2 * beta_4 + 15.0 * beta_6;
102 double a1 = c3 - 3.0 * alpha / tilde_cum2;
103 double a2 = c4 - 6.0 * c2 / tilde_cum2 + 3.0 / tilde_cum2_2;
104 double a3 = c6 - 15.0 * c4 / tilde_cum2 + 45.0 * c2 / tilde_cum2_2 - 15.0 / tilde_cum2_3;
106 double tmp = cum1 - tilde_cum1 + sqrt_cum2;
107 double resu = cum3_2 / (12.0 * cum2_3) + (log(tilde_cum2 / cum2) - 1.0 + tmp * tmp / tilde_cum2) / 2.0 -
108 (tilde_cum3 * a1 / 6.0 + tilde_cum4 * a2 / 24.0 + tilde_cum3_2 * a3 / 72.0) -
109 tilde_cum3_2 * (c6 - 6.0 * c4 / cum2 + 9.0 * c2 / tilde_cum2_2) / 72.0 -
110 10.0 * cum3 * tilde_cum3 * (cum1 - tilde_cum1) * (cum2 - tilde_cum2) / tilde_cum2_6;
112 if (vnl_math_isnan(resu) || resu > 1e3)
115 return resu < 0.0 ? 0.0 : resu;
120 template <
class TInput>
123 fMu.resize(mask.size());
124 std::vector<itk::Array2D<int>>::iterator iter = mask.begin();
126 if (InitSumAndMoments(input, (*iter++)))
129 for (
unsigned int level = 1; level < mask.size(); level++)
130 if (ReInitSumAndMoments(input, (*iter++), level))
139 template <
class TInput>
142 fSum0 = fSum1 = fSum2 = fSum3 = fSum4 = 0.0;
147 double pixel, pixel_2;
150 for (i = 0; i < mask.rows(); ++i)
152 for (j = 0; j < mask.cols(); ++j)
155 if (mask.get(i, j) == 1)
157 pixel =
static_cast<double>(input.GetPixel(k));
158 pixel_2 = pixel * pixel;
163 fSum3 += pixel_2 * pixel;
164 fSum4 += pixel_2 * pixel_2;
172 fDataAvailable =
false;
179 mu2 = fSum2 / fSum0 - mu1 * mu1;
183 fDataAvailable =
false;
187 double sigma = sqrt(mu2);
189 itk::VariableLengthVector<double> tab(input.Size());
190 double* x =
const_cast<double*
>(tab.GetDataPointer());
191 for (
unsigned long cp = 0; cp < input.Size(); ++cp)
192 *x++ = (
static_cast<double>(input.GetPixel(cp)) - mu1) / sigma;
196 x =
const_cast<double*
>(tab.GetDataPointer());
199 for (i = 0; i < mask.rows(); ++i)
201 for (j = 0; j < mask.cols(); ++j)
203 if (mask.get(i, j) == 1)
206 pixel_2 = pixel * pixel;
208 mu3 += pixel * pixel_2;
209 mu4 += pixel_2 * pixel_2;
219 if (vnl_math_isnan(mu3) || vnl_math_isnan(mu4))
221 fDataAvailable =
false;
230 fDataAvailable =
true;
237 template <
class TInput>
240 fMu[level].Fill(0.0);
242 double sum0 = 0.0, sum1 = 0.0, sum2 = 0.0, sum3 = 0.0, sum4 = 0.0;
244 double pixel, pixel_2;
247 unsigned long k = 0L;
250 for (i = 0; i < mask.rows(); ++i)
252 for (j = 0; j < mask.cols(); ++j)
254 if (mask.get(i, j) == 1)
256 pixel =
static_cast<double>(input.GetPixel(k));
257 pixel_2 = pixel * pixel;
262 sum3 += pixel * pixel_2;
263 sum4 += pixel_2 * pixel_2;
275 double mu = fSum1 / fSum0;
276 double mu_2 = mu * mu;
277 double mu_3 = mu_2 * mu;
278 double mu_4 = mu_2 * mu_2;
281 fMu[level][1] = fSum2 / fSum0 - mu_2;
283 double sigma = sqrt(fSum2);
284 double sigma_2 = fSum2;
285 double sigma_3 = sigma * sigma_2;
286 double sigma_4 = sigma_2 * sigma_2;
288 fMu[level][2] = (fSum3 - 3.0 * mu * fSum2 + 3.0 * mu_2 * fSum1 - fSum0 * mu_3) / (sigma_3 * fSum0);
289 fMu[level][3] = (fSum4 - 4.0 * mu * fSum3 + 6.0 * mu_2 * fSum2 - 4.0 * mu_3 * fSum1 + fSum0 * mu_4) / (sigma_4 * fSum0);
296 template <
class TInput>
299 if (!IsDataAvailable())
302 fCum.resize(fMu.size());
305 for (
unsigned int i = 0; i < fCum.size(); ++i)
321 template <
class TInput1,
class TInput2,
class TOutput>
330 template <
class TInput1,
class TInput2,
class TOutput>
333 m_RadiusMin = min < max ? min : max;
334 m_RadiusMax = max > min ? max : min;
335 MakeMultiscaleProfile();
338 template <
class TInput1,
class TInput2,
class TOutput>
344 template <
class TInput1,
class TInput2,
class TOutput>
352 template <
class TInput1,
class TInput2,
class TOutput>
355 m_mask.resize(m_RadiusMax - m_RadiusMin + 1);
356 int lenMax = 2 * m_RadiusMax + 1;
357 int i, j, middle = m_RadiusMax;
360 std::vector<itk::Array2D<int>>::iterator outer_iter = m_mask.begin();
361 (*outer_iter).SetSize(lenMax, lenMax);
362 (*outer_iter).fill(0);
363 for (i = middle - m_RadiusMin; i <= middle + m_RadiusMin; ++i)
364 for (j = middle - m_RadiusMin; j <= middle + m_RadiusMin; ++j)
365 (*outer_iter).put(i, j, 1);
371 for (
int radius = m_RadiusMin + 1; radius <= m_RadiusMax; ++radius)
373 (*outer_iter).SetSize(lenMax, lenMax);
374 (*outer_iter).fill(0);
376 for (i = middle - radius; i <= middle + radius; ++i)
378 (*outer_iter).put(i, middle - radius, 1);
379 (*outer_iter).put(i, middle + radius, 1);
380 (*outer_iter).put(middle - radius, i, 1);
381 (*outer_iter).put(middle + radius, i, 1);
391 template <
class TInput1,
class TInput2,
class TOutput>
398 itk::VariableLengthVector<double> resu(m_RadiusMax - m_RadiusMin + 1);
400 return static_cast<TOutput
>(resu);
407 itk::VariableLengthVector<double> resu(m_RadiusMax - m_RadiusMin + 1);
409 return static_cast<TOutput
>(resu);
Helper class for KullbackLeiblerProfileImageFilter. Please refer to KullbackLeibleProfileImageFilter.
CumulantSet::iterator Iterator
itk::Vector< double, 4 > CumulantType
int InitSumAndMoments(const TInput &input, itk::Array2D< int > &mask)
CumulantsForEdgeworthProfile()
itk::VariableLengthVector< double > KL_profile(CumulantsForEdgeworthProfile< TInput2 > &cumulants)
int ReInitSumAndMoments(const TInput &input, itk::Array2D< int > &mask, int level)
int MakeSumAndMoments(const TInput &input, std::vector< itk::Array2D< int >> &mask)
unsigned char GetRadiusMax(void)
void SetRadius(const unsigned char &min, const unsigned char &max)
void MakeMultiscaleProfile()
TOutput operator()(const TInput1 &it1, const TInput2 &it2)
unsigned char GetRadiusMin(void)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.