/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLFilter/src/ICLFilter/WarpOp.cpp ** ** Module : ICLFilter ** ** Authors: Christof Elbrechter, Sergius Gaulik ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** 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 #ifdef ICL_HAVE_OPENCL #include #endif #include using namespace icl::utils; using namespace icl::core; namespace icl{ namespace filter{ #ifdef ICL_HAVE_OPENCL struct WarpOp::CLWarp { CLProgram program; CLImage2D input; CLImage2D output; CLImage2D warpX, warpY; CLKernel kernel; Size mapSize; CLWarp() { static const char *k = ( "__kernel void warp(const unsigned int mode, \n" " __read_only image2d_t warpX, \n" " __read_only image2d_t warpY, \n" " __read_only image2d_t in, \n" " __write_only image2d_t out) { \n" " const int x = get_global_id(0); \n" " const int y = get_global_id(1); \n" " const int w = get_global_size(0); \n" " const int h = get_global_size(1); \n" " if(x && y && xgetWidth(); int h = src->getHeight(); if (mode == interpolateNN) filterMode = CL_FILTER_NEAREST; else if (mode == interpolateLIN) filterMode = CL_FILTER_LINEAR; else { ERROR_LOG("region average interpolation mode does not work here!"); return; } if (warpMap[0].getSize() != mapSize) setWarpMap(warpMap); input = program.createImage2D("r", w, h, src->getDepth()); output = program.createImage2D("w", w, h, src->getDepth()); for (int i = 0; i < src->getChannels(); i++) { input.write(src->getDataPtr(i)); kernel.setArgs(filterMode, warpX, warpY, input, output); kernel.apply(w, h, 0); output.read(dst->getDataPtr(i)); } } }; #endif template T interpolate_pixel_nn(float x, float y, const Channel &src){ if(x < 0) return T(0); return src(round(x),round(y)); } template T interpolate_pixel_lin(float x, float y, const Channel &src){ float fX0 = x - floor(x), fX1 = 1.0 - fX0; float fY0 = y - floor(y), fY1 = 1.0 - fY0; int xll = (int) x; int yll = (int) y; const T* pLL = &src(xll,yll); float a = *pLL; // a b float b = *(++pLL); // c d pLL += src.getWidth(); float d = *pLL; float c = *(--pLL); return fX1 * (fY1*a + fY0*c) + fX0 * (fY1*b + fY0*d); } template static inline void apply_warp_2(const Channel32f warpMap[2], const Channel &src, Channel &dst, const Size &size, T (*interpolator)(float x, float y, const Channel &src)){ for(int x=0;x static void apply_warp(const Channel32f warpMap[2], const Img&src, Img &dst, scalemode mode){ for(int c=0;c s = src[c]; Channel d = dst[c]; if(mode == interpolateNN){ apply_warp_2(warpMap,s,d,s.getSize(),interpolate_pixel_nn); }else if(mode == interpolateLIN){ apply_warp_2(warpMap,s,d,s.getSize(),interpolate_pixel_lin); }else{ ERROR_LOG("region average interpolation mode does not work here!"); return; } } } #ifdef ICL_HAVE_IPP template<> void apply_warp(const Channel32f warpMap[2], const Img &src, Img &dst, scalemode mode){ for(int c=0;c void apply_warp(const Channel32f warpMap[2], const Img &src, Img &dst, scalemode mode){ for(int c=0;c and #endif void prepare_warp_table_inplace(Img32f &warpMap){ const Rect r = warpMap.getImageRect(); Channel32f cs[2]; warpMap.extractChannels(cs); const Size size = warpMap.getSize(); for(int x=0;xsetWarpMap(m_warpMap); #endif } void WarpOp::setAllowWarpMapScaling(bool allow){ m_allowWarpMapScaling = allow; } void WarpOp::apply(const ImgBase *src, ImgBase **dst){ ICLASSERT_RETURN(src); ICLASSERT_RETURN(dst); ICLASSERT_RETURN(src != *dst); ICLASSERT_RETURN(m_warpMap.getSize() != Size::null); if(!src->hasFullROI()){ ERROR_LOG("warp op does currently not support ROI"); return; } if(!UnaryOp::prepare(dst,src->getDepth(),src->getSize(), src->getFormat(),src->getChannels(), src->getROI(),src->getTime())){ ERROR_LOG("unable to prepare destination image (returning)"); return; } Channel32f cwm[2]; if(src->getSize() != m_warpMap.getSize()){ if(m_allowWarpMapScaling){ if(m_scaledWarpMap.getSize() != src->getSize()){ m_scaledWarpMap.setSize(src->getSize()); m_warpMap.scaledCopy(&m_scaledWarpMap); prepare_warp_table_inplace(m_scaledWarpMap); } m_scaledWarpMap.extractChannels(cwm); }else{ ERROR_LOG("warp map size and image size are not equal\n" "warp map can be scaled using\n" "setAllowWarpMapScaling(true)"); return; } }else{ m_warpMap.extractChannels(cwm); } #ifdef ICL_HAVE_OPENCL // the written kernel of CLWarp supports only uint values and linear interpolation; // TODO: create CLSampler for diffrent interpolation methods if (m_tryUseOpenCL && src->getDepth() == depth8u && m_scaleMode == interpolateLIN) { m_clWarp->apply(cwm, src, *dst, m_scaleMode); return; } #endif switch(src->getDepth()){ #define ICL_INSTANTIATE_DEPTH(D) \ case depth##D: \ apply_warp(cwm,*src->asImg(), \ *(*dst)->asImg(),m_scaleMode); \ break; ICL_INSTANTIATE_ALL_DEPTHS; default: ICL_INVALID_DEPTH; #undef ICL_INSTANTIATE_DEPTH } } void WarpOp::setTryUseOpenCL(bool on){ m_tryUseOpenCL = on; } } // namespace filter }