#include #include namespace icl { #ifdef HAVE_IPP namespace{ template inline void ippiCall(const Img *src1, const Img *src2, Img32f *dst){ // {{{ open for (int c=src1->getChannels()-1; c >= 0; --c) { ippiFunc (src1->getROIData (c), src1->getLineStep(), src1->getROISize(), src2->getROIData (c), src2->getLineStep(), src2->getROISize(), dst->getROIData (c), dst->getLineStep()); } } // }}} template struct ProximityOpTemplate{ // {{{ open static void apply(const Img *poSrc1,const Img *poSrc2, Img32f *poDst){ (void)poSrc1; (void)poSrc2; (void)poDst; } }; // }}} // {{{ ProximityOpTemplate specialization (each calling a specific ipp function) /** Description: the following macro costructs a full template spcialization for the ProximityOpTemplate class. The parameters contain all necessary information for the ICL variable names as well as the IPP function name definition. the ipp function name, inserted into the ippCall function template above, is constructed as follows: ippi___C1R(..) where -IPPOT_A is the first part of operation description: "SqrDistance" or "CrossCorr" -IPPAM specifies the ipp apply mode "Full", "Valid" or "Same" -IPPOT_B is the second part of the operation description: "Norm" or "NormLevel" -IPPDEPTH specifies ipps depth token "32f" or "8u32f" the other macro parameters with ICL-prefix are used the build the correct ICL enum names, used the for the template specialization. */ #define CREATE_TEMPLATE(ICLDEPTH,ICLOT,ICLAM,IPPOT_A,IPPAM,IPPOT_B,IPPDEPTH) \ template<> struct ProximityOpTemplate { \ static void apply(const Img *src1,const Img *src2, Img32f *dst){ \ ippiCall(src1,src2,dst); \ } \ } #define CREATE_TEMPLATE_ALL_AM(ICLDEPTH,ICLOT,IPPOT_A,IPPOT_B,IPPDEPTH) \ CREATE_TEMPLATE(ICLDEPTH,ICLOT,full,IPPOT_A,Full,IPPOT_B,IPPDEPTH); \ CREATE_TEMPLATE(ICLDEPTH,ICLOT,same,IPPOT_A,Same,IPPOT_B,IPPDEPTH); \ CREATE_TEMPLATE(ICLDEPTH,ICLOT,valid,IPPOT_A,Valid,IPPOT_B,IPPDEPTH) CREATE_TEMPLATE_ALL_AM(8u,sqrDistance,SqrDistance,Norm,8u32f); CREATE_TEMPLATE_ALL_AM(32f,sqrDistance,SqrDistance,Norm,32f); CREATE_TEMPLATE_ALL_AM(8u,crossCorr,CrossCorr,Norm,8u32f); CREATE_TEMPLATE_ALL_AM(32f,crossCorr,CrossCorr,Norm,32f); CREATE_TEMPLATE_ALL_AM(8u,crossCorrCoeff,CrossCorr,NormLevel,8u32f); CREATE_TEMPLATE_ALL_AM(32f,crossCorrCoeff,CrossCorr,NormLevel,32f); #undef CREATE_TEMPLATE #undef CREATE_TEMPLATE_ALL_AM // }}} template void proximity_apply(const Img *poSrc1, const Img *poSrc2, Img32f *poDst, ProximityOp::optype ot, ProximityOp::applymode am){ // {{{ open switch(ot){ case ProximityOp::sqrDistance: switch(am){ case ProximityOp::full: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::same: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::valid: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; } break; case ProximityOp::crossCorr: switch(am){ case ProximityOp::full: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::same: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::valid: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; } break; case ProximityOp::crossCorrCoeff: switch(am){ case ProximityOp::full: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::same: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; case ProximityOp::valid: ProximityOpTemplate::apply(poSrc1,poSrc2,poDst); break; } break; } } // }}} }// anonymous namespace void ProximityOp::apply(const ImgBase *poSrc1, const ImgBase *poSrc2, ImgBase **ppoDst){ // {{{ open ICLASSERT_RETURN( poSrc1 && poSrc2 ); ICLASSERT_RETURN( poSrc1->getChannels() == poSrc2->getChannels() ); ICLASSERT_RETURN( poSrc1->getDepth() == poSrc2->getDepth() ); if(poSrc1->getDepth() != depth8u && poSrc1->getDepth() != depth32f){ poSrc1 = m_poImageBuffer = poSrc1->convert(m_poImageBuffer); poSrc2 = m_poTemplateBuffer = poSrc2->convert(m_poTemplateBuffer); } /// set up dst image in depth, channel count and size ensureDepth(ppoDst,depth32f); (*ppoDst)->setChannels(poSrc1->getChannels()); switch(m_eApplyMode){ case full: (*ppoDst)->setSize(poSrc1->getSize()+poSrc2->getSize()-Size(1,1)); break; case same: (*ppoDst)->setSize(poSrc1->getSize()); break; case valid:(*ppoDst)->setSize(poSrc1->getSize()-poSrc2->getSize()+Size(1,1)); break; } switch(poSrc1->getDepth()){ case depth8u: proximity_apply(poSrc1->asImg(),poSrc2->asImg(),(*ppoDst)->asImg(), m_eOpType, m_eApplyMode); break; case depth32f: proximity_apply(poSrc1->asImg(),poSrc2->asImg(),(*ppoDst)->asImg(), m_eOpType, m_eApplyMode); break; default: ICL_INVALID_DEPTH; } } // }}} #endif }