/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2010 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLFilter/src/UnaryOp.cpp ** ** Module : ICLFilter ** ** Authors: Christof Elbrechter ** ** ** ** ** ** Commercial License ** ** ICL can be used commercially, please refer to our website ** ** www.iclcv.org for more details. ** ** ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the ** ** GNU General Public License version 3.0 as published by the ** ** Free Software Foundation and appearing in the file LICENSE.GPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the GNU General Public License ** ** version 3.0 requirements will be met: ** ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** *********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_IPP #include #endif #include #include #include #include namespace icl{ UnaryOp::UnaryOp():m_poMT(0),m_buf(0){}; UnaryOp::UnaryOp(const UnaryOp &other): m_poMT(0),m_oROIHandler(other.m_oROIHandler),m_buf(0){} UnaryOp &UnaryOp::operator=(const UnaryOp &other){ m_oROIHandler = other.m_oROIHandler; ICL_DELETE( m_poMT ); return *this; } UnaryOp::~UnaryOp(){ ICL_DELETE( m_poMT ); ICL_DELETE( m_buf ); } const ImgBase *UnaryOp::apply(const ImgBase *src){ apply(src,&m_buf); return m_buf; } void UnaryOp::applyMT(const ImgBase *poSrc, ImgBase **ppoDst, unsigned int nThreads){ ICLASSERT_RETURN( nThreads > 0 ); ICLASSERT_RETURN( poSrc ); if(nThreads == 1){ apply(poSrc,ppoDst); return; } if(!prepare (ppoDst, poSrc)) return; bool ctr = getClipToROI(); bool co = getCheckOnly(); setClipToROI(false); setCheckOnly(true); const std::vector srcs = ImageSplitter::split(poSrc,nThreads); std::vector dsts = ImageSplitter::split(*ppoDst,nThreads); MultiThreader::WorkSet works(nThreads); for(unsigned int i=0;i(dsts[i])); } if(!m_poMT){ m_poMT = new MultiThreader(nThreads); }else{ if(m_poMT->getNumThreads() != (int)nThreads){ delete m_poMT; m_poMT = new MultiThreader(nThreads); } } (*m_poMT)( works ); for(unsigned int i=0;i paramlist; typedef UnaryOp* (*creator)(const paramlist ¶ms); struct Creator{ Creator(creator c=0, const std::string &n="", const std::string &s=""):c(c),s(s),n(n){} creator c; std::string s; // syntax std::string n; // name operator const std::string&() const{ return n; } UnaryOp *operator()(const paramlist ¶ms) const { return c(params); } }; static std::map CREATORS; UnaryOp *create_generic_conv(const paramlist ¶msIn){ paramlist params = paramsIn; ICLASSERT_THROW(params.size() >= 2,ICLException(str(__FUNCTION__)+":param list must have at least two elements")); Size kernelSize = parse(params[0]); ICLASSERT_THROW(kernelSize.getDim()>=1,ICLException(str(__FUNCTION__)+":kernel dimension is <=0")) params.erase(params.begin()); std::vector kernelValues = parseVec(params); ICLASSERT_THROW(kernelSize.getDim() == (int)kernelValues.size(),ICLException(str(__FUNCTION__)+":kernel dimension is "+ str(kernelSize.getDim())+" kernel value list's size is "+ str(kernelValues.size()))); return new ConvolutionOp(ConvolutionKernel(kernelValues.data(),kernelSize)); } template UnaryOp *create_fixed_conv(const paramlist ¶ms){ ICLASSERT_THROW(!params.size(),ICLException(str(__FUNCTION__)+": no parameters allowed here")); return new ConvolutionOp(ConvolutionKernel(t)); } template UnaryOp *create_fixed_morph(const paramlist ¶ms){ Size kernelSize = params.size()?parse(params.front()):Size(3,3); ICLASSERT_THROW(kernelSize.getDim()>=1,ICLException(str(__FUNCTION__)+": kernel dimension is <=0")); return new MorphologicalOp(t,kernelSize); } UnaryOp *create_median(const paramlist ¶ms){ Size kernelSize = params.size()?parse(params.front()):Size(3,3); ICLASSERT_THROW(kernelSize.getDim()>=1,ICLException(str(__FUNCTION__)+": kernel dimension is <=0")); return new MedianOp(kernelSize); } struct PassOp:public UnaryOp{ void apply(const ImgBase *src, ImgBase **dst){ ICLASSERT(dst); const_cast(src)->deepCopy(dst); (*dst)->setFullROI(); } static UnaryOp *create(const paramlist ¶ms){ ICLASSERT_THROW(!params.size(),ICLException(str(__FUNCTION__)+": no parameters allowed here")); return new PassOp; } }; UnaryOp *create_rotate(const paramlist ¶ms){ ICLASSERT_THROW(params.size() == 1,ICLException(str(__FUNCTION__)+": params list size must be 1 here")); float angle = parse(params.front()); return new RotateOp(angle); } UnaryOp *create_scale(const paramlist ¶ms){ ICLASSERT_THROW(params.size() == 1 ||params.size() == 2 || params.size() == 3,ICLException(str(__FUNCTION__)+": params list size must be 1,2 or 3 here")); float fx = parse(params[0]); if(fx > 5) throw ICLException(str(__FUNCTION__)+": scale factor fx must not be higher than 5"); float fy = params.size()>1 ? parse(params[1]) : fx; if(fy > 5) throw ICLException(str(__FUNCTION__)+": scale factor fy must not be higher than 5"); scalemode sm = interpolateNN; if(params.size()==3 && params[2] == "NN"){} else if(params.size()==3 && params[2] == "LIN"){sm = interpolateLIN;} else if(params.size()==3 && params[2] == "RA"){sm = interpolateRA;} else if(params.size()==3) throw ICLException(str(__FUNCTION__)+": 3rd param must be one of NN, LIN or RA"); return new ScaleOp(fx,fy,sm); } #ifdef HAVE_IPP UnaryOp *create_canny(const paramlist ¶ms){ ICLASSERT_THROW(params.size() == 2 ||params.size() == 3,ICLException(str(__FUNCTION__)+": params list size must be 2 or 3 here")); float low = parse(params[0]); float hi = parse(params[1]); bool preblur = params.size()==3?parse(params[2]):false; return new CannyOp(low,hi,preblur); } #endif template UnaryOp *create_any(const paramlist ¶ms){ ICLASSERT_THROW(!params.size(),ICLException(str(__FUNCTION__)+": no params allowed here")); return new T; } UnaryOp *create_gabor(const paramlist ¶ms){ ICLASSERT_THROW(params.size()<=6,ICLException(str(__FUNCTION__)+": max 6. params allowed")); Size kernelSize(5,5); float lambda = 1; float theta = 1; float psi = 1; float sigma = 1; float gamma = 1; if(params.size() > 0){ kernelSize = parse(params[0]); if(kernelSize.getDim() < 1) throw ICLException(str(__FUNCTION__)+": kernel dimension must be > 0"); } if(params.size() > 1)lambda = parse(params[1]); if(params.size() > 2)theta = parse(params[2]); if(params.size() > 3)psi = parse(params[3]); if(params.size() > 4)sigma = parse(params[4]); if(params.size() > 5)gamma = parse(params[5]); return new GaborOp(kernelSize,std::vector(1,lambda),std::vector(1,theta), std::vector(1,psi),std::vector(1,sigma),std::vector(1,gamma)); } UnaryOp *create_compare(const paramlist ¶ms){ ICLASSERT_THROW(params.size()<=4,ICLException(str(__FUNCTION__)+": max 3. params allowed")); UnaryCompareOp::optype ot = UnaryCompareOp::lteq; icl64f value = 127; icl64f toll = 0; if(params.size()>0){ if(params[0] == "<") ot = UnaryCompareOp::lt; else if(params[0] == "<") ot = UnaryCompareOp::lt; else if(params[0] == ">") ot = UnaryCompareOp::gt; else if(params[0] == "<=") ot = UnaryCompareOp::lteq; else if(params[0] == ">=") ot = UnaryCompareOp::gteq; else if(params[0] == "==") ot = UnaryCompareOp::eq; } if(params.size()>1){ value = parse(params[1]); } if(params.size()>2){ toll = parse(params[2]); } return new UnaryCompareOp(ot,value,toll); } UnaryOp *create_localThresh(const paramlist ¶ms){ ICLASSERT_THROW(params.size()<=4,ICLException(str(__FUNCTION__)+": max 3. params allowed")); unsigned int maskSize=10; int globalThreshold=0; float gammaSlope=0; if(params.size()>0) maskSize = parse(params[0]); if(!maskSize) throw ICLException(str(__FUNCTION__)+": masksize is 0"); if(params.size()>1) globalThreshold = parse(params[1]); if(params.size()>2) gammaSlope = parse(params[2]); return new LocalThresholdOp(maskSize,globalThreshold,gammaSlope); } void static_init(){ static bool first = true; if(!first)return; first = false; CREATORS["copy"] = Creator(PassOp::create,"copy",""); // convolution op #define FIXED_CONV_CREATOR_ENTRY(X) \ CREATORS[#X] = Creator(create_fixed_conv,#X,"") FIXED_CONV_CREATOR_ENTRY(gauss3x3); FIXED_CONV_CREATOR_ENTRY(laplace3x3); FIXED_CONV_CREATOR_ENTRY(sobelX3x3); FIXED_CONV_CREATOR_ENTRY(sobelY3x3); FIXED_CONV_CREATOR_ENTRY(gauss5x5); FIXED_CONV_CREATOR_ENTRY(laplace5x5); FIXED_CONV_CREATOR_ENTRY(sobelX5x5); FIXED_CONV_CREATOR_ENTRY(sobelY5x5); CREATORS["conv"] = Creator(create_generic_conv,"conv", "size,comma sep. value list"); #undef FIXED_CONV_CREATOR_ENTRY // morphological op #define FIXED_MORPH_CREATOR_ENTRY(X) \ CREATORS[#X] = Creator(create_fixed_morph,#X,"kernel-size WxH=3x3"); FIXED_MORPH_CREATOR_ENTRY(dilate); FIXED_MORPH_CREATOR_ENTRY(erode); FIXED_MORPH_CREATOR_ENTRY(dilate3x3); FIXED_MORPH_CREATOR_ENTRY(erode3x3); FIXED_MORPH_CREATOR_ENTRY(dilateBorderReplicate); FIXED_MORPH_CREATOR_ENTRY(erodeBorderReplicate); FIXED_MORPH_CREATOR_ENTRY(openBorder); FIXED_MORPH_CREATOR_ENTRY(closeBorder); FIXED_MORPH_CREATOR_ENTRY(tophatBorder); FIXED_MORPH_CREATOR_ENTRY(blackhatBorder); FIXED_MORPH_CREATOR_ENTRY(gradientBorder); #undef FIXED_MORPH_CREATOR_ENTRY // median CREATORS["median"] = Creator(create_median,"median","kernel-size WxH=3x3"); CREATORS["rotate"] = Creator(create_rotate,"rotate","angle in degree"); CREATORS["scale"] = Creator(create_scale,"scale","fx (<5),fy (<5)=fx,interplation=NN (one of RA,LIN or NN)"); #ifdef HAVE_IPP CREATORS["canny"] = Creator(create_canny,"canny","lowThresh,highThresh,preblur=false (true or false)"); #endif CREATORS["chamfer"] = Creator(create_any,"chamfer",""); CREATORS["gabor"] = Creator(create_gabor,"gabor","kernelSize=(5,5),lambda=1,theta=1,psi=1,sigma=1,gamma=1"); CREATORS["compare"] = Creator(create_compare,"compare","op=>= (one of <,<=,>,>= or ==), value=127, tollerance=0"); CREATORS["localThresh"] = Creator(create_localThresh,"localThresh","maskSize=10,globalThreshold=0,gammaSlope=0"); } } UnaryOp *UnaryOp::fromString(const std::string &definition) throw (ICLException){ unary_op_from_string::static_init(); bool hasParams = true; if(!definition.size()) throw ICLException(str(__FUNCTION__)+": empty defintion string"); std::string::size_type a = definition.find('('); std::string name; std::vector plist; if(a == std::string::npos){ hasParams = false; name = definition; }else{ if(definition[definition.size()-1] != ')') throw ICLException(str(__FUNCTION__)+": missing closing ')' in definition ["+definition+"]"); name = definition.substr(0,a); std::string ps = definition.substr(a+1); plist = tok(ps.substr(0,ps.size()-1),","); } std::map::iterator it=unary_op_from_string::CREATORS.find(name); if(it == unary_op_from_string::CREATORS.end()) throw ICLException(str(__FUNCTION__)+": no op found for given specifier ["+name+"]"); UnaryOp * op = it->second(plist); if(!op) throw ICLException("wrong parameter list syntax"); return op; } std::string UnaryOp::getFromStringSyntax(const std::string &opSpecifier) throw (ICLException){ unary_op_from_string::static_init(); std::map::iterator it=unary_op_from_string::CREATORS.find(opSpecifier); if(it == unary_op_from_string::CREATORS.end()) throw ICLException(str(__FUNCTION__)+": no op found for given specifier ["+opSpecifier+"]"); return it->second.s; } std::vector UnaryOp::listFromStringOps(){ unary_op_from_string::static_init(); std::vector v(unary_op_from_string::CREATORS.size()); int i=0; for(std::map::iterator it=unary_op_from_string::CREATORS.begin(); it!=unary_op_from_string::CREATORS.end();++it){ v[i++] = it->second; } return v; } void UnaryOp::applyFromString(const std::string &definition, const ImgBase *src, ImgBase **dst) throw (ICLException){ unary_op_from_string::static_init(); UnaryOp *op = fromString(definition); if(!op) throw ICLException(str(__FUNCTION__)+": no op found for given definition string ["+definition+"]"); op->apply(src,dst); delete op; } }