diff --git a/modules/img/alg/src/CMakeLists.txt b/modules/img/alg/src/CMakeLists.txt index c181156dbfe99eb4ac8b6a4532fa359b8b161d45..5dc212da9f112a9eed2dafc53eb187254a550a95 100644 --- a/modules/img/alg/src/CMakeLists.txt +++ b/modules/img/alg/src/CMakeLists.txt @@ -25,7 +25,6 @@ power_spectrum.cc randomize.cc smooth_mask_image.cc stat.cc -stat_accumulator.cc stat_min_max.cc alg_transform.cc alg_mirror.cc diff --git a/modules/img/alg/src/stat.cc b/modules/img/alg/src/stat.cc index f433cd6d69a7810a2e34ca043ad3257720cb9acc..01053ab7e28bbccdfaf0a7c4839633246d675995 100644 --- a/modules/img/alg/src/stat.cc +++ b/modules/img/alg/src/stat.cc @@ -64,7 +64,7 @@ void StatBase::VisitState(const ImageStateImpl<T,D>& isi) ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0)); min_ = std::numeric_limits<Real>::max(); max_ = -std::numeric_limits<Real>::max(); - StatAccumulator acc; + StatAccumulator<> acc; int wi=isi.GetSize()[0]; int he=isi.GetSize()[1]; @@ -124,7 +124,7 @@ void StatBase::VisitFunction(const Function& fnc) ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0)); min_ = std::numeric_limits<Real>::max(); max_ = -std::numeric_limits<Real>::max(); - StatAccumulator acc; + StatAccumulator<> acc; for(ExtentIterator it(fnc.GetExtent());!it.AtEnd(); ++it) { Real val=fnc.GetReal(it); diff --git a/modules/img/alg/src/stat_accumulator.cc b/modules/img/alg/src/stat_accumulator.cc deleted file mode 100644 index c4641d5504cafa83cfb788dec0ad21b59cead46e..0000000000000000000000000000000000000000 --- a/modules/img/alg/src/stat_accumulator.cc +++ /dev/null @@ -1,141 +0,0 @@ -//------------------------------------------------------------------------------ -// This file is part of the OpenStructure project <www.openstructure.org> -// -// Copyright (C) 2008-2011 by the OpenStructure authors -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License as published by the Free -// Software Foundation; either version 3.0 of the License, or (at your option) -// any later version. -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -// details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this library; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -//------------------------------------------------------------------------------ - - -#include "stat_accumulator.hh" - -namespace ost { namespace img { namespace alg { - -StatAccumulator::StatAccumulator(): - mean_(0.0), - sum_(0.0), - sum2_(0.0), - m2_(0.0), - m3_(0.0), - m4_(0.0), - n_(1) - -{ -} - -void StatAccumulator::operator()(Real val) -{ - Real delta = val - mean_; - Real delta_n = delta / n_; - Real delta_n2 = delta_n * delta_n; - Real term = delta * delta_n * (n_-1); - - mean_ += delta_n; - m4_ += term * delta_n2 * (n_*n_ - 3*n_ + 3) + 6 * delta_n2 * m2_ - 4 * delta_n * m3_; - m3_ += term * delta_n * (n_ - 2) - 3 * delta_n * m2_; - m2_ += term; - sum_+=val; - sum2_+=val*val; - n_+=1; -} - -StatAccumulator StatAccumulator::operator+(const StatAccumulator& acc2) const -{ - StatAccumulator acc(acc2); - acc+=*this; - return acc; -} - -StatAccumulator& StatAccumulator::operator+=(const StatAccumulator& acc) -{ - if(acc.n_==1){ - return *this; - } - if(n_==1){ - mean_=acc.mean_; - sum_=acc.sum_; - sum2_=acc.sum2_; - m2_=acc.m2_; - m3_=acc.m3_; - m4_=acc.m4_; - n_=acc.n_; - return *this; - } - Real na=n_-1; - Real nb=acc.n_-1; - Real nanb=na*nb; - Real delta = acc.mean_ - mean_; - Real delta_n = delta / (na+nb); - Real delta_n2 = delta_n * delta_n; - - mean_ += nb*delta_n; - m4_+=acc.m4_+delta*delta_n*delta_n2*nanb*(na*na-nanb+nb*nb)+6.0*delta_n2*(na*na*acc.m2_+nb*nb*m2_)+4.0*delta_n*(na*acc.m3_-nb*m3_); - m3_+=acc.m3_+delta*delta_n2*nanb*(na-nb)+3.0*delta_n*(na*acc.m2_-nb*m2_); - m2_ += acc.m2_+delta*delta_n*nanb; - sum_+=acc.sum_; - sum2_+=acc.sum2_; - n_+=nb; - return *this; -} - -Real StatAccumulator::GetMean() const -{ - return mean_; -} - -Real StatAccumulator::GetSum() const -{ - return sum_; -} - -Real StatAccumulator::GetVariance() const -{ - if(n_==1.0){ - return 0.0; - } - return m2_/(n_-1); -} - -Real StatAccumulator::GetStandardDeviation() const -{ - return sqrt(GetVariance()); -} - -Real StatAccumulator::GetRootMeanSquare() const -{ - if(n_==1.0){ - return 0.0; - } - return sqrt(sum2_/(n_-1)); -} - -Real StatAccumulator::GetSkewness() const -{ - if(m2_<1e-20){ - return 0.0; - }else{ - return m3_/sqrt(m2_*m2_*m2_); - } -} - -Real StatAccumulator::GetKurtosis() const -{ - if(m2_<1e-20){ - return 0.0; - }else{ - return ((n_-1)*m4_) / (m2_*m2_); - } -} - -}}} //ns diff --git a/modules/img/alg/src/stat_accumulator.hh b/modules/img/alg/src/stat_accumulator.hh index 3cb5f06eb3c9882aa1481b637de626e11322d567..3483890b0ced8c3f5e71382f3273fcdcafc68ef0 100644 --- a/modules/img/alg/src/stat_accumulator.hh +++ b/modules/img/alg/src/stat_accumulator.hh @@ -25,21 +25,168 @@ namespace ost { namespace img { namespace alg { +template<unsigned int MAX_MOMENT=4> class DLLEXPORT_IMG_ALG StatAccumulator { public: - StatAccumulator(); - void operator()(Real val); - StatAccumulator operator+(const StatAccumulator& acc) const; - StatAccumulator& operator+=(const StatAccumulator& acc); - - Real GetMean() const ; - Real GetSum() const ; - Real GetVariance() const; - Real GetStandardDeviation() const ; - Real GetRootMeanSquare() const; - Real GetSkewness() const ; - Real GetKurtosis() const; + StatAccumulator(): + mean_(0.0), + sum_(0.0), + sum2_(0.0), + m2_(0.0), + m3_(0.0), + m4_(0.0), + n_(1) + {} + + void operator()(Real val) + { + Real delta,delta_n,delta_n2,term; + if(MAX_MOMENT>0){ + delta = val - mean_; + delta_n = delta / n_; + } + if(MAX_MOMENT>3){ + delta_n2 = delta_n * delta_n; + } + if(MAX_MOMENT>1){ + term = delta * delta_n * (n_-1); + } + if(MAX_MOMENT>3){ + m4_ += term * delta_n2 * (n_*n_ - 3*n_ + 3) + 6 * delta_n2 * m2_ - 4 * delta_n * m3_; + } + if(MAX_MOMENT>2){ + m3_ += term * delta_n * (n_ - 2) - 3 * delta_n * m2_; + } + if(MAX_MOMENT>1){ + m2_ += term; + } + if(MAX_MOMENT>0){ + mean_ += delta_n; + } + n_+=1; + sum_+=val; + sum2_+=val*val; + } + + StatAccumulator operator+(const StatAccumulator& acc2) const + { + StatAccumulator acc(acc2); + acc+=*this; + return acc; + } + + StatAccumulator& operator+=(const StatAccumulator& acc) + { + if(acc.n_==1){ + return *this; + } + if(n_==1){ + mean_=acc.mean_; + sum_=acc.sum_; + sum2_=acc.sum2_; + m2_=acc.m2_; + m3_=acc.m3_; + m4_=acc.m4_; + n_=acc.n_; + return *this; + } + Real delta,delta_n,delta_n2,na,nanb; + Real nb=acc.n_-1; + if(MAX_MOMENT>0){ + na=n_-1; + delta = acc.mean_ - mean_; + delta_n = delta / (na+nb); + } + if(MAX_MOMENT>1){ + nanb=na*nb; + } + if(MAX_MOMENT>2){ + delta_n2 = delta_n * delta_n; + } + if(MAX_MOMENT>3){ + m4_+=acc.m4_+delta*delta_n*delta_n2*nanb*(na*na-nanb+nb*nb)+6.0*delta_n2*(na*na*acc.m2_+nb*nb*m2_)+4.0*delta_n*(na*acc.m3_-nb*m3_); + } + if(MAX_MOMENT>2){ + m3_+=acc.m3_+delta*delta_n2*nanb*(na-nb)+3.0*delta_n*(na*acc.m2_-nb*m2_); + } + if(MAX_MOMENT>1){ + m2_ += acc.m2_+delta*delta_n*nanb; + } + if(MAX_MOMENT>0){ + mean_ += nb*delta_n; + } + sum_+=acc.sum_; + sum2_+=acc.sum2_; + n_+=nb; + return *this; + } + + Real GetNumSamples() const + { + return n_-1.0; + } + + Real GetMean() const + { + if(MAX_MOMENT<1){ + throw Error("Mean was not calculated."); + } + return mean_; + } + + Real GetSum() const + { + return sum_; + } + + Real GetVariance() const + { + if(MAX_MOMENT<2){ + throw Error("Variance was not calculated."); + } + if(n_==1.0){ + return 0.0; + } + return m2_/(n_-1); + } + + Real GetStandardDeviation() const + { + return sqrt(GetVariance()); + } + + Real GetRootMeanSquare() const + { + if(n_==1.0){ + return 0.0; + } + return sqrt(sum2_/(n_-1)); + } + + Real GetSkewness() const + { + if(MAX_MOMENT<3){ + throw Error("Skewness was not calculated."); + } + if(m2_<1e-20){ + return 0.0; + }else{ + return m3_/sqrt(m2_*m2_*m2_); + } + } + + Real GetKurtosis() const + { + if(MAX_MOMENT<4){ + throw Error("Kurtosis was not calculated."); + } + if(m2_<1e-20){ + return 0.0; + }else{ + return ((n_-1)*m4_) / (m2_*m2_); + } + } private: Real mean_; diff --git a/modules/img/alg/tests/test_stat.cc b/modules/img/alg/tests/test_stat.cc index 592d00c9a907d591be0999790490471af88ce4da..9c9694a4caace6c7b79c14fd9d2fc2c9a1b57778 100644 --- a/modules/img/alg/tests/test_stat.cc +++ b/modules/img/alg/tests/test_stat.cc @@ -64,7 +64,7 @@ void test() { BOOST_CHECK_CLOSE(stat.GetKurtosis(),Real(1.77),Real(0.01)); - StatAccumulator acc; + StatAccumulator<> acc; for(int u=0;u<3;++u) { for(int v=0;v<3;++v) { acc(val[u][v]); @@ -75,13 +75,13 @@ void test() { BOOST_CHECK_CLOSE(acc.GetSkewness()+0.5,Real(0.5),Real(0.0001)); BOOST_CHECK_CLOSE(acc.GetKurtosis(),Real(1.77),Real(0.0001)); - StatAccumulator acc1,acc2,acc3; + StatAccumulator<> acc1,acc2,acc3; for(int u=0;u<3;++u) { acc1(val[u][0]); acc2(val[u][1]); acc3(val[u][2]); } - StatAccumulator acc_c=acc1+acc2+acc3; + StatAccumulator<> acc_c=acc1+acc2+acc3; BOOST_CHECK_CLOSE(acc_c.GetMean(),Real(5.0),Real(0.0001)); BOOST_CHECK_CLOSE(acc_c.GetStandardDeviation(),Real(2.58198889747),Real(0.0001)); BOOST_CHECK_CLOSE(acc_c.GetSkewness()+0.5,Real(0.5),Real(0.0001));