OpenCV代码提取:remap函数的实现

2024-04-22 01:32

本文主要是介绍OpenCV代码提取:remap函数的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文转载自:http://blog.csdn.net/fengbingchun/article/details/51872436

图像重映射:即是把一个图像中一个位置的像素放置到另一个图像指定位置的过程。因为有时候源图像和目标图像并不总是一一对应的关系(目标图像的像素可能映射到源图像的非整数坐标上),所以有时候会需要做插值。

         描述映射过程:通过重映射来表达每个像素的位置(x,y):g(x,y) = f(h(x,y))

         其中:g()是目标图像,即重映射的结果;f()是源图像;h(x,y)是作用于(x,y)的映射方法函数。如h(x,y)=(I.cols-x,y),得到的目标图像将是按照x轴方向发生翻转。

         映射分为向前映射和向后映射。将输入映射到输出的向前映射,反正就是向后映射。即如果已知源图像到目标图像的坐标变换,即可以知道源图像的一点在变换后在目标图像的位置,称为向前映射。如果知道目标图像的一点在变换前在源图像上的位置,称为向后映射。向后映射比较直观,计算量小,OpenCV中经常使用的图像变换都是采用向后映射的方法来处理。但向后映射需要知道变换的反变换公式,但在有些变换比较复杂的场合,这个反变换是很难得到的。此时就需要采用前向映射的方法进行变换了。

这里对opencv中remap函数进行了提取目前支持uchar和float两种类型,经测试,与OpenCV3.1结果完全一致。

实现代码remap.hpp:

