#include "iclLocalThresholdOp.h" #include "iclSize.h" #include "iclMacros.h" namespace icl{ void create_roi_size_image(const Size &s, int r, Img32s& dst){ // {{{ open dst.setSize(s); dst.setChannels(1); ICLASSERT_RETURN( s.width > 2*r && s.height > 2*r ); int *p = dst.getData(0); int w = s.width; int h = s.height; int r1 = r+1; int rr1 = r+r+1; int dim = rr1*rr1; // corners: // top left / right for(int y=0;y>>>>>>> left } for(int x=w-r;x> right } // center for(int x=r,xEnd=w-r;x>>>>>>> left } for(int x=w-r;x> right } // center for(int x=r,xEnd=w-r;x>>>>>>> left } for(int x=w-r;x> right } } for(int y=r,yEnd=h-r; ym_fGammaSlope = gammaSlope; } // }}} template void local_threshold_algorithm(const Img *src, Img* dst, Img *integralImage, int *roiSizeImage, int globalThreshold, int r, float gammaSlope){ // {{{ open /********************************************************* *** local Threshold algorithm ************************** **********************************************************/ /* r=2 .C....A... ..+++++... ..+++++... ..++X++... ..+++++... .B++++D... .......... |+| = D - A - B + C */ Size s = src->getSize(); const int w = s.width; const int h = s.height; const int r1 = r+1; const int r_1 = -r-1; int yu, yl, xr, xl; T2 thresh; int iw =w+2*(r1); // int ih =h+2*(r1); for(int channel=0;channelgetChannels();++channel){ const T *S = src->getData(channel); T *D = dst->getData(channel); T2 *I = integralImage->getData(channel)+(r1+r1*iw); if(gammaSlope){ /** using function f(x) = m*x + b (with clipping) with m = gammaSlope k = localThresh+globalThresh f(k) = 128 f(x) = clip( m(x-k)+128 , 0 , 255 ) */ for(int y=0;ygetSize() != Size::null ); ICLASSERT_RETURN( src->getChannels() ); ICLASSERT_RETURN( dst ); ICLASSERT_RETURN( src != *dst ); // cut the roi of src if set if(!(src->hasFullROI())){ src->deepCopy(&m_poROIImage); src = m_poROIImage; } // prepare the destination image if(!prepare(dst,src)){ ERROR_LOG("prepare failure in LocalThreshold! ??"); } // prepare the roi size image if(m_oROISizeImage.getSize().isNull() || m_uiROISizeImagesMaskSize != m_uiMaskSize || m_oROISizeImage.getSize() != src->getSize() ) { create_roi_size_image(src->getSize(),m_uiMaskSize,m_oROISizeImage); m_uiROISizeImagesMaskSize = m_uiMaskSize; } // create the integral images with border 1+roiSize switch(src->getDepth()){ case depth8u:{ // IntegralImg::create(src->asImg(), m_uiMaskSize+1, &m_oIntegralImage); ImgBase *ii = &m_oIntegralImage; IntegralImgOp(m_uiMaskSize+1, depth32s).apply(src, &ii); local_threshold_algorithm(src->asImg(), (*dst)->asImg(), &m_oIntegralImage, m_oROISizeImage.getData(0), m_iGlobalThreshold, m_uiMaskSize, m_fGammaSlope); break; } case depth32f:{ //IntegralImg::create(src->asImg(), m_uiMaskSize+1, &m_oIntegralImageF); ImgBase *ii = &m_oIntegralImageF; IntegralImgOp(m_uiMaskSize+1, depth32f).apply(src, &ii); local_threshold_algorithm(src->asImg(), (*dst)->asImg(), &m_oIntegralImageF, m_oROISizeImage.getData(0), m_iGlobalThreshold, m_uiMaskSize, m_fGammaSlope); break; } default: ICL_INVALID_FORMAT; } } // }}} unsigned int LocalThresholdOp::getMaskSize() const{ return m_uiMaskSize; } int LocalThresholdOp::getGlobalThreshold() const{ return m_iGlobalThreshold; } float LocalThresholdOp::getGammaSlope() const{ return m_fGammaSlope; } }