#include #include #include #include using namespace std; namespace icl{ // {{{ uniform Random // this anonymous namespace holds utiliy functions, that are used only here namespace { template void uniform_image_random(Img *image, const Range &range, bool roiOnly){ for(int c=0;cgetChannels();++c){ ImgIterator it = roiOnly ? image->getROIIterator(c) : image->getIterator(c); while(it.inRegion()){ *it++ = clipped_cast( random(range.minVal, range.maxVal) ); } } } template void gaussian_image_random(Img *image,double mean, double var, const Range &range, bool roiOnly){ for(int c=0;cgetChannels();++c){ ImgIterator it = roiOnly ? image->getROIIterator(c) : image->getIterator(c); while(it.inRegion()){ *it++ = clipped_cast( gaussRandom(mean,var,range) ); } } } } void random(ImgBase *poImage, const Range &range, bool roiOnly){ ICLASSERT_RETURN( poImage ); switch(poImage->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) case depth##D: uniform_image_random(poImage->asImg(),range,roiOnly); break; ICL_INSTANTIATE_ALL_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } } // }}} // {{{ gaussian random void gaussRandom(ImgBase *poImage, double mean, double var, const Range &minAndMax, bool roiOnly){ ICLASSERT_RETURN( poImage ); switch(poImage->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) case depth##D: gaussian_image_random(poImage->asImg(),mean,var,minAndMax,roiOnly); break; ICL_INSTANTIATE_ALL_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } } //-------------------------------------------------------------------------- double gaussRandom(double mu, double sigma){ static bool haveNextGaussian = false; static double nextGaussian = 0; if(haveNextGaussian){ haveNextGaussian = false; return nextGaussian*sigma + mu; } else{ double v1(0), v2(0), s(0); do{ v1 = 2 * random(1.0)-1; v2 = 2 * random(1.0)-1; s = v1*v1 + v2*v2; }while(s>=1 || s == 0); double fac = sqrt(-2.0*log(s)/s); nextGaussian = v2 * fac; haveNextGaussian = true; return v1 * fac * sigma + mu; } } // }}} // {{{ mean namespace{ template double channel_mean(const Img &image, int channel, bool roiOnly){ double sum = 0; if(roiOnly && !image.hasFullROI()){ ConstImgIterator it = image.getROIIterator(channel); while(it.inRegion()){ sum += *it; } return sum/image.getROISize().getDim(); }else{ return mean(image.getData(channel),image.getData(channel)+image.getDim()); } } #ifdef WITH_IPP_OPTIMIZATION template<> double channel_mean(const Img8u &image, int channel, bool roiOnly){ icl64f m=0; ippiMean_8u_C1R(roiOnly ? image.getROIData(channel) : image.getData(channel),image.getLineStep(), roiOnly ? image.getROISize() : image.getROISize(),&m); return m; } template<> double channel_mean(const Img16s &image, int channel, bool roiOnly){ icl64f m=0; ippiMean_16s_C1R(roiOnly ? image.getROIData(channel) : image.getData(channel),image.getLineStep(), roiOnly ? image.getROISize() : image.getROISize(),&m); return m; } template<> double channel_mean(const Img32f &image, int channel, bool roiOnly){ icl64f m=0; ippiMean_32f_C1R(roiOnly ? image.getROIData(channel) : image.getData(channel),image.getLineStep(), roiOnly ? image.getROISize() : image.getROISize(),&m, ippAlgHintAccurate); return m; } #endif } vector mean(const ImgBase *poImg, int iChannel, bool roiOnly){ FUNCTION_LOG(""); vector vecMean; ICLASSERT_RETURN_VAL(poImg,vecMean); int firstChannel = iChannel<0 ? 0 : iChannel; int lastChannel = iChannel<0 ? poImg->getChannels()-1 : firstChannel; switch(poImg->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) \ case depth##D: \ for(int i=firstChannel;i<=lastChannel;++i){ \ vecMean.push_back(channel_mean(*poImg->asImg(),i,roiOnly)); \ } \ break; ICL_INSTANTIATE_ALL_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } return vecMean; } // }}} // {{{ variance namespace{ template double channel_var_with_mean(const Img &image, int channel,double mean,bool empiricMean, bool roiOnly){ register double sum = 0; register double d = 0; if(roiOnly && !image.hasFullROI()){ ConstImgIterator it = image.getROIIterator(channel); while(it.inRegion()){ d = *it - mean; sum += d*d; ++it; } return sum/(empiricMean ? iclMax(double(image.getROISize().getDim()-1),double(1)) : image.getROISize().getDim()); }else{ return variance(image.getData(channel),image.getData(channel)+image.getDim(),mean,empiricMean); } } // no IPP function available with given mean } vector variance(const ImgBase *poImg, const vector &mean, bool empiricMean, int iChannel, bool roiOnly){ FUNCTION_LOG(""); vector vecVar; ICLASSERT_RETURN_VAL(poImg,vecVar); int firstChannel = iChannel<0 ? 0 : iChannel; int lastChannel = iChannel<0 ? poImg->getChannels()-1 : firstChannel; switch(poImg->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) \ case depth##D: \ for(int i=firstChannel,j=0;i<=lastChannel;++i,++j){ \ ICLASSERT_RETURN_VAL(j<(int)mean.size(),vecVar); \ vecVar.push_back(channel_var_with_mean(*poImg->asImg(),i,mean[j],empiricMean,roiOnly)); \ } \ break; ICL_INSTANTIATE_ALL_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } return vecVar; } /// Compute the variance value of an image a \ingroup MATH /** @param poImg input imge @param iChannel channel index (-1 for all channels) @return The variance value form the vector */ vector variance(const ImgBase *poImg, int iChannel, bool roiOnly){ return variance(poImg,mean(poImg,iChannel,roiOnly),true,iChannel,roiOnly); } // }}} // {{{ std-deviation vector stdDeviation(const ImgBase *poImage, int iChannel, bool roiOnly){ vector v = variance(poImage,iChannel,roiOnly); for(unsigned int i=0;i stdDeviation(const ImgBase *poImage, const vector mean, bool empiricMean, int iChannel, bool roiOnly){ vector v = variance(poImage,mean,empiricMean, iChannel,roiOnly); for(unsigned int i=0;i > meanAndStdDev(const ImgBase *image, int iChannel, bool roiOnly){ vector channelMeans = mean(image,iChannel,roiOnly); vector channelStdDevs = stdDeviation(image,channelMeans,true,iChannel,roiOnly); vector< pair > md(channelMeans.size()); for(unsigned int i=0;i void compute_default_histo_256(const Img &image, int c, vector &h, bool roiOnly){ ICLASSERT_RETURN(h.size() == 256); if(roiOnly && !image.hasFullROI()){ ConstImgIterator it = image.getROIIterator(c); for(;it.inRegion();++it){ h[clipped_cast(*it)]++; } }else{ const T* p = image.getData(c); const T* pEnd = p+image.getDim(); while(p(*p++)]++; } } } template inline void histo_entry(T v, double m, vector &h, unsigned int n, double r){ // todo check 1000 times h[ ceil( n*(v-m)/(r+1)) ]++; // h[ ceil( n*(v-m)/r) ]++; problem at v=255 } template void compute_complex_histo(const Img &image, int c, vector &h, bool roiOnly){ const Range range = image.getMinMax(c); double r = range.getLength(); unsigned int n = h.size(); if(roiOnly && !image.hasFullROI()){ ConstImgIterator it = image.getROIIterator(c); for(;it.inRegion();++it){ histo_entry(*it,range.minVal,h,n,r); } }else{ const T* p = image.getData(c); const T* pEnd = p+image.getDim(); while(p void compute_default_histo_256(const Img##D &image, int c, vector &h, bool roiOnly){ \ ICLASSERT_RETURN(h.size() == 256); \ static icl32s levels[257]; \ static bool first = true; \ if(first){ \ for(int i=0;i<257;levels[i]=i,i++); \ first = false; \ } \ \ if(roiOnly && !image.hasFullROI()){ \ ippiHistogramEven_##D##_C1R(image.getROIData(c),image.getLineStep(),image.getROISize(),&h[0], levels, 257, 0,256); \ }else{ \ ippiHistogramEven_##D##_C1R(image.getData(c),image.getLineStep(),image.getSize(),&h[0], levels, 257, 0,256); \ } \ } COMPUTE_DEFAULT_HISTO_256_TEMPLATE(8u) COMPUTE_DEFAULT_HISTO_256_TEMPLATE(16s) #define COMPUTE_COMPLEX_HISTO_TEMPLATE(D) \ template<> void compute_complex_histo(const Img##D &image, int c, vector &h, bool roiOnly){ \ Range range = image.getMinMax(c); \ double l = range.getLength(); \ vector levels(h.size()+1); \ for(unsigned int i=0;i void compute_channel_histo(const Img &image, int c, vector &h, bool roiOnly){ if(image.getFormat() != formatMatrix && h.size() == 256){ compute_default_histo_256(image,c,h,roiOnly); }else{ compute_complex_histo(image,c,h,roiOnly); } } } vector channelHisto(const ImgBase *image,int channel, int levels, bool roiOnly){ ICLASSERT_RETURN_VAL(image && image->getChannels()>channel, vector()); ICLASSERT_RETURN_VAL(levels > 1,vector()); vector h(levels); switch(image->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) case depth##D: compute_channel_histo(*image->asImg(),channel,h,roiOnly); break; ICL_INSTANTIATE_ALL_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } return h; } vector > hist(const ImgBase *image, int levels, bool roiOnly){ ICLASSERT_RETURN_VAL(image && image->getChannels(), vector >()); vector > h(image->getChannels()); for(int i=0;igetChannels();i++){ h[i] = channelHisto(image,i,levels,roiOnly); } return h; } // }}} } //namespace icl