[cpp]  view plain copy
  1. // fbc_cv is free software and uses the same licence as OpenCV  
  2. // Email: fengbingchun@163.com  
  3.   
  4. #ifndef FBC_CV_REMAP_HPP_  
  5. #define FBC_CV_REMAP_HPP_  
  6.   
  7. /* reference: include/opencv2/imgproc.hpp 
  8.               modules/imgproc/src/imgwarp.cpp 
  9. */  
  10.   
  11. #include <typeinfo>  
  12. #include "core/mat.hpp"  
  13. #include "core/base.hpp"  
  14. #include "core/core.hpp"  
  15. #include "imgproc.hpp"  
  16. #include "resize.hpp"  
  17.   
  18. namespace fbc {  
  19.   
  20. const int INTER_REMAP_COEF_BITS = 15;  
  21. const int INTER_REMAP_COEF_SCALE = 1 << INTER_REMAP_COEF_BITS;  
  22.   
  23. static uchar NNDeltaTab_i[INTER_TAB_SIZE2][2];  
  24.   
  25. static float BilinearTab_f[INTER_TAB_SIZE2][2][2];  
  26. static short BilinearTab_i[INTER_TAB_SIZE2][2][2];  
  27.   
  28. static float BicubicTab_f[INTER_TAB_SIZE2][4][4];  
  29. static short BicubicTab_i[INTER_TAB_SIZE2][4][4];  
  30.   
  31. static float Lanczos4Tab_f[INTER_TAB_SIZE2][8][8];  
  32. static short Lanczos4Tab_i[INTER_TAB_SIZE2][8][8];  
  33.   
  34. template<typename _Tp1, typename _Tp2, int chs1, int chs2> static int remap_nearest(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  35.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue);  
  36. template<typename _Tp1, typename _Tp2, int chs1, int chs2> static int remap_linear(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  37.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue);  
  38. template<typename _Tp1, typename _Tp2, int chs1, int chs2> static int remap_cubic(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  39.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue);  
  40. template<typename _Tp1, typename _Tp2, int chs1, int chs2> static int remap_lanczos4(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  41.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue);  
  42.   
  43. // Applies a generic geometrical transformation to an image  
  44. // transforms the source image using the specified map, this function cannot operate in-place  
  45. // support type: uchar/float  
  46. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  47. int remap(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst, const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2,  
  48.     int interpolation, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar())  
  49. {  
  50.     FBC_Assert(map1.size().area() > 0 && map1.size() == map2.size());  
  51.     FBC_Assert(map1.data != NULL && map2.data != NULL);  
  52.     FBC_Assert(src.size() == map1.size() && src.size() == dst.size());  
  53.     FBC_Assert(src.data != dst.data);  
  54.     FBC_Assert(typeid(uchar).name() == typeid(_Tp1).name() || typeid(float).name() == typeid(_Tp1).name()); // uchar || float  
  55.     FBC_Assert(typeid(float).name() == typeid(_Tp2).name());  
  56.     FBC_Assert(chs2 == 1);  
  57.   
  58.     switch (interpolation) {  
  59.         case 0: {  
  60.             remap_nearest(src, dst, map1, map2, borderMode, borderValue);  
  61.             break;  
  62.         }  
  63.         case 1:  
  64.         case 3: {  
  65.             remap_linear(src, dst, map1, map2, borderMode, borderValue);  
  66.             break;  
  67.         }  
  68.         case 2: {  
  69.             remap_cubic(src, dst, map1, map2, borderMode, borderValue);  
  70.             break;  
  71.         }  
  72.         case 4: {  
  73.             remap_lanczos4(src, dst, map1, map2, borderMode, borderValue);  
  74.             break;  
  75.         }  
  76.         default:  
  77.             return -1;  
  78.     }  
  79.   
  80.     return 0;  
  81. }  
  82.   
  83. template<typename _Tp>  
  84. static inline void interpolateLinear(_Tp x, _Tp* coeffs)  
  85. {  
  86.     coeffs[0] = 1.f - x;  
  87.     coeffs[1] = x;  
  88. }  
  89.   
  90. template<typename _Tp>  
  91. static void initInterTab1D(int method, float* tab, int tabsz)  
  92. {  
  93.     float scale = 1.f / tabsz;  
  94.     if (method == INTER_LINEAR) {  
  95.         for (int i = 0; i < tabsz; i++, tab += 2)  
  96.             interpolateLinear<float>(i*scale, tab);  
  97.     } else if (method == INTER_CUBIC) {  
  98.         for (int i = 0; i < tabsz; i++, tab += 4)  
  99.             interpolateCubic<float>(i*scale, tab);  
  100.     } else if (method == INTER_LANCZOS4) {  
  101.         for (int i = 0; i < tabsz; i++, tab += 8)  
  102.             interpolateLanczos4<float>(i*scale, tab);  
  103.     } else {  
  104.         FBC_Error("Unknown interpolation method");  
  105.     }  
  106. }  
  107.   
  108. template<typename _Tp>  
  109. static const void* initInterTab2D(int method, bool fixpt)  
  110. {  
  111.     static bool inittab[INTER_MAX + 1] = { false };  
  112.     float* tab = 0;  
  113.     short* itab = 0;  
  114.     int ksize = 0;  
  115.     if (method == INTER_LINEAR) {  
  116.         tab = BilinearTab_f[0][0], itab = BilinearTab_i[0][0], ksize = 2;  
  117.     } else if (method == INTER_CUBIC) {  
  118.         tab = BicubicTab_f[0][0], itab = BicubicTab_i[0][0], ksize = 4;  
  119.     } else if (method == INTER_LANCZOS4) {  
  120.         tab = Lanczos4Tab_f[0][0], itab = Lanczos4Tab_i[0][0], ksize = 8;  
  121.     } else {  
  122.         FBC_Error("Unknown/unsupported interpolation type");  
  123.     }  
  124.   
  125.     if (!inittab[method]) {  
  126.         AutoBuffer<float> _tab(8 * INTER_TAB_SIZE);  
  127.         int i, j, k1, k2;  
  128.         initInterTab1D<float>(method, _tab, INTER_TAB_SIZE);  
  129.         for (i = 0; i < INTER_TAB_SIZE; i++) {  
  130.             for (j = 0; j < INTER_TAB_SIZE; j++, tab += ksize*ksize, itab += ksize*ksize) {  
  131.                 int isum = 0;  
  132.                 NNDeltaTab_i[i*INTER_TAB_SIZE + j][0] = j < INTER_TAB_SIZE / 2;  
  133.                 NNDeltaTab_i[i*INTER_TAB_SIZE + j][1] = i < INTER_TAB_SIZE / 2;  
  134.   
  135.                 for (k1 = 0; k1 < ksize; k1++) {  
  136.                     float vy = _tab[i*ksize + k1];  
  137.                     for (k2 = 0; k2 < ksize; k2++) {  
  138.                         float v = vy*_tab[j*ksize + k2];  
  139.                         tab[k1*ksize + k2] = v;  
  140.                         isum += itab[k1*ksize + k2] = saturate_cast<short>(v*INTER_REMAP_COEF_SCALE);  
  141.                     }  
  142.                 }  
  143.   
  144.                 if (isum != INTER_REMAP_COEF_SCALE) {  
  145.                     int diff = isum - INTER_REMAP_COEF_SCALE;  
  146.                     int ksize2 = ksize / 2, Mk1 = ksize2, Mk2 = ksize2, mk1 = ksize2, mk2 = ksize2;  
  147.                     for (k1 = ksize2; k1 < ksize2 + 2; k1++) {  
  148.                         for (k2 = ksize2; k2 < ksize2 + 2; k2++) {  
  149.                             if (itab[k1*ksize + k2] < itab[mk1*ksize + mk2])  
  150.                                 mk1 = k1, mk2 = k2;  
  151.                             else if (itab[k1*ksize + k2] > itab[Mk1*ksize + Mk2])  
  152.                                 Mk1 = k1, Mk2 = k2;  
  153.                         }  
  154.                     }  
  155.                     if (diff < 0)  
  156.                         itab[Mk1*ksize + Mk2] = (short)(itab[Mk1*ksize + Mk2] - diff);  
  157.                     else  
  158.                         itab[mk1*ksize + mk2] = (short)(itab[mk1*ksize + mk2] - diff);  
  159.                 }  
  160.             }  
  161.         }  
  162.         tab -= INTER_TAB_SIZE2*ksize*ksize;  
  163.         itab -= INTER_TAB_SIZE2*ksize*ksize;  
  164.         inittab[method] = true;  
  165.     }  
  166.   
  167.     return fixpt ? (const void*)itab : (const void*)tab;  
  168. }  
  169.   
  170. template<typename _Tp>  
  171. static bool initAllInterTab2D()  
  172. {  
  173.     return  initInterTab2D<uchar>(INTER_LINEAR, false) &&  
  174.         initInterTab2D<uchar>(INTER_LINEAR, true) &&  
  175.         initInterTab2D<uchar>(INTER_CUBIC, false) &&  
  176.         initInterTab2D<uchar>(INTER_CUBIC, true) &&  
  177.         initInterTab2D<uchar>(INTER_LANCZOS4, false) &&  
  178.         initInterTab2D<uchar>(INTER_LANCZOS4, true);  
  179. }  
  180.   
  181. static volatile bool doInitAllInterTab2D = initAllInterTab2D<uchar>();  
  182.   
  183. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  184. static void remapNearest(const Mat_<_Tp1, chs1>& _src, Mat_<_Tp1, chs1>& _dst, const Mat_<_Tp2, chs2>& _xy, int borderType, const Scalar& _borderValue)  
  185. {  
  186.     Size ssize = _src.size(), dsize = _dst.size();  
  187.     int cn = _src.channels;  
  188.     const _Tp1* S0 = (const _Tp1*)_src.ptr();  
  189.     size_t sstep = _src.step / sizeof(S0[0]);  
  190.     Scalar_<_Tp1> cval(saturate_cast<_Tp1>(_borderValue[0]), saturate_cast<_Tp1>(_borderValue[1]), saturate_cast<_Tp1>(_borderValue[2]), saturate_cast<_Tp1>(_borderValue[3]));  
  191.     int dx, dy;  
  192.   
  193.     unsigned width1 = ssize.width, height1 = ssize.height;  
  194.   
  195.     for (dy = 0; dy < dsize.height; dy++) {  
  196.         _Tp1* D = (_Tp1*)_dst.ptr(dy);  
  197.         const short* XY = (const short*)_xy.ptr(dy);  
  198.   
  199.         if (cn == 1) {  
  200.             for (dx = 0; dx < dsize.width; dx++) {  
  201.                 int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  202.                 if ((unsigned)sx < width1 && (unsigned)sy < height1) {  
  203.                     D[dx] = S0[sy*sstep + sx];  
  204.                 } else {  
  205.                     if (borderType == BORDER_REPLICATE) {  
  206.                         sx = clip<int>(sx, 0, ssize.width);  
  207.                         sy = clip<int>(sy, 0, ssize.height);  
  208.                         D[dx] = S0[sy*sstep + sx];  
  209.                     } else if (borderType == BORDER_CONSTANT) {  
  210.                         D[dx] = cval[0];  
  211.                     } else if (borderType != BORDER_TRANSPARENT) {  
  212.                         sx = borderInterpolate(sx, ssize.width, borderType);  
  213.                         sy = borderInterpolate(sy, ssize.height, borderType);  
  214.                         D[dx] = S0[sy*sstep + sx];  
  215.                     }  
  216.                 }  
  217.             }  
  218.         } else {  
  219.             for (dx = 0; dx < dsize.width; dx++, D += cn) {  
  220.                 int sx = XY[dx * 2], sy = XY[dx * 2 + 1], k;  
  221.                 const _Tp1 *S;  
  222.                 if ((unsigned)sx < width1 && (unsigned)sy < height1) {  
  223.                     if (cn == 3) {  
  224.                         S = S0 + sy*sstep + sx * 3;  
  225.                         D[0] = S[0], D[1] = S[1], D[2] = S[2];  
  226.                     } else if (cn == 4) {  
  227.                         S = S0 + sy*sstep + sx * 4;  
  228.                         D[0] = S[0], D[1] = S[1], D[2] = S[2], D[3] = S[3];  
  229.                     } else {  
  230.                         S = S0 + sy*sstep + sx*cn;  
  231.                         for (k = 0; k < cn; k++)  
  232.                             D[k] = S[k];  
  233.                     }  
  234.                 } else if (borderType != BORDER_TRANSPARENT) {  
  235.                     if (borderType == BORDER_REPLICATE) {  
  236.                         sx = clip<int>(sx, 0, ssize.width);  
  237.                         sy = clip<int>(sy, 0, ssize.height);  
  238.                         S = S0 + sy*sstep + sx*cn;  
  239.                     } else if (borderType == BORDER_CONSTANT) {  
  240.                         S = &cval[0];  
  241.                     } else {  
  242.                         sx = borderInterpolate(sx, ssize.width, borderType);  
  243.                         sy = borderInterpolate(sy, ssize.height, borderType);  
  244.                         S = S0 + sy*sstep + sx*cn;  
  245.                     }  
  246.                     for (k = 0; k < cn; k++)  
  247.                         D[k] = S[k];  
  248.                 }  
  249.             }  
  250.         }  
  251.     }  
  252. }  
  253.   
  254. template<class CastOp, typename AT, typename _Tp1, typename _Tp2, typename _Tp3, int chs1, int chs2, int chs3>  
  255. static int remapBilinear(const Mat_<_Tp1, chs1>& _src, Mat_<_Tp1, chs1>& _dst,  
  256.     const Mat_<_Tp2, chs2>& _xy, const Mat_<_Tp3, chs3>& _fxy, const void* _wtab, int borderType, const Scalar& _borderValue)  
  257. {  
  258.     typedef typename CastOp::rtype T;  
  259.     typedef typename CastOp::type1 WT;  
  260.     Size ssize = _src.size(), dsize = _dst.size();  
  261.     int k, cn = _src.channels;  
  262.     const AT* wtab = (const AT*)_wtab;  
  263.     const T* S0 = (const T*)_src.ptr();  
  264.     size_t sstep = _src.step / sizeof(S0[0]);  
  265.     T cval[CV_CN_MAX];  
  266.     int dx, dy;  
  267.     CastOp castOp;  
  268.   
  269.     for (k = 0; k < cn; k++)  
  270.         cval[k] = saturate_cast<T>(_borderValue[k & 3]);  
  271.   
  272.     unsigned width1 = std::max(ssize.width - 1, 0), height1 = std::max(ssize.height - 1, 0);  
  273.     FBC_Assert(ssize.area() > 0);  
  274.   
  275.     for (dy = 0; dy < dsize.height; dy++) {  
  276.         T* D = (T*)_dst.ptr(dy);  
  277.         const short* XY = (const short*)_xy.ptr(dy);  
  278.         const ushort* FXY = (const ushort*)_fxy.ptr(dy);  
  279.         int X0 = 0;  
  280.         bool prevInlier = false;  
  281.   
  282.         for (dx = 0; dx <= dsize.width; dx++) {  
  283.             bool curInlier = dx < dsize.width ? (unsigned)XY[dx * 2] < width1 && (unsigned)XY[dx * 2 + 1] < height1 : !prevInlier;  
  284.             if (curInlier == prevInlier)  
  285.                 continue;  
  286.   
  287.             int X1 = dx;  
  288.             dx = X0;  
  289.             X0 = X1;  
  290.             prevInlier = curInlier;  
  291.   
  292.             if (!curInlier) {  
  293.                 int len = 0;  
  294.                 D += len*cn;  
  295.                 dx += len;  
  296.   
  297.                 if (cn == 1) {  
  298.                     for (; dx < X1; dx++, D++) {  
  299.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  300.                         const AT* w = wtab + FXY[dx] * 4;  
  301.                         const T* S = S0 + sy*sstep + sx;  
  302.                         *D = castOp(WT(S[0] * w[0] + S[1] * w[1] + S[sstep] * w[2] + S[sstep + 1] * w[3]));  
  303.                     }  
  304.                 } else if (cn == 2) {  
  305.                     for (; dx < X1; dx++, D += 2) {  
  306.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  307.                         const AT* w = wtab + FXY[dx] * 4;  
  308.                         const T* S = S0 + sy*sstep + sx * 2;  
  309.                         WT t0 = S[0] * w[0] + S[2] * w[1] + S[sstep] * w[2] + S[sstep + 2] * w[3];  
  310.                         WT t1 = S[1] * w[0] + S[3] * w[1] + S[sstep + 1] * w[2] + S[sstep + 3] * w[3];  
  311.                         D[0] = castOp(t0); D[1] = castOp(t1);  
  312.                     }  
  313.                 } else if (cn == 3) {  
  314.                     for (; dx < X1; dx++, D += 3) {  
  315.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  316.                         const AT* w = wtab + FXY[dx] * 4;  
  317.                         const T* S = S0 + sy*sstep + sx * 3;  
  318.                         WT t0 = S[0] * w[0] + S[3] * w[1] + S[sstep] * w[2] + S[sstep + 3] * w[3];  
  319.                         WT t1 = S[1] * w[0] + S[4] * w[1] + S[sstep + 1] * w[2] + S[sstep + 4] * w[3];  
  320.                         WT t2 = S[2] * w[0] + S[5] * w[1] + S[sstep + 2] * w[2] + S[sstep + 5] * w[3];  
  321.                         D[0] = castOp(t0); D[1] = castOp(t1); D[2] = castOp(t2);  
  322.                     }  
  323.                 } else if (cn == 4) {  
  324.                     for (; dx < X1; dx++, D += 4) {  
  325.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  326.                         const AT* w = wtab + FXY[dx] * 4;  
  327.                         const T* S = S0 + sy*sstep + sx * 4;  
  328.                         WT t0 = S[0] * w[0] + S[4] * w[1] + S[sstep] * w[2] + S[sstep + 4] * w[3];  
  329.                         WT t1 = S[1] * w[0] + S[5] * w[1] + S[sstep + 1] * w[2] + S[sstep + 5] * w[3];  
  330.                         D[0] = castOp(t0); D[1] = castOp(t1);  
  331.                         t0 = S[2] * w[0] + S[6] * w[1] + S[sstep + 2] * w[2] + S[sstep + 6] * w[3];  
  332.                         t1 = S[3] * w[0] + S[7] * w[1] + S[sstep + 3] * w[2] + S[sstep + 7] * w[3];  
  333.                         D[2] = castOp(t0); D[3] = castOp(t1);  
  334.                     }  
  335.                 } else {  
  336.                     for (; dx < X1; dx++, D += cn) {  
  337.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  338.                         const AT* w = wtab + FXY[dx] * 4;  
  339.                         const T* S = S0 + sy*sstep + sx*cn;  
  340.                         for (k = 0; k < cn; k++) {  
  341.                             WT t0 = S[k] * w[0] + S[k + cn] * w[1] + S[sstep + k] * w[2] + S[sstep + k + cn] * w[3];  
  342.                             D[k] = castOp(t0);  
  343.                         }  
  344.                     }  
  345.                 }  
  346.             } else {  
  347.                 if (borderType == BORDER_TRANSPARENT && cn != 3) {  
  348.                     D += (X1 - dx)*cn;  
  349.                     dx = X1;  
  350.                     continue;  
  351.                 }  
  352.   
  353.                 if (cn == 1) {  
  354.                     for (; dx < X1; dx++, D++) {  
  355.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  356.                         if (borderType == BORDER_CONSTANT && (sx >= ssize.width || sx + 1 < 0 || sy >= ssize.height || sy + 1 < 0)) {  
  357.                             D[0] = cval[0];  
  358.                         } else {  
  359.                             int sx0, sx1, sy0, sy1;  
  360.                             T v0, v1, v2, v3;  
  361.                             const AT* w = wtab + FXY[dx] * 4;  
  362.                             if (borderType == BORDER_REPLICATE) {  
  363.                                 sx0 = clip(sx, 0, ssize.width);  
  364.                                 sx1 = clip(sx + 1, 0, ssize.width);  
  365.                                 sy0 = clip(sy, 0, ssize.height);  
  366.                                 sy1 = clip(sy + 1, 0, ssize.height);  
  367.                                 v0 = S0[sy0*sstep + sx0];  
  368.                                 v1 = S0[sy0*sstep + sx1];  
  369.                                 v2 = S0[sy1*sstep + sx0];  
  370.                                 v3 = S0[sy1*sstep + sx1];  
  371.                             } else {  
  372.                                 sx0 = borderInterpolate(sx, ssize.width, borderType);  
  373.                                 sx1 = borderInterpolate(sx + 1, ssize.width, borderType);  
  374.                                 sy0 = borderInterpolate(sy, ssize.height, borderType);  
  375.                                 sy1 = borderInterpolate(sy + 1, ssize.height, borderType);  
  376.                                 v0 = sx0 >= 0 && sy0 >= 0 ? S0[sy0*sstep + sx0] : cval[0];  
  377.                                 v1 = sx1 >= 0 && sy0 >= 0 ? S0[sy0*sstep + sx1] : cval[0];  
  378.                                 v2 = sx0 >= 0 && sy1 >= 0 ? S0[sy1*sstep + sx0] : cval[0];  
  379.                                 v3 = sx1 >= 0 && sy1 >= 0 ? S0[sy1*sstep + sx1] : cval[0];  
  380.                             }  
  381.                             D[0] = castOp(WT(v0*w[0] + v1*w[1] + v2*w[2] + v3*w[3]));  
  382.                         }  
  383.                     }  
  384.                 } else {  
  385.                     for (; dx < X1; dx++, D += cn) {  
  386.                         int sx = XY[dx * 2], sy = XY[dx * 2 + 1];  
  387.                         if (borderType == BORDER_CONSTANT && (sx >= ssize.width || sx + 1 < 0 || sy >= ssize.height || sy + 1 < 0)) {  
  388.                             for (k = 0; k < cn; k++)  
  389.                                 D[k] = cval[k];  
  390.                         } else {  
  391.                             int sx0, sx1, sy0, sy1;  
  392.                             const T *v0, *v1, *v2, *v3;  
  393.                             const AT* w = wtab + FXY[dx] * 4;  
  394.                             if (borderType == BORDER_REPLICATE) {  
  395.                                 sx0 = clip(sx, 0, ssize.width);  
  396.                                 sx1 = clip(sx + 1, 0, ssize.width);  
  397.                                 sy0 = clip(sy, 0, ssize.height);  
  398.                                 sy1 = clip(sy + 1, 0, ssize.height);  
  399.                                 v0 = S0 + sy0*sstep + sx0*cn;  
  400.                                 v1 = S0 + sy0*sstep + sx1*cn;  
  401.                                 v2 = S0 + sy1*sstep + sx0*cn;  
  402.                                 v3 = S0 + sy1*sstep + sx1*cn;  
  403.                             } else if (borderType == BORDER_TRANSPARENT && ((unsigned)sx >= (unsigned)(ssize.width - 1) || (unsigned)sy >= (unsigned)(ssize.height - 1))) {  
  404.                                 continue;  
  405.                             } else {  
  406.                                 sx0 = borderInterpolate(sx, ssize.width, borderType);  
  407.                                 sx1 = borderInterpolate(sx + 1, ssize.width, borderType);  
  408.                                 sy0 = borderInterpolate(sy, ssize.height, borderType);  
  409.                                 sy1 = borderInterpolate(sy + 1, ssize.height, borderType);  
  410.                                 v0 = sx0 >= 0 && sy0 >= 0 ? S0 + sy0*sstep + sx0*cn : &cval[0];  
  411.                                 v1 = sx1 >= 0 && sy0 >= 0 ? S0 + sy0*sstep + sx1*cn : &cval[0];  
  412.                                 v2 = sx0 >= 0 && sy1 >= 0 ? S0 + sy1*sstep + sx0*cn : &cval[0];  
  413.                                 v3 = sx1 >= 0 && sy1 >= 0 ? S0 + sy1*sstep + sx1*cn : &cval[0];  
  414.                             }  
  415.                             for (k = 0; k < cn; k++)  
  416.                                 D[k] = castOp(WT(v0[k] * w[0] + v1[k] * w[1] + v2[k] * w[2] + v3[k] * w[3]));  
  417.                         }  
  418.                     }  
  419.                 }  
  420.             }  
  421.         }  
  422.     }  
  423.   
  424.     return 0;  
  425. }  
  426.   
  427. template<class CastOp, typename AT, int ONE, typename _Tp1, typename _Tp2, typename _Tp3, int chs1, int chs2, int chs3>  
  428. static int remapBicubic(const Mat_<_Tp1, chs1>& _src, Mat_<_Tp1, chs1>& _dst,  
  429.     const Mat_<_Tp2, chs2>& _xy, const Mat_<_Tp3, chs3>& _fxy, const void* _wtab, int borderType, const Scalar& _borderValue)  
  430. {  
  431.     typedef typename CastOp::rtype T;  
  432.     typedef typename CastOp::type1 WT;  
  433.     Size ssize = _src.size(), dsize = _dst.size();  
  434.     int cn = _src.channels;  
  435.     const AT* wtab = (const AT*)_wtab;  
  436.     const T* S0 = (const T*)_src.ptr();  
  437.     size_t sstep = _src.step / sizeof(S0[0]);  
  438.     Scalar_<T> cval(saturate_cast<T>(_borderValue[0]),  
  439.         saturate_cast<T>(_borderValue[1]),  
  440.         saturate_cast<T>(_borderValue[2]),  
  441.         saturate_cast<T>(_borderValue[3]));  
  442.     int dx, dy;  
  443.     CastOp castOp;  
  444.     int borderType1 = borderType != BORDER_TRANSPARENT ? borderType : BORDER_REFLECT_101;  
  445.   
  446.     unsigned width1 = std::max(ssize.width - 3, 0), height1 = std::max(ssize.height - 3, 0);  
  447.   
  448.     for (dy = 0; dy < dsize.height; dy++) {  
  449.         T* D = (T*)_dst.ptr(dy);  
  450.         const short* XY = (const short*)_xy.ptr(dy);  
  451.         const ushort* FXY = (const ushort*)_fxy.ptr(dy);  
  452.   
  453.         for (dx = 0; dx < dsize.width; dx++, D += cn) {  
  454.             int sx = XY[dx * 2] - 1, sy = XY[dx * 2 + 1] - 1;  
  455.             const AT* w = wtab + FXY[dx] * 16;  
  456.             int i, k;  
  457.             if ((unsigned)sx < width1 && (unsigned)sy < height1) {  
  458.                 const T* S = S0 + sy*sstep + sx*cn;  
  459.                 for (k = 0; k < cn; k++) {  
  460.                     WT sum = S[0] * w[0] + S[cn] * w[1] + S[cn * 2] * w[2] + S[cn * 3] * w[3];  
  461.                     S += sstep;  
  462.                     sum += S[0] * w[4] + S[cn] * w[5] + S[cn * 2] * w[6] + S[cn * 3] * w[7];  
  463.                     S += sstep;  
  464.                     sum += S[0] * w[8] + S[cn] * w[9] + S[cn * 2] * w[10] + S[cn * 3] * w[11];  
  465.                     S += sstep;  
  466.                     sum += S[0] * w[12] + S[cn] * w[13] + S[cn * 2] * w[14] + S[cn * 3] * w[15];  
  467.                     S += 1 - sstep * 3;  
  468.                     D[k] = castOp(sum);  
  469.                 }  
  470.             } else {  
  471.                 int x[4], y[4];  
  472.                 if (borderType == BORDER_TRANSPARENT &&  
  473.                     ((unsigned)(sx + 1) >= (unsigned)ssize.width ||  
  474.                     (unsigned)(sy + 1) >= (unsigned)ssize.height))  
  475.                     continue;  
  476.   
  477.                 if (borderType1 == BORDER_CONSTANT &&  
  478.                     (sx >= ssize.width || sx + 4 <= 0 ||  
  479.                     sy >= ssize.height || sy + 4 <= 0)) {  
  480.                     for (k = 0; k < cn; k++)  
  481.                         D[k] = cval[k];  
  482.                     continue;  
  483.                 }  
  484.   
  485.                 for (i = 0; i < 4; i++) {  
  486.                     x[i] = borderInterpolate(sx + i, ssize.width, borderType1)*cn;  
  487.                     y[i] = borderInterpolate(sy + i, ssize.height, borderType1);  
  488.                 }  
  489.   
  490.                 for (k = 0; k < cn; k++, S0++, w -= 16) {  
  491.                     WT cv = cval[k], sum = cv*ONE;  
  492.                     for (i = 0; i < 4; i++, w += 4) {  
  493.                         int yi = y[i];  
  494.                         const T* S = S0 + yi*sstep;  
  495.                         if (yi < 0)  
  496.                             continue;  
  497.                         if (x[0] >= 0)  
  498.                             sum += (S[x[0]] - cv)*w[0];  
  499.                         if (x[1] >= 0)  
  500.                             sum += (S[x[1]] - cv)*w[1];  
  501.                         if (x[2] >= 0)  
  502.                             sum += (S[x[2]] - cv)*w[2];  
  503.                         if (x[3] >= 0)  
  504.                             sum += (S[x[3]] - cv)*w[3];  
  505.                     }  
  506.                     D[k] = castOp(sum);  
  507.                 }  
  508.                 S0 -= cn;  
  509.             }  
  510.         }  
  511.     }  
  512.   
  513.     return 0;  
  514. }  
  515.   
  516. template<class CastOp, typename AT, int ONE, typename _Tp1, typename _Tp2, typename _Tp3, int chs1, int chs2, int chs3>  
  517. static int remapLanczos4(const Mat_<_Tp1, chs1>& _src, Mat_<_Tp1, chs1>& _dst,  
  518.     const Mat_<_Tp2, chs2>& _xy, const Mat_<_Tp3, chs3>& _fxy, const void* _wtab, int borderType, const Scalar& _borderValue)  
  519. {  
  520.     typedef typename CastOp::rtype T;  
  521.     typedef typename CastOp::type1 WT;  
  522.     Size ssize = _src.size(), dsize = _dst.size();  
  523.     int cn = _src.channels;  
  524.     const AT* wtab = (const AT*)_wtab;  
  525.     const T* S0 = (const T*)_src.ptr();  
  526.     size_t sstep = _src.step / sizeof(S0[0]);  
  527.     Scalar_<T> cval(saturate_cast<T>(_borderValue[0]),  
  528.         saturate_cast<T>(_borderValue[1]),  
  529.         saturate_cast<T>(_borderValue[2]),  
  530.         saturate_cast<T>(_borderValue[3]));  
  531.     int dx, dy;  
  532.     CastOp castOp;  
  533.     int borderType1 = borderType != BORDER_TRANSPARENT ? borderType : BORDER_REFLECT_101;  
  534.   
  535.     unsigned width1 = std::max(ssize.width - 7, 0), height1 = std::max(ssize.height - 7, 0);  
  536.   
  537.     for (dy = 0; dy < dsize.height; dy++) {  
  538.         T* D = (T*)_dst.ptr(dy);  
  539.         const short* XY = (const short*)_xy.ptr(dy);  
  540.         const ushort* FXY = (const ushort*)_fxy.ptr(dy);  
  541.   
  542.         for (dx = 0; dx < dsize.width; dx++, D += cn) {  
  543.             int sx = XY[dx * 2] - 3, sy = XY[dx * 2 + 1] - 3;  
  544.             const AT* w = wtab + FXY[dx] * 64;  
  545.             const T* S = S0 + sy*sstep + sx*cn;  
  546.             int i, k;  
  547.             if ((unsigned)sx < width1 && (unsigned)sy < height1) {  
  548.                 for (k = 0; k < cn; k++) {  
  549.                     WT sum = 0;  
  550.                     for (int r = 0; r < 8; r++, S += sstep, w += 8)  
  551.                         sum += S[0] * w[0] + S[cn] * w[1] + S[cn * 2] * w[2] + S[cn * 3] * w[3] +  
  552.                         S[cn * 4] * w[4] + S[cn * 5] * w[5] + S[cn * 6] * w[6] + S[cn * 7] * w[7];  
  553.                     w -= 64;  
  554.                     S -= sstep * 8 - 1;  
  555.                     D[k] = castOp(sum);  
  556.                 }  
  557.             } else {  
  558.                 int x[8], y[8];  
  559.                 if (borderType == BORDER_TRANSPARENT &&  
  560.                     ((unsigned)(sx + 3) >= (unsigned)ssize.width ||  
  561.                     (unsigned)(sy + 3) >= (unsigned)ssize.height))  
  562.                     continue;  
  563.   
  564.                 if (borderType1 == BORDER_CONSTANT &&  
  565.                     (sx >= ssize.width || sx + 8 <= 0 ||  
  566.                     sy >= ssize.height || sy + 8 <= 0)) {  
  567.                     for (k = 0; k < cn; k++)  
  568.                         D[k] = cval[k];  
  569.                     continue;  
  570.                 }  
  571.   
  572.                 for (i = 0; i < 8; i++) {  
  573.                     x[i] = borderInterpolate(sx + i, ssize.width, borderType1)*cn;  
  574.                     y[i] = borderInterpolate(sy + i, ssize.height, borderType1);  
  575.                 }  
  576.   
  577.                 for (k = 0; k < cn; k++, S0++, w -= 64) {  
  578.                     WT cv = cval[k], sum = cv*ONE;  
  579.                     for (i = 0; i < 8; i++, w += 8) {  
  580.                         int yi = y[i];  
  581.                         const T* S1 = S0 + yi*sstep;  
  582.                         if (yi < 0)  
  583.                             continue;  
  584.                         if (x[0] >= 0)  
  585.                             sum += (S1[x[0]] - cv)*w[0];  
  586.                         if (x[1] >= 0)  
  587.                             sum += (S1[x[1]] - cv)*w[1];  
  588.                         if (x[2] >= 0)  
  589.                             sum += (S1[x[2]] - cv)*w[2];  
  590.                         if (x[3] >= 0)  
  591.                             sum += (S1[x[3]] - cv)*w[3];  
  592.                         if (x[4] >= 0)  
  593.                             sum += (S1[x[4]] - cv)*w[4];  
  594.                         if (x[5] >= 0)  
  595.                             sum += (S1[x[5]] - cv)*w[5];  
  596.                         if (x[6] >= 0)  
  597.                             sum += (S1[x[6]] - cv)*w[6];  
  598.                         if (x[7] >= 0)  
  599.                             sum += (S1[x[7]] - cv)*w[7];  
  600.                     }  
  601.                     D[k] = castOp(sum);  
  602.                 }  
  603.                 S0 -= cn;  
  604.             }  
  605.         }  
  606.     }  
  607.   
  608.     return 0;  
  609. }  
  610.   
  611. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  612. static int remap_nearest(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  613.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue)  
  614. {  
  615.     const void* ctab = 0;  
  616.     bool fixpt = typeid(uchar).name() == typeid(_Tp1).name();  
  617.     bool planar_input = map1.channels == 1;  
  618.     Range range(0, dst.rows);  
  619.   
  620.     int x, y, x1, y1;  
  621.     const int buf_size = 1 << 14;  
  622.     int brows0 = std::min(128, dst.rows);  
  623.     int bcols0 = std::min(buf_size / brows0, dst.cols);  
  624.     brows0 = std::min(buf_size / bcols0, dst.rows);  
  625.   
  626.     Mat_<short, 2> _bufxy(brows0, bcols0);  
  627.   
  628.     for (y = range.start; y < range.end; y += brows0) {  
  629.         for (x = 0; x < dst.cols; x += bcols0) {  
  630.             int brows = std::min(brows0, range.end - y);  
  631.             int bcols = std::min(bcols0, dst.cols - x);  
  632.             Mat_<_Tp1, chs1> dpart;  
  633.             dst.getROI(dpart, Rect(x, y, bcols, brows));  
  634.             Mat_<short, 2> bufxy;  
  635.             _bufxy.getROI(bufxy, Rect(0, 0, bcols, brows));  
  636.   
  637.             if (sizeof(_Tp2) == sizeof(short)) { // short  
  638.                 for (y1 = 0; y1 < brows; y1++) {  
  639.                     short* XY = (short*)bufxy.ptr(y1);  
  640.                     const short* sXY = (const short*)map1.ptr(y + y1) + x * 2;  
  641.                     const ushort* sA = (const ushort*)map2.ptr(y + y1) + x;  
  642.   
  643.                     for (x1 = 0; x1 < bcols; x1++) {  
  644.                         int a = sA[x1] & (INTER_TAB_SIZE2 - 1);  
  645.                         XY[x1 * 2] = sXY[x1 * 2] + NNDeltaTab_i[a][0];  
  646.                         XY[x1 * 2 + 1] = sXY[x1 * 2 + 1] + NNDeltaTab_i[a][1];  
  647.                     }  
  648.                 }  
  649.             } else { // float  
  650.                 for (y1 = 0; y1 < brows; y1++) {  
  651.                     short* XY = (short*)bufxy.ptr(y1);  
  652.                     const float* sX = (const float*)map1.ptr(y + y1) + x;  
  653.                     const float* sY = (const float*)map2.ptr(y + y1) + x;  
  654.   
  655.                     x1 = 0;  
  656.                     for (; x1 < bcols; x1++) {  
  657.                         XY[x1 * 2] = saturate_cast<short>(sX[x1]);  
  658.                         XY[x1 * 2 + 1] = saturate_cast<short>(sY[x1]);  
  659.                     }  
  660.                 }  
  661.             }  
  662.   
  663.             remapNearest<_Tp1, short, chs1, 2>(src, dpart, bufxy, borderMode, borderValue);  
  664.         }  
  665.     }  
  666.   
  667.     return 0;  
  668. }  
  669.   
  670. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  671. static int remap_linear(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  672.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue)  
  673. {  
  674.     const void* ctab = 0;  
  675.     bool fixpt = typeid(uchar).name() == typeid(_Tp1).name();  
  676.     bool planar_input = map1.channels == 1;  
  677.     ctab = initInterTab2D<_Tp1>(INTER_LINEAR, fixpt);  
  678.     Range range(0, dst.rows);  
  679.   
  680.     int x, y, x1, y1;  
  681.     const int buf_size = 1 << 14;  
  682.     int brows0 = std::min(128, dst.rows);  
  683.     int bcols0 = std::min(buf_size / brows0, dst.cols);  
  684.     brows0 = std::min(buf_size / bcols0, dst.rows);  
  685.   
  686.     Mat_<short, 2> _bufxy(brows0, bcols0);  
  687.     Mat_<ushort, 1> _bufa(brows0, bcols0);  
  688.   
  689.     for (y = range.start; y < range.end; y += brows0) {  
  690.         for (x = 0; x < dst.cols; x += bcols0) {  
  691.             int brows = std::min(brows0, range.end - y);  
  692.             int bcols = std::min(bcols0, dst.cols - x);  
  693.             Mat_<_Tp1, chs1> dpart;  
  694.             dst.getROI(dpart, Rect(x, y, bcols, brows));  
  695.             Mat_<short, 2> bufxy;  
  696.             _bufxy.getROI(bufxy, Rect(0, 0, bcols, brows));  
  697.             Mat_<ushort, 1> bufa;  
  698.             _bufa.getROI(bufa, Rect(0, 0, bcols, brows));  
  699.   
  700.             for (y1 = 0; y1 < brows; y1++) {  
  701.                 short* XY = (short*)bufxy.ptr(y1);  
  702.                 ushort* A = (ushort*)bufa.ptr(y1);  
  703.   
  704.                 if (planar_input) {  
  705.                     const float* sX = (const float*)map1.ptr(y + y1) + x;  
  706.                     const float* sY = (const float*)map2.ptr(y + y1) + x;  
  707.   
  708.                     x1 = 0;  
  709.                     for (; x1 < bcols; x1++) {  
  710.                         int sx = fbcRound(sX[x1] * INTER_TAB_SIZE);  
  711.                         int sy = fbcRound(sY[x1] * INTER_TAB_SIZE);  
  712.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  713.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  714.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  715.                         A[x1] = (ushort)v;  
  716.                     }  
  717.                 } else {  
  718.                     const float* sXY = (const float*)map1.ptr(y + y1) + x * 2;  
  719.                     x1 = 0;  
  720.                     for (x1 = 0; x1 < bcols; x1++) {  
  721.                         int sx = fbcRound(sXY[x1 * 2] * INTER_TAB_SIZE);  
  722.                         int sy = fbcRound(sXY[x1 * 2 + 1] * INTER_TAB_SIZE);  
  723.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  724.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  725.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  726.                         A[x1] = (ushort)v;  
  727.                     }  
  728.                 }  
  729.             }  
  730.   
  731.             if (typeid(_Tp1).name() == typeid(uchar).name()) { // uchar  
  732.                 remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  733.             } else { // float  
  734.                 remapBilinear<Cast<floatfloat>, float, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  735.             }  
  736.         }  
  737.     }  
  738.   
  739.     return 0;  
  740. }  
  741.   
  742. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  743. static int remap_cubic(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  744.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue)  
  745. {  
  746.     const void* ctab = 0;  
  747.     bool fixpt = typeid(uchar).name() == typeid(_Tp1).name();  
  748.     bool planar_input = map1.channels == 1;  
  749.     ctab = initInterTab2D<_Tp1>(INTER_CUBIC, fixpt);  
  750.     Range range(0, dst.rows);  
  751.   
  752.     int x, y, x1, y1;  
  753.     const int buf_size = 1 << 14;  
  754.     int brows0 = std::min(128, dst.rows);  
  755.     int bcols0 = std::min(buf_size / brows0, dst.cols);  
  756.     brows0 = std::min(buf_size / bcols0, dst.rows);  
  757.   
  758.     Mat_<short, 2> _bufxy(brows0, bcols0);  
  759.     Mat_<ushort, 1> _bufa(brows0, bcols0);  
  760.   
  761.     for (y = range.start; y < range.end; y += brows0) {  
  762.         for (x = 0; x < dst.cols; x += bcols0) {  
  763.             int brows = std::min(brows0, range.end - y);  
  764.             int bcols = std::min(bcols0, dst.cols - x);  
  765.             Mat_<_Tp1, chs1> dpart;  
  766.             dst.getROI(dpart, Rect(x, y, bcols, brows));  
  767.             Mat_<short, 2> bufxy;  
  768.             _bufxy.getROI(bufxy, Rect(0, 0, bcols, brows));  
  769.             Mat_<ushort, 1> bufa;  
  770.             _bufa.getROI(bufa, Rect(0, 0, bcols, brows));  
  771.   
  772.             for (y1 = 0; y1 < brows; y1++) {  
  773.                 short* XY = (short*)bufxy.ptr(y1);  
  774.                 ushort* A = (ushort*)bufa.ptr(y1);  
  775.   
  776.                 if (planar_input) {  
  777.                     const float* sX = (const float*)map1.ptr(y + y1) + x;  
  778.                     const float* sY = (const float*)map2.ptr(y + y1) + x;  
  779.   
  780.                     x1 = 0;  
  781.                     for (; x1 < bcols; x1++) {  
  782.                         int sx = fbcRound(sX[x1] * INTER_TAB_SIZE);  
  783.                         int sy = fbcRound(sY[x1] * INTER_TAB_SIZE);  
  784.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  785.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  786.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  787.                         A[x1] = (ushort)v;  
  788.                     }  
  789.                 } else {  
  790.                     const float* sXY = (const float*)map1.ptr(y + y1) + x * 2;  
  791.                     x1 = 0;  
  792.                     for (x1 = 0; x1 < bcols; x1++) {  
  793.                         int sx = fbcRound(sXY[x1 * 2] * INTER_TAB_SIZE);  
  794.                         int sy = fbcRound(sXY[x1 * 2 + 1] * INTER_TAB_SIZE);  
  795.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  796.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  797.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  798.                         A[x1] = (ushort)v;  
  799.                     }  
  800.                 }  
  801.             }  
  802.   
  803.             if (typeid(_Tp1).name() == typeid(uchar).name()) { // uchar  
  804.                 remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  805.             } else { // float  
  806.                 remapBicubic<Cast<floatfloat>, float, 1, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  807.             }  
  808.         }  
  809.     }  
  810.   
  811.     return 0;  
  812. }  
  813.   
  814. template<typename _Tp1, typename _Tp2, int chs1, int chs2>  
  815. static int remap_lanczos4(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst,  
  816.     const Mat_<_Tp2, chs2>& map1, const Mat_<_Tp2, chs2>& map2, int borderMode, const Scalar& borderValue)  
  817. {  
  818.     const void* ctab = 0;  
  819.     bool fixpt = typeid(uchar).name() == typeid(_Tp1).name();  
  820.     bool planar_input = map1.channels == 1;  
  821.     ctab = initInterTab2D<_Tp1>(INTER_LANCZOS4, fixpt);  
  822.     Range range(0, dst.rows);  
  823.   
  824.     int x, y, x1, y1;  
  825.     const int buf_size = 1 << 14;  
  826.     int brows0 = std::min(128, dst.rows);  
  827.     int bcols0 = std::min(buf_size / brows0, dst.cols);  
  828.     brows0 = std::min(buf_size / bcols0, dst.rows);  
  829.   
  830.     Mat_<short, 2> _bufxy(brows0, bcols0);  
  831.     Mat_<ushort, 1> _bufa(brows0, bcols0);  
  832.   
  833.     for (y = range.start; y < range.end; y += brows0) {  
  834.         for (x = 0; x < dst.cols; x += bcols0) {  
  835.             int brows = std::min(brows0, range.end - y);  
  836.             int bcols = std::min(bcols0, dst.cols - x);  
  837.             Mat_<_Tp1, chs1> dpart;  
  838.             dst.getROI(dpart, Rect(x, y, bcols, brows));  
  839.             Mat_<short, 2> bufxy;  
  840.             _bufxy.getROI(bufxy, Rect(0, 0, bcols, brows));  
  841.             Mat_<ushort, 1> bufa;  
  842.             _bufa.getROI(bufa, Rect(0, 0, bcols, brows));  
  843.   
  844.             for (y1 = 0; y1 < brows; y1++) {  
  845.                 short* XY = (short*)bufxy.ptr(y1);  
  846.                 ushort* A = (ushort*)bufa.ptr(y1);  
  847.   
  848.                 if (planar_input) {  
  849.                     const float* sX = (const float*)map1.ptr(y + y1) + x;  
  850.                     const float* sY = (const float*)map2.ptr(y + y1) + x;  
  851.   
  852.                     x1 = 0;  
  853.                     for (; x1 < bcols; x1++) {  
  854.                         int sx = fbcRound(sX[x1] * INTER_TAB_SIZE);  
  855.                         int sy = fbcRound(sY[x1] * INTER_TAB_SIZE);  
  856.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  857.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  858.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  859.                         A[x1] = (ushort)v;  
  860.                     }  
  861.                 } else {  
  862.                     const float* sXY = (const float*)map1.ptr(y + y1) + x * 2;  
  863.                     x1 = 0;  
  864.                     for (x1 = 0; x1 < bcols; x1++) {  
  865.                         int sx = fbcRound(sXY[x1 * 2] * INTER_TAB_SIZE);  
  866.                         int sy = fbcRound(sXY[x1 * 2 + 1] * INTER_TAB_SIZE);  
  867.                         int v = (sy & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE - 1));  
  868.                         XY[x1 * 2] = saturate_cast<short>(sx >> INTER_BITS);  
  869.                         XY[x1 * 2 + 1] = saturate_cast<short>(sy >> INTER_BITS);  
  870.                         A[x1] = (ushort)v;  
  871.                     }  
  872.                 }  
  873.             }  
  874.   
  875.             if (typeid(_Tp1).name() == typeid(uchar).name()) { // uchar  
  876.                 remapLanczos4<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  877.             }  
  878.             else { // float  
  879.                 remapLanczos4<Cast<floatfloat>, float, 1, _Tp1, short, ushort, chs1, 2, 1>(src, dpart, bufxy, bufa, ctab, borderMode, borderValue);  
  880.             }  
  881.         }  
  882.     }  
  883.   
  884.     return 0;  
  885. }  
  886.   
  887. // namespace fbc  
  888.   
  889. #endif // FBC_CV_REMAP_HPP_  
测试代码test_remap.cpp:

[cpp]  view plain copy
  1. #include "test_remap.hpp"  
  2. #include <assert.h>  
  3. #include <opencv2/opencv.hpp>  
  4. #include <remap.hpp>  
  5.   
  6. static void update_map(const cv::Mat& src, cv::Mat& map_x, cv::Mat& map_y, int ind_)  
  7. {  
  8.     int ind = ind_ % 4;  
  9.   
  10.     for (int j = 0; j < src.rows; j++) {  
  11.         for (int i = 0; i < src.cols; i++) {  
  12.             switch (ind) {  
  13.                 case 0:  
  14.                     if (i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75) {  
  15.                         map_x.at<float>(j, i) = 2 * (i - src.cols*0.25) + 0.5;  
  16.                         map_y.at<float>(j, i) = 2 * (j - src.rows*0.25) + 0.5;  
  17.                     } else {  
  18.                         map_x.at<float>(j, i) = 0;  
  19.                         map_y.at<float>(j, i) = 0;  
  20.                     }  
  21.                     break;  
  22.                 case 1:  
  23.                     map_x.at<float>(j, i) = i;  
  24.                     map_y.at<float>(j, i) = src.rows - j;  
  25.                     break;  
  26.                 case 2:  
  27.                     map_x.at<float>(j, i) = src.cols - i;  
  28.                     map_y.at<float>(j, i) = j;  
  29.                     break;  
  30.                 case 3:  
  31.                     map_x.at<float>(j, i) = src.cols - i;  
  32.                     map_y.at<float>(j, i) = src.rows - j;  
  33.                     break;  
  34.             } // end of switch  
  35.         }  
  36.     }  
  37. }  
  38.   
  39. int test_remap_uchar()  
  40. {  
  41.     cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);  
  42.     if (!matSrc.data) {  
  43.         std::cout << "read image fail" << std::endl;  
  44.         return -1;  
  45.     }  
  46.   
  47.     for (int ind = 0; ind < 4; ind++) {  
  48.         for (int interpolation = 0; interpolation < 5; interpolation++) {  
  49.             for (int borderType = 0; borderType < 6; borderType++) {  
  50.                 cv::Mat map_x, map_y;  
  51.                 map_x.create(matSrc.size(), CV_32FC1);  
  52.                 map_y.create(matSrc.size(), CV_32FC1);  
  53.   
  54.                 update_map(matSrc, map_x, map_y, ind);  
  55.   
  56.                 int width = matSrc.cols;  
  57.                 int height = matSrc.rows;  
  58.   
  59.                 fbc::Mat_<fbc::uchar, 3> mat1(height, width, matSrc.data);  
  60.                 fbc::Mat_<float, 1> mapX(height, width, map_x.data);  
  61.                 fbc::Mat_<float, 1> mapY(height, width, map_y.data);  
  62.                 fbc::Mat_<fbc::uchar, 3> mat2(height, width);  
  63.   
  64.                 fbc::remap(mat1, mat2, mapX, mapY, interpolation, borderType, fbc::Scalar::all(0));  
  65.   
  66.                 cv::Mat mat2_ = cv::Mat(height, width, CV_8UC3);  
  67.                 cv::remap(matSrc, mat2_, map_x, map_y, interpolation, borderType, cv::Scalar::all(0));  
  68.   
  69.                 assert(mat2.step == mat2_.step);  
  70.                 for (int y = 0; y < mat2.rows; y++) {  
  71.                     const fbc::uchar* p = mat2.ptr(y);  
  72.                     const uchar* p_ = mat2_.ptr(y);  
  73.   
  74.                     for (int x = 0; x < mat2.step; x++) {  
  75.                         assert(p[x] == p_[x]);  
  76.                     }  
  77.                 }  
  78.             }  
  79.         }  
  80.     }  
  81.   
  82.     return 0;  
  83. }  
  84.   
  85. int test_remap_float()  
  86. {  
  87.     cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);  
  88.     if (!matSrc.data) {  
  89.         std::cout << "read image fail" << std::endl;  
  90.         return -1;  
  91.     }  
  92.     matSrc.convertTo(matSrc, CV_32FC3);  
  93.   
  94.     for (int ind = 0; ind < 4; ind++) {  
  95.         for (int interpolation = 0; interpolation < 5; interpolation++) {  
  96.             for (int borderType = 0; borderType < 6; borderType++) {  
  97.                 cv::Mat map_x, map_y;  
  98.                 map_x.create(matSrc.size(), CV_32FC1);  
  99.                 map_y.create(matSrc.size(), CV_32FC1);  
  100.   
  101.                 update_map(matSrc, map_x, map_y, ind);  
  102.   
  103.                 int width = matSrc.cols;  
  104.                 int height = matSrc.rows;  
  105.   
  106.                 fbc::Mat_<float, 3> mat1(height, width, matSrc.data);  
  107.                 fbc::Mat_<float, 1> mapX(height, width, map_x.data);  
  108.                 fbc::Mat_<float, 1> mapY(height, width, map_y.data);  
  109.                 fbc::Mat_<float, 3> mat2(height, width);  
  110.   
  111.                 fbc::remap(mat1, mat2, mapX, mapY, interpolation, borderType, fbc::Scalar::all(0));  
  112.   
  113.                 cv::Mat mat2_ = cv::Mat(height, width, CV_32FC3);  
  114.                 cv::remap(matSrc, mat2_, map_x, map_y, interpolation, borderType, cv::Scalar::all(0));  
  115.   
  116.                 assert(mat2.step == mat2_.step);  
  117.                 for (int y = 0; y < mat2.rows; y++) {  
  118.                     const fbc::uchar* p = mat2.ptr(y);  
  119.                     const uchar* p_ = mat2_.ptr(y);  
  120.   
  121.                     for (int x = 0; x < mat2.step; x++) {  
  122.                         assert(p[x] == p_[x]);  
  123.                     }  
  124.                 }  
  125.             }  
  126.         }  
  127.     }  
  128.   
  129.     return 0;  
  130. }  

这篇关于OpenCV代码提取:remap函数的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924520

相关文章

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性: