aihot  2017-05-24 18:31:03  OpenCV |   查看评论   
这里将OpenCV3.1中五种插值算法的代码进行了提取调整。支持N通道uchar和float类型。经测试,与OpenCV3.1结果完全一致。
 
实现代码resize.hpp:
  1. // fbc_cv是免费软件,并且使用与OpenCV相同的许可证  
  2. #ifndef FBC_CV_RESIZE_HPP_  
  3. #define FBC_CV_RESIZE_HPP_  
  4.   
  5. /* reference: imgproc/include/opencv2/imgproc.hpp 
  6.               imgproc/src/imgwarp.cpp 
  7. */  
  8.   
  9. #include "core/mat.hpp"  
  10. #include "core/base.hpp"  
  11. #include "core/saturate.hpp"  
  12. #include "core/utility.hpp"  
  13. #include "imgproc.hpp"  
  14.   
  15. namespace fbc {  
  16.   
  17. static const int MAX_ESIZE = 16;  
  18.   
  19. // 插值公式和表格
  20. const int INTER_RESIZE_COEF_BITS = 11;  
  21. const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;  
  22.   
  23. template<typename _Tp, int chs> static int resize_nearest(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);  
  24. template<typename _Tp, int chs> static int resize_linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);  
  25. template<typename _Tp, int chs> static int resize_cubic(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);  
  26. template<typename _Tp, int chs> static int resize_area(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);  
  27. template<typename _Tp, int chs> static int resize_lanczos4(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);  
  28.   
  29. // 将图像src调整到大小或达到指定的大小
  30. // 支持类型:uchar / float
  31. template<typename _Tp, int chs>  
  32. int resize(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, int interpolation = NTER_LINEAR)  
  33. {  
  34.     FBC_Assert((interpolation >= 0) && (interpolation < 5));  
  35.     FBC_Assert((src.rows >= 4 && src.cols >= 4) && (dst.rows >= 4  && dst.cols >= 4));  
  36.     FBC_Assert((sizeof(_Tp) == 1) || sizeof(_Tp) == 4); // uchar || float  
  37.   
  38.     Size ssize = src.size();  
  39.     Size dsize = dst.size();  
  40.   
  41.     if (dsize == ssize) {  
  42.         // 来源和目的地的大小相同。 使用简单的副本.  
  43.         src.copyTo(dst);  
  44.         return 0;  
  45.     }  
  46.   
  47.     switch (interpolation) {  
  48.         case 0: {  
  49.             resize_nearest(src, dst);  
  50.             break;  
  51.         }  
  52.         case 1: {  
  53.             resize_linear(src, dst);  
  54.             break;  
  55.         }  
  56.         case 2: {  
  57.             resize_cubic(src, dst);  
  58.             break;  
  59.         }  
  60.         case 3: {  
  61.             resize_area(src, dst);  
  62.             break;  
  63.         }  
  64.         case 4: {  
  65.             resize_lanczos4(src, dst);  
  66.             break;  
  67.         }  
  68.         default:  
  69.             return -1;  
  70.     }  
  71.   
  72.     return 0;  
  73. }  
  74.   
  75. struct DecimateAlpha  
  76. {  
  77.     int si, di;  
  78.     float alpha;  
  79. };  
  80.   
  81. template<typename type>  
  82. static int computeResizeAreaTab(int ssize, int dsize, int cn, double scale, DecimateAlpha* tab)  
  83. {  
  84.     int k = 0;  
  85.     for (int dx = 0; dx < dsize; dx++) {  
  86.         double fsx1 = dx * scale;  
  87.         double fsx2 = fsx1 + scale;  
  88.         double cellWidth = std::min(scale, ssize - fsx1);  
  89.   
  90.         int sx1 = fbcCeil(fsx1), sx2 = fbcFloor(fsx2);  
  91.   
  92.         sx2 = std::min(sx2, ssize - 1);  
  93.         sx1 = std::min(sx1, sx2);  
  94.   
  95.         if (sx1 - fsx1 > 1e-3) {  
  96.             assert(k < ssize * 2);  
  97.             tab[k].di = dx * cn;  
  98.             tab[k].si = (sx1 - 1) * cn;  
  99.             tab[k++].alpha = (float)((sx1 - fsx1) / cellWidth);  
  100.         }  
  101.   
  102.         for (int sx = sx1; sx < sx2; sx++) {  
  103.             assert(k < ssize * 2);  
  104.             tab[k].di = dx * cn;  
  105.             tab[k].si = sx * cn;  
  106.             tab[k++].alpha = float(1.0 / cellWidth);  
  107.         }  
  108.   
  109.         if (fsx2 - sx2 > 1e-3) {  
  110.             assert(k < ssize * 2);  
  111.             tab[k].di = dx * cn;  
  112.             tab[k].si = sx2 * cn;  
  113.             tab[k++].alpha = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth);  
  114.         }  
  115.     }  
  116.     return k;  
  117. }  
  118.   
  119. template<typename ST, typename DT> struct Cast  
  120. {  
  121.     typedef ST type1;  
  122.     typedef DT rtype;  
  123.   
  124.     DT operator()(ST val) const { return saturate_cast<DT>(val); }  
  125. };  
  126.   
  127. template<typename ST, typename DT, int bits> struct FixedPtCast  
  128. {  
  129.     typedef ST type1;  
  130.     typedef DT rtype;  
  131.     enum { SHIFT = bits, DELTA = 1 << (bits - 1) };  
  132.   
  133.     DT operator()(ST val) const { return saturate_cast<DT>((val + DELTA) >> SHIFT); }  
  134. };  
  135.   
  136. template<typename type>  
  137. static type clip(type x, type a, type b)  
  138. {  
  139.     return x >= a ? (x < b ? x : b - 1) : a;  
  140. }  
  141.   
  142. template<typename T, typename WT, typename AT>  
  143. struct HResizeLinear  
  144. {  
  145.     typedef T value_type;  
  146.     typedef WT buf_type;  
  147.     typedef AT alpha_type;  
  148.   
  149.     void operator()(const T** src, WT** dst, int count,  
  150.         const int* xofs, const AT* alpha,  
  151.         int swidth, int dwidth, int cn, int xmin, int xmax, int ONE) const  
  152.     {  
  153.         int dx, k;  
  154.         int dx0 = 0;  
  155.   
  156.         for (k = 0; k <= count - 2; k++) {  
  157.             const T *S0 = src[k], *S1 = src[k + 1];  
  158.             WT *D0 = dst[k], *D1 = dst[k + 1];  
  159.             for (dx = dx0; dx < xmax; dx++) {  
  160.                 int sx = xofs[dx];  
  161.                 WT a0 = alpha[dx * 2], a1 = alpha[dx * 2 + 1];  
  162.                 WT t0 = S0[sx] * a0 + S0[sx + cn] * a1;  
  163.                 WT t1 = S1[sx] * a0 + S1[sx + cn] * a1;  
  164.                 D0[dx] = t0; D1[dx] = t1;  
  165.             }  
  166.   
  167.             for (; dx < dwidth; dx++) {  
  168.                 int sx = xofs[dx];  
  169.                 D0[dx] = WT(S0[sx] * ONE); D1[dx] = WT(S1[sx] * ONE);  
  170.             }  
  171.         }  
  172.   
  173.         for (; k < count; k++) {  
  174.             const T *S = src[k];  
  175.             WT *D = dst[k];  
  176.             for (dx = 0; dx < xmax; dx++) {  
  177.                 int sx = xofs[dx];  
  178.                 D[dx] = S[sx] * alpha[dx * 2] + S[sx + cn] * alpha[dx * 2 + 1];  
  179.             }  
  180.   
  181.             for (; dx < dwidth; dx++) {  
  182.                 D[dx] = WT(S[xofs[dx]] * ONE);  
  183.             }  
  184.         }  
  185.     }  
  186. };  
  187.   
  188. template<typename T, typename WT, typename AT, class CastOp>  
  189. struct VResizeLinear  
  190. {  
  191.     typedef T value_type;  
  192.     typedef WT buf_type;  
  193.     typedef AT alpha_type;  
  194.   
  195.     void operator()(const WT** src, T* dst, const AT* beta, int width) const  
  196.     {  
  197.         WT b0 = beta[0], b1 = beta[1];  
  198.         const WT *S0 = src[0], *S1 = src[1];  
  199.         CastOp castOp;  
  200.         int x = 0;  
  201.   
  202.         for (; x <= width - 4; x += 4) {  
  203.             WT t0, t1;  
  204.             t0 = S0[x] * b0 + S1[x] * b1;  
  205.             t1 = S0[x + 1] * b0 + S1[x + 1] * b1;  
  206.             dst[x] = castOp(t0); dst[x + 1] = castOp(t1);  
  207.             t0 = S0[x + 2] * b0 + S1[x + 2] * b1;  
  208.             t1 = S0[x + 3] * b0 + S1[x + 3] * b1;  
  209.             dst[x + 2] = castOp(t0); dst[x + 3] = castOp(t1);  
  210.         }  
  211.   
  212.         for (; x < width; x++) {  
  213.             dst[x] = castOp(S0[x] * b0 + S1[x] * b1);  
  214.         }  
  215.     }  
  216. };  
  217.   
  218. template<>  
  219. struct VResizeLinear<uchar, intshort, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>>  
  220. {  
  221.     typedef uchar value_type;  
  222.     typedef int buf_type;  
  223.     typedef short alpha_type;  
  224.   
  225.     void operator()(const buf_type** src, value_type* dst, const alpha_type* beta, int width) const  
  226.     {  
  227.         alpha_type b0 = beta[0], b1 = beta[1];  
  228.         const buf_type *S0 = src[0], *S1 = src[1];  
  229.         int x = 0;  
  230.   
  231.         for (; x <= width - 4; x += 4) {  
  232.             dst[x + 0] = uchar((((b0 * (S0[x + 0] >> 4)) >> 16) + ((b1 * (S1[x + 0] >> 4)) >> 16) + 2) >> 2);  
  233.             dst[x + 1] = uchar((((b0 * (S0[x + 1] >> 4)) >> 16) + ((b1 * (S1[x + 1] >> 4)) >> 16) + 2) >> 2);  
  234.             dst[x + 2] = uchar((((b0 * (S0[x + 2] >> 4)) >> 16) + ((b1 * (S1[x + 2] >> 4)) >> 16) + 2) >> 2);  
  235.             dst[x + 3] = uchar((((b0 * (S0[x + 3] >> 4)) >> 16) + ((b1 * (S1[x + 3] >> 4)) >> 16) + 2) >> 2);  
  236.         }  
  237.   
  238.         for (; x < width; x++) {  
  239.             dst[x] = uchar((((b0 * (S0[x] >> 4)) >> 16) + ((b1 * (S1[x] >> 4)) >> 16) + 2) >> 2);  
  240.         }  
  241.     }  
  242. };  
  243.   
  244. template<typename T, typename WT, typename AT>  
  245. struct HResizeCubic  
  246. {  
  247.     typedef T value_type;  
  248.     typedef WT buf_type;  
  249.     typedef AT alpha_type;  
  250.   
  251.     void operator()(const T** src, WT** dst, int count,  
  252.         const int* xofs, const AT* alpha,  
  253.         int swidth, int dwidth, int cn, int xmin, int xmax) const  
  254.     {  
  255.         for (int k = 0; k < count; k++) {  
  256.             const T *S = src[k];  
  257.             WT *D = dst[k];  
  258.             int dx = 0, limit = xmin;  
  259.             for (;;) {  
  260.                 for (; dx < limit; dx++, alpha += 4) {  
  261.                     int j, sx = xofs[dx] - cn;  
  262.                     WT v = 0;  
  263.                     for (j = 0; j < 4; j++) {  
  264.                         int sxj = sx + j*cn;  
  265.                         if ((unsigned)sxj >= (unsigned)swidth) {  
  266.                             while (sxj < 0)  
  267.                                 sxj += cn;  
  268.                             while (sxj >= swidth)  
  269.                                 sxj -= cn;  
  270.                         }  
  271.                         v += S[sxj] * alpha[j];  
  272.                     }  
  273.                     D[dx] = v;  
  274.                 }  
  275.                 if (limit == dwidth)  
  276.                     break;  
  277.                 for (; dx < xmax; dx++, alpha += 4) {  
  278.                     int sx = xofs[dx];  
  279.                     D[dx] = S[sx - cn] * alpha[0] + S[sx] * alpha[1] +  
  280.                         S[sx + cn] * alpha[2] + S[sx + cn * 2] * alpha[3];  
  281.                 }  
  282.                 limit = dwidth;  
  283.             }  
  284.             alpha -= dwidth * 4;  
  285.         }  
  286.     }  
  287. };  
  288.   
  289. template<typename T, typename WT, typename AT, class CastOp>  
  290. struct VResizeCubic  
  291. {  
  292.     typedef T value_type;  
  293.     typedef WT buf_type;  
  294.     typedef AT alpha_type;  
  295.   
  296.     void operator()(const WT** src, T* dst, const AT* beta, int width) const  
  297.     {  
  298.         WT b0 = beta[0], b1 = beta[1], b2 = beta[2], b3 = beta[3];  
  299.         const WT *S0 = src[0], *S1 = src[1], *S2 = src[2], *S3 = src[3];  
  300.         CastOp castOp;  
  301.   
  302.         int x = 0;  
  303.         for (; x < width; x++) {  
  304.             dst[x] = castOp(S0[x] * b0 + S1[x] * b1 + S2[x] * b2 + S3[x] * b3);  
  305.         }  
  306.     }  
  307. };  
  308.   
  309. template<typename T, typename WT, typename AT>  
  310. struct HResizeLanczos4  
  311. {  
  312.     typedef T value_type;  
  313.     typedef WT buf_type;  
  314.     typedef AT alpha_type;  
  315.   
  316.     void operator()(const T** src, WT** dst, int count,  
  317.         const int* xofs, const AT* alpha,  
  318.         int swidth, int dwidth, int cn, int xmin, int xmax) const  
  319.     {  
  320.         for (int k = 0; k < count; k++) {  
  321.             const T *S = src[k];  
  322.             WT *D = dst[k];  
  323.             int dx = 0, limit = xmin;  
  324.             for (;;) {  
  325.                 for (; dx < limit; dx++, alpha += 8) {  
  326.                     int j, sx = xofs[dx] - cn * 3;  
  327.                     WT v = 0;  
  328.                     for (j = 0; j < 8; j++) {  
  329.                         int sxj = sx + j*cn;  
  330.                         if ((unsigned)sxj >= (unsigned)swidth) {  
  331.                             while (sxj < 0)  
  332.                                 sxj += cn;  
  333.                             while (sxj >= swidth)  
  334.                                 sxj -= cn;  
  335.                         }  
  336.                         v += S[sxj] * alpha[j];  
  337.                     }  
  338.                     D[dx] = v;  
  339.                 }  
  340.                 if (limit == dwidth)  
  341.                     break;  
  342.                 for (; dx < xmax; dx++, alpha += 8) {  
  343.                     int sx = xofs[dx];  
  344.                     D[dx] = S[sx - cn * 3] * alpha[0] + S[sx - cn * 2] * alpha[1] +  
  345.                         S[sx - cn] * alpha[2] + S[sx] * alpha[3] +  
  346.                         S[sx + cn] * alpha[4] + S[sx + cn * 2] * alpha[5] +  
  347.                         S[sx + cn * 3] * alpha[6] + S[sx + cn * 4] * alpha[7];  
  348.                 }  
  349.                 limit = dwidth;  
  350.             }  
  351.             alpha -= dwidth * 8;  
  352.         }  
  353.     }  
  354. };  
  355.   
  356. template<typename T, typename WT, typename AT, class CastOp>  
  357. struct VResizeLanczos4  
  358. {  
  359.     typedef T value_type;  
  360.     typedef WT buf_type;  
  361.     typedef AT alpha_type;  
  362.   
  363.     void operator()(const WT** src, T* dst, const AT* beta, int width) const  
  364.     {  
  365.         CastOp castOp;  
  366.         int k, x = 0;  
  367.   
  368.         for (; x <= width - 4; x += 4) {  
  369.             WT b = beta[0];  
  370.             const WT* S = src[0];  
  371.             WT s0 = S[x] * b, s1 = S[x + 1] * b, s2 = S[x + 2] * b, s3 = S[x + 3] * b;  
  372.   
  373.             for (k = 1; k < 8; k++) {  
  374.                 b = beta[k]; S = src[k];  
  375.                 s0 += S[x] * b; s1 += S[x + 1] * b;  
  376.                 s2 += S[x + 2] * b; s3 += S[x + 3] * b;  
  377.             }  
  378.   
  379.             dst[x] = castOp(s0); dst[x + 1] = castOp(s1);  
  380.             dst[x + 2] = castOp(s2); dst[x + 3] = castOp(s3);  
  381.         }  
  382.   
  383.         for (; x < width; x++) {  
  384.             dst[x] = castOp(src[0][x] * beta[0] + src[1][x] * beta[1] +  
  385.                 src[2][x] * beta[2] + src[3][x] * beta[3] + src[4][x] * beta[4] +  
  386.                 src[5][x] * beta[5] + src[6][x] * beta[6] + src[7][x] * beta[7]);  
  387.         }  
  388.     }  
  389. };  
  390.   
  391. template<typename T>  
  392. struct ResizeAreaFastVec  
  393. {  
  394.     ResizeAreaFastVec(int _scale_x, int _scale_y, int _cn, int _step) :  
  395.         scale_x(_scale_x), scale_y(_scale_y), cn(_cn), step(_step)  
  396.     {  
  397.         fast_mode = scale_x == 2 && scale_y == 2 && (cn == 1 || cn == 3 || cn == 4);  
  398.     }  
  399.   
  400.     int operator() (const T* S, T* D, int w) const  
  401.     {  
  402.         if (!fast_mode) {  
  403.             return 0;  
  404.         }  
  405.   
  406.         const T* nextS = (const T*)((const uchar*)S + step);  
  407.         int dx = 0;  
  408.   
  409.         if (cn == 1) {  
  410.             for (; dx < w; ++dx) {  
  411.                 int index = dx * 2;  
  412.                 D[dx] = (T)((S[index] + S[index + 1] + nextS[index] + nextS[index + 1] + 2) >> 2);  
  413.             }  
  414.         }  
  415.         else if (cn == 3) {  
  416.             for (; dx < w; dx += 3) {  
  417.                 int index = dx * 2;  
  418.                 D[dx] = (T)((S[index] + S[index + 3] + nextS[index] + nextS[index + 3] + 2) >> 2);  
  419.                 D[dx + 1] = (T)((S[index + 1] + S[index + 4] + nextS[index + 1] + nextS[index + 4] + 2) >> 2);  
  420.                 D[dx + 2] = (T)((S[index + 2] + S[index + 5] + nextS[index + 2] + nextS[index + 5] + 2) >> 2);  
  421.             }  
  422.         } else {  
  423.             FBC_Assert(cn == 4);  
  424.             for (; dx < w; dx += 4) {  
  425.                 int index = dx * 2;  
  426.                 D[dx] = (T)((S[index] + S[index + 4] + nextS[index] + nextS[index + 4] + 2) >> 2);  
  427.                 D[dx + 1] = (T)((S[index + 1] + S[index + 5] + nextS[index + 1] + nextS[index + 5] + 2) >> 2);  
  428.                 D[dx + 2] = (T)((S[index + 2] + S[index + 6] + nextS[index + 2] + nextS[index + 6] + 2) >> 2);  
  429.                 D[dx + 3] = (T)((S[index + 3] + S[index + 7] + nextS[index + 3] + nextS[index + 7] + 2) >> 2);  
  430.             }  
  431.         }  
  432.   
  433.         return dx;  
  434.     }  
  435.   
  436. private:  
  437.     int scale_x, scale_y;  
  438.     int cn;  
  439.     bool fast_mode;  
  440.     int step;  
  441. };  
  442.   
  443. template<typename _Tp, typename value_type, typename buf_type, typename alpha_type, int chs>  
  444. static void resizeGeneric_Linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,  
  445.     const int* xofs, const void* _alpha, const int* yofs, const void* _beta, int xmin, int xmax, int ksize, int ONE)  
  446. {  
  447.     Size ssize = src.size(), dsize = dst.size();  
  448.     int dy, cn = src.channels;  
  449.     ssize.width *= cn;  
  450.     dsize.width *= cn;  
  451.     xmin *= cn;  
  452.     xmax *= cn;  
  453.     // 图像调整大小是一个可分离的操作。 万一不太强
  454.   
  455.     Range range(0, dsize.height);  
  456.   
  457.     int bufstep = (int)alignSize(dsize.width, 16);  
  458.     AutoBuffer<buf_type> _buffer(bufstep*ksize);  
  459.     const value_type* srows[MAX_ESIZE] = { 0 };  
  460.     buf_type* rows[MAX_ESIZE] = { 0 };  
  461.     int prev_sy[MAX_ESIZE];  
  462.   
  463.     for (int k = 0; k < ksize; k++) {  
  464.         prev_sy[k] = -1;  
  465.         rows[k] = (buf_type*)_buffer + bufstep*k;  
  466.     }  
  467.   
  468.     const alpha_type* beta = (const alpha_type*)_beta + ksize * range.start;  
  469.   
  470.     HResizeLinear<value_type, buf_type, alpha_type> hresize;  
  471.     VResizeLinear<value_type, buf_type, alpha_type, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>> vresize1;  
  472.     VResizeLinear<value_type, buf_type, alpha_type, Cast<floatfloat>> vresize2;  
  473.   
  474.     for (dy = range.start; dy < range.end; dy++, beta += ksize) {  
  475.         int sy0 = yofs[dy], k0 = ksize, k1 = 0, ksize2 = ksize / 2;  
  476.   
  477.         for (int k = 0; k < ksize; k++) {  
  478.             int sy = clip<int>(sy0 - ksize2 + 1 + k, 0, ssize.height);  
  479.             for (k1 = std::max(k1, k); k1 < ksize; k1++) {  
  480.                 if (sy == prev_sy[k1]) { // if the sy-th row has been computed already, reuse it.  
  481.                     if (k1 > k) {  
  482.                         memcpy(rows[k], rows[k1], bufstep*sizeof(rows[0][0]));  
  483.                     }  
  484.                     break;  
  485.                 }  
  486.             }  
  487.             if (k1 == ksize) {  
  488.                 k0 = std::min(k0, k); // 记住需要计算的第一行
  489.             }  
  490.             srows[k] = (const value_type*)src.ptr(sy);  
  491.             prev_sy[k] = sy;  
  492.         }  
  493.   
  494.         if (k0 < ksize) {  
  495.             hresize((const value_type**)(srows + k0), (buf_type**)(rows + k0), ksize - k0, xofs, (const alpha_type*)(_alpha),  
  496.                 ssize.width, dsize.width, cn, xmin, xmax, ONE);  
  497.         }  
  498.         if (sizeof(_Tp) == 1) { // uchar  
  499.             vresize1((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  500.         } else { // float  
  501.             vresize2((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  502.         }  
  503.     }  
  504. }  
  505.   
  506. template<typename _Tp, typename value_type, typename buf_type, typename alpha_type, int chs>  
  507. static void resizeGeneric_Cubic(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,  
  508.     const int* xofs, const void* _alpha, const int* yofs, const void* _beta, int xmin, int xmax, int ksize)  
  509. {  
  510.     Size ssize = src.size(), dsize = dst.size();  
  511.     int dy, cn = src.channels;  
  512.     ssize.width *= cn;  
  513.     dsize.width *= cn;  
  514.     xmin *= cn;  
  515.     xmax *= cn;  
  516.     // 图像调整大小是一个可分离的操作。 万一不太强
  517.   
  518.     Range range(0, dsize.height);  
  519.   
  520.     int bufstep = (int)alignSize(dsize.width, 16);  
  521.     AutoBuffer<buf_type> _buffer(bufstep*ksize);  
  522.     const value_type* srows[MAX_ESIZE] = { 0 };  
  523.     buf_type* rows[MAX_ESIZE] = { 0 };  
  524.     int prev_sy[MAX_ESIZE];  
  525.   
  526.     for (int k = 0; k < ksize; k++) {  
  527.         prev_sy[k] = -1;  
  528.         rows[k] = (buf_type*)_buffer + bufstep*k;  
  529.     }  
  530.   
  531.     const alpha_type* beta = (const alpha_type*)_beta + ksize * range.start;  
  532.   
  533.     HResizeCubic<value_type, buf_type, alpha_type> hresize;  
  534.     VResizeCubic<value_type, buf_type, alpha_type, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>> vresize1;  
  535.     VResizeCubic<value_type, buf_type, alpha_type, Cast<floatfloat>> vresize2;  
  536.   
  537.     for (dy = range.start; dy < range.end; dy++, beta += ksize) {  
  538.         int sy0 = yofs[dy], k0 = ksize, k1 = 0, ksize2 = ksize / 2;  
  539.   
  540.         for (int k = 0; k < ksize; k++) {  
  541.             int sy = clip<int>(sy0 - ksize2 + 1 + k, 0, ssize.height);  
  542.             for (k1 = std::max(k1, k); k1 < ksize; k1++) {  
  543.                 if (sy == prev_sy[k1]) { // if the sy-th row has been computed already, reuse it.  
  544.                     if (k1 > k) {  
  545.                         memcpy(rows[k], rows[k1], bufstep*sizeof(rows[0][0]));  
  546.                     }  
  547.                     break;  
  548.                 }  
  549.             }  
  550.             if (k1 == ksize) {  
  551.                 k0 = std::min(k0, k); // 记住需要计算的第一行
  552.             }  
  553.             srows[k] = (const value_type*)src.ptr(sy);  
  554.             prev_sy[k] = sy;  
  555.         }  
  556.   
  557.         if (k0 < ksize) {  
  558.             hresize((const value_type**)(srows + k0), (buf_type**)(rows + k0), ksize - k0, xofs, (const alpha_type*)(_alpha),  
  559.                 ssize.width, dsize.width, cn, xmin, xmax);  
  560.         }  
  561.         if (sizeof(_Tp) == 1) { // uchar  
  562.             vresize1((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  563.         } else { // float  
  564.             vresize2((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  565.         }  
  566.     }  
  567. }  
  568.   
  569. template<typename _Tp, typename value_type, typename buf_type, typename alpha_type, int chs>  
  570. static void resizeGeneric_Lanczos4(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,  
  571.     const int* xofs, const void* _alpha, const int* yofs, const void* _beta, int xmin, int xmax, int ksize)  
  572. {  
  573.     Size ssize = src.size(), dsize = dst.size();  
  574.     int dy, cn = src.channels;  
  575.     ssize.width *= cn;  
  576.     dsize.width *= cn;  
  577.     xmin *= cn;  
  578.     xmax *= cn;  
  579.     // 图像调整大小是一个可分离的操作。 万一不太强
  580.   
  581.     Range range(0, dsize.height);  
  582.   
  583.     int bufstep = (int)alignSize(dsize.width, 16);  
  584.     AutoBuffer<buf_type> _buffer(bufstep*ksize);  
  585.     const value_type* srows[MAX_ESIZE] = { 0 };  
  586.     buf_type* rows[MAX_ESIZE] = { 0 };  
  587.     int prev_sy[MAX_ESIZE];  
  588.   
  589.     for (int k = 0; k < ksize; k++) {  
  590.         prev_sy[k] = -1;  
  591.         rows[k] = (buf_type*)_buffer + bufstep*k;  
  592.     }  
  593.   
  594.     const alpha_type* beta = (const alpha_type*)_beta + ksize * range.start;  
  595.   
  596.     HResizeLanczos4<value_type, buf_type, alpha_type> hresize;  
  597.     VResizeLanczos4<value_type, buf_type, alpha_type, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>> vresize1;  
  598.     VResizeLanczos4<value_type, buf_type, alpha_type, Cast<floatfloat>> vresize2;  
  599.   
  600.     for (dy = range.start; dy < range.end; dy++, beta += ksize) {  
  601.         int sy0 = yofs[dy], k0 = ksize, k1 = 0, ksize2 = ksize / 2;  
  602.   
  603.         for (int k = 0; k < ksize; k++) {  
  604.             int sy = clip<int>(sy0 - ksize2 + 1 + k, 0, ssize.height);  
  605.             for (k1 = std::max(k1, k); k1 < ksize; k1++) {  
  606.                 if (sy == prev_sy[k1]) { // 如果已经计算了第sy行,则重新使用它.  
  607.                     if (k1 > k) {  
  608.                         memcpy(rows[k], rows[k1], bufstep*sizeof(rows[0][0]));  
  609.                     }  
  610.                     break;  
  611.                 }  
  612.             }  
  613.             if (k1 == ksize) {  
  614.                 k0 = std::min(k0, k); // 记住需要计算的第一行
  615.             }  
  616.             srows[k] = (const value_type*)src.ptr(sy);  
  617.             prev_sy[k] = sy;  
  618.         }  
  619.   
  620.         if (k0 < ksize) {  
  621.             hresize((const value_type**)(srows + k0), (buf_type**)(rows + k0), ksize - k0, xofs, (const alpha_type*)(_alpha),  
  622.                 ssize.width, dsize.width, cn, xmin, xmax);  
  623.         }  
  624.         if (sizeof(_Tp) == 1) { // uchar  
  625.             vresize1((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  626.         }  
  627.         else { // float  
  628.             vresize2((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);  
  629.         }  
  630.     }  
  631.   
  632. }  
  633.   
  634. template<typename _Tp, typename T, typename WT, int chs>  
  635. static void resizeGeneric_Area(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,  
  636.     const DecimateAlpha* xtab0, int xtab_size0, const DecimateAlpha* ytab, int ytab_size, const int* tabofs)  
  637. {  
  638.     Size dsize = dst.size();  
  639.     int cn = dst.channels;  
  640.     Range range(0, dsize.height);  
  641.     dsize.width *= cn;  
  642.     AutoBuffer<WT> _buffer(dsize.width * 2);  
  643.     const DecimateAlpha* xtab = xtab0;  
  644.     int xtab_size = xtab_size0;  
  645.     WT *buf = _buffer, *sum = buf + dsize.width;  
  646.     int j_start = tabofs[range.start], j_end = tabofs[range.end], j, k, dx, prev_dy = ytab[j_start].di;  
  647.   
  648.     for (dx = 0; dx < dsize.width; dx++) {  
  649.         sum[dx] = (WT)0;  
  650.     }  
  651.   
  652.     for (j = j_start; j < j_end; j++) {  
  653.         WT beta = ytab[j].alpha;  
  654.         int dy = ytab[j].di;  
  655.         int sy = ytab[j].si;  
  656.   
  657.         const T* S = (const T*)src.ptr(sy);  
  658.         for (dx = 0; dx < dsize.width; dx++) {  
  659.             buf[dx] = (WT)0;  
  660.         }  
  661.   
  662.         if (cn == 1) {  
  663.             for (k = 0; k < xtab_size; k++) {  
  664.                 int dxn = xtab[k].di;  
  665.                 WT alpha = xtab[k].alpha;  
  666.                 buf[dxn] += S[xtab[k].si] * alpha;  
  667.             }  
  668.         } else if (cn == 2) {  
  669.             for (k = 0; k < xtab_size; k++) {  
  670.                 int sxn = xtab[k].si;  
  671.                 int dxn = xtab[k].di;  
  672.                 WT alpha = xtab[k].alpha;  
  673.                 WT t0 = buf[dxn] + S[sxn] * alpha;  
  674.                 WT t1 = buf[dxn + 1] + S[sxn + 1] * alpha;  
  675.                 buf[dxn] = t0; buf[dxn + 1] = t1;  
  676.             }  
  677.         } else if (cn == 3) {  
  678.             for (k = 0; k < xtab_size; k++) {  
  679.                 int sxn = xtab[k].si;  
  680.                 int dxn = xtab[k].di;  
  681.                 WT alpha = xtab[k].alpha;  
  682.                 WT t0 = buf[dxn] + S[sxn] * alpha;  
  683.                 WT t1 = buf[dxn + 1] + S[sxn + 1] * alpha;  
  684.                 WT t2 = buf[dxn + 2] + S[sxn + 2] * alpha;  
  685.                 buf[dxn] = t0; buf[dxn + 1] = t1; buf[dxn + 2] = t2;  
  686.             }  
  687.         } else if (cn == 4) {  
  688.             for (k = 0; k < xtab_size; k++) {  
  689.                 int sxn = xtab[k].si;  
  690.                 int dxn = xtab[k].di;  
  691.                 WT alpha = xtab[k].alpha;  
  692.                 WT t0 = buf[dxn] + S[sxn] * alpha;  
  693.                 WT t1 = buf[dxn + 1] + S[sxn + 1] * alpha;  
  694.                 buf[dxn] = t0; buf[dxn + 1] = t1;  
  695.                 t0 = buf[dxn + 2] + S[sxn + 2] * alpha;  
  696.                 t1 = buf[dxn + 3] + S[sxn + 3] * alpha;  
  697.                 buf[dxn + 2] = t0; buf[dxn + 3] = t1;  
  698.             }  
  699.         } else {  
  700.             for (k = 0; k < xtab_size; k++) {  
  701.                 int sxn = xtab[k].si;  
  702.                 int dxn = xtab[k].di;  
  703.                 WT alpha = xtab[k].alpha;  
  704.                 for (int c = 0; c < cn; c++)  
  705.                     buf[dxn + c] += S[sxn + c] * alpha;  
  706.             }  
  707.         }  
  708.   
  709.         if (dy != prev_dy) {  
  710.             T* D = (T*)dst.ptr(prev_dy);  
  711.   
  712.             for (dx = 0; dx < dsize.width; dx++) {  
  713.                 D[dx] = saturate_cast<T>(sum[dx]);  
  714.                 sum[dx] = beta*buf[dx];  
  715.             }  
  716.             prev_dy = dy;  
  717.         } else {  
  718.             for (dx = 0; dx < dsize.width; dx++) {  
  719.                 sum[dx] += beta*buf[dx];  
  720.             }  
  721.         }  
  722.     }  
  723.   
  724.     T* D = (T*)dst.ptr(prev_dy);  
  725.     for (dx = 0; dx < dsize.width; dx++) {  
  726.         D[dx] = saturate_cast<T>(sum[dx]);  
  727.     }  
  728. }  
  729.   
  730. template<typename _Tp, typename T, typename WT, int chs>  
  731. static void resizeGeneric_AreaFast(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,  
  732.     const int* ofs, const int* xofs, int scale_x, int scale_y)  
  733. {  
  734.     Size ssize = src.size(), dsize = dst.size();  
  735.     int cn = src.channels;  
  736.     Range range(0, dsize.height);  
  737.     int area = scale_x*scale_y;  
  738.     float scale = 1.f / (area);  
  739.     int dwidth1 = (ssize.width / scale_x)*cn;  
  740.     dsize.width *= cn;  
  741.     ssize.width *= cn;  
  742.     int dy, dx, k = 0;  
  743.   
  744.     ResizeAreaFastVec<uchar> vop(scale_x, scale_y, src.channels, (int)src.step);  
  745.   
  746.     for (dy = range.start; dy < range.end; dy++) {  
  747.         T* D = (T*)(dst.data + dst.step*dy);  
  748.         int sy0 = dy*scale_y;  
  749.         int w = sy0 + scale_y <= ssize.height ? dwidth1 : 0;  
  750.   
  751.         if (sy0 >= ssize.height) {  
  752.             for (dx = 0; dx < dsize.width; dx++) {  
  753.                 D[dx] = 0;  
  754.             }  
  755.             continue;  
  756.         }  
  757.   
  758.         dx = sizeof(_Tp) == 1 ? vop(src.ptr(sy0), (uchar*)D, w) : 0;  
  759.         for (; dx < w; dx++) {  
  760.             const T* S = (const T*)src.ptr(sy0) +xofs[dx];  
  761.             WT sum = 0;  
  762.             k = 0;  
  763.   
  764.             for (; k <= area - 4; k += 4) {  
  765.                 sum += S[ofs[k]] + S[ofs[k + 1]] + S[ofs[k + 2]] + S[ofs[k + 3]];  
  766.             }  
  767.   
  768.             for (; k < area; k++) {  
  769.                 sum += S[ofs[k]];  
  770.             }  
  771.   
  772.             D[dx] = saturate_cast<T>(sum * scale);  
  773.         }  
  774.   
  775.         for (; dx < dsize.width; dx++) {  
  776.             WT sum = 0;  
  777.             int count = 0, sx0 = xofs[dx];  
  778.             if (sx0 >= ssize.width) {  
  779.                 D[dx] = 0;  
  780.             }  
  781.   
  782.             for (int sy = 0; sy < scale_y; sy++) {  
  783.                 if (sy0 + sy >= ssize.height) {  
  784.                     break;  
  785.                 }  
  786.                 const T* S = (const T*)src.ptr(sy0 + sy) + sx0;  
  787.                 for (int sx = 0; sx < scale_x*cn; sx += cn) {  
  788.                     if (sx0 + sx >= ssize.width) {  
  789.                         break;  
  790.                     }  
  791.                     sum += S[sx];  
  792.                     count++;  
  793.                 }  
  794.             }  
  795.   
  796.             D[dx] = saturate_cast<T>((float)sum / count);  
  797.         }  
  798.     }  
  799. }  
  800.   
  801. template<typename _Tp>  
  802. static void interpolateCubic(_Tp x, _Tp* coeffs)  
  803. {  
  804.     const float A = -0.75f;  
  805.   
  806.     coeffs[0] = ((A*(x + 1) - 5 * A)*(x + 1) + 8 * A)*(x + 1) - 4 * A;  
  807.     coeffs[1] = ((A + 2)*x - (A + 3))*x*x + 1;  
  808.     coeffs[2] = ((A + 2)*(1 - x) - (A + 3))*(1 - x)*(1 - x) + 1;  
  809.     coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2];  
  810. }  
  811.   
  812. template<typename _Tp>  
  813. static void interpolateLanczos4(_Tp x, _Tp* coeffs)  
  814. {  
  815.     static const double s45 = 0.70710678118654752440084436210485;  
  816.     static const double cs[][2] = { { 1, 0 }, { -s45, -s45 }, { 0, 1 }, { s45, -s45 }, { -1, 0 }, { s45, s45 }, { 0, -1 }, { -s45, s45 } };  
  817.   
  818.     if (x < FLT_EPSILON) {  
  819.         for (int i = 0; i < 8; i++) {  
  820.             coeffs[i] = 0;  
  821.         }  
  822.         coeffs[3] = 1;  
  823.         return;  
  824.     }  
  825.   
  826.     float sum = 0;  
  827.     double y0 = -(x + 3)*FBC_PI*0.25, s0 = sin(y0), c0 = cos(y0);  
  828.     for (int i = 0; i < 8; i++) {  
  829.         double y = -(x + 3 - i)*FBC_PI*0.25;  
  830.         coeffs[i] = (float)((cs[i][0] * s0 + cs[i][1] * c0) / (y*y));  
  831.         sum += coeffs[i];  
  832.     }  
  833.   
  834.     sum = 1.f / sum;  
  835.     for (int i = 0; i < 8; i++) {  
  836.         coeffs[i] *= sum;  
  837.     }  
  838. }  
  839.   
  840. template<typename _Tp, int chs>  
  841. static int resize_nearest(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)  
  842. {  
  843.     Size ssize = src.size();  
  844.     Size dsize = dst.size();  
  845.   
  846.     double fx = (double)dsize.width / ssize.width;  
  847.     double fy = (double)dsize.height / ssize.height;  
  848.   
  849.     AutoBuffer<int> _x_ofs(dsize.width);  
  850.     int* x_ofs = _x_ofs;  
  851.     int pix_size = (int)src.elemSize();  
  852.     int pix_size4 = (int)(pix_size / sizeof(int));  
  853.     double ifx = 1. / fx, ify = 1. / fy;  
  854.   
  855.     for (int x = 0; x < dsize.width; x++) {  
  856.         int sx = fbcFloor(x*ifx);  
  857.         x_ofs[x] = std::min(sx, ssize.width - 1)*pix_size;  
  858.     }  
  859.   
  860.     Range range(0, dsize.height);  
  861.     int x, y;  
  862.   
  863.     for (y = range.start; y < range.end; y++) {  
  864.         uchar* D = dst.data + dst.step*y;  
  865.         int sy = std::min(fbcFloor(y*ify), ssize.height - 1);  
  866.         const uchar* S = src.ptr(sy);  
  867.   
  868.         switch (pix_size) {  
  869.         case 1:  
  870.             for (x = 0; x <= dsize.width - 2; x += 2) {  
  871.                 uchar t0 = S[x_ofs[x]];  
  872.                 uchar t1 = S[x_ofs[x + 1]];  
  873.                 D[x] = t0;  
  874.                 D[x + 1] = t1;  
  875.             }  
  876.   
  877.             for (; x < dsize.width; x++) {  
  878.                 D[x] = S[x_ofs[x]];  
  879.             }  
  880.             break;  
  881.         case 2:  
  882.             for (x = 0; x < dsize.width; x++) {  
  883.                 *(ushort*)(D + x * 2) = *(ushort*)(S + x_ofs[x]);  
  884.             }  
  885.             break;  
  886.         case 3:  
  887.             for (x = 0; x < dsize.width; x++, D += 3) {  
  888.                 const uchar* _tS = S + x_ofs[x];  
  889.                 D[0] = _tS[0]; D[1] = _tS[1]; D[2] = _tS[2];  
  890.             }  
  891.             break;  
  892.         case 4:  
  893.             for (x = 0; x < dsize.width; x++) {  
  894.                 *(int*)(D + x * 4) = *(int*)(S + x_ofs[x]);  
  895.             }  
  896.             break;  
  897.         case 6:  
  898.             for (x = 0; x < dsize.width; x++, D += 6) {  
  899.                 const ushort* _tS = (const ushort*)(S + x_ofs[x]);  
  900.                 ushort* _tD = (ushort*)D;  
  901.                 _tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2];  
  902.             }  
  903.             break;  
  904.         case 8:  
  905.             for (x = 0; x < dsize.width; x++, D += 8) {  
  906.                 const int* _tS = (const int*)(S + x_ofs[x]);  
  907.                 int* _tD = (int*)D;  
  908.                 _tD[0] = _tS[0]; _tD[1] = _tS[1];  
  909.             }  
  910.             break;  
  911.         case 12:  
  912.             for (x = 0; x < dsize.width; x++, D += 12) {  
  913.                 const int* _tS = (const int*)(S + x_ofs[x]);  
  914.                 int* _tD = (int*)D;  
  915.                 _tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2];  
  916.             }  
  917.             break;  
  918.         default:  
  919.             for (x = 0; x < dsize.width; x++, D += pix_size) {  
  920.                 const int* _tS = (const int*)(S + x_ofs[x]);  
  921.                 int* _tD = (int*)D;  
  922.                 for (int k = 0; k < pix_size4; k++)  
  923.                     _tD[k] = _tS[k];  
  924.             }  
  925.         }  
  926.     }  
  927.   
  928.     return 0;  
  929. }  
  930.   
  931. template<typename _Tp, int chs>  
  932. static int resize_linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)  
  933. {  
  934.     Size ssize = src.size();  
  935.     Size dsize = dst.size();  
  936.   
  937.     double inv_scale_x = (double)dsize.width / ssize.width;  
  938.     double inv_scale_y = (double)dsize.height / ssize.height;  
  939.     double scale_x = 1. / inv_scale_x, scale_y = 1. / inv_scale_y;  
  940.   
  941.     int iscale_x = saturate_cast<int>(scale_x);  
  942.     int iscale_y = saturate_cast<int>(scale_y);  
  943.   
  944.     bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;  
  945.     // 在scale_x && scale_y等于2的情况下
  946.     // INTER_AREA(fast)也等于INTER_LINEAR
  947.     if (is_area_fast && iscale_x == 2 && iscale_y == 2) {  
  948.         resize_area(src, dst);  
  949.         return 0;  
  950.     }  
  951.   
  952.     int cn = dst.channels;  
  953.     int k, sx, sy, dx, dy;  
  954.     int xmin = 0, xmax = dsize.width, width = dsize.width*cn;  
  955.     bool fixpt = sizeof(_Tp) == 1 ? true : false;  
  956.     float fx, fy;  
  957.     int ksize = 2, ksize2;  
  958.     ksize2 = ksize / 2;  
  959.   
  960.     AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));  
  961.     int* xofs = (int*)(uchar*)_buffer;  
  962.     int* yofs = xofs + width;  
  963.     float* alpha = (float*)(yofs + dsize.height);  
  964.     short* ialpha = (short*)alpha;  
  965.     float* beta = alpha + width*ksize;  
  966.     short* ibeta = ialpha + width*ksize;  
  967.     float cbuf[MAX_ESIZE];  
  968.   
  969.     for (dx = 0; dx < dsize.width; dx++) {  
  970.         fx = (float)((dx + 0.5)*scale_x - 0.5);  
  971.         sx = fbcFloor(fx);  
  972.         fx -= sx;  
  973.   
  974.         if (sx < ksize2 - 1) {  
  975.             xmin = dx + 1;  
  976.             if (sx < 0) {  
  977.                 fx = 0, sx = 0;  
  978.             }  
  979.         }  
  980.   
  981.         if (sx + ksize2 >= ssize.width) {  
  982.             xmax = std::min(xmax, dx);  
  983.             if (sx >= ssize.width - 1) {  
  984.                 fx = 0, sx = ssize.width - 1;  
  985.             }  
  986.         }  
  987.   
  988.         for (k = 0, sx *= cn; k < cn; k++) {  
  989.             xofs[dx*cn + k] = sx + k;  
  990.         }  
  991.   
  992.         cbuf[0] = 1.f - fx;  
  993.         cbuf[1] = fx;  
  994.   
  995.         if (fixpt) {  
  996.             for (k = 0; k < ksize; k++) {  
  997.                 ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  998.             }  
  999.             for (; k < cn*ksize; k++) {  
  1000.                 ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];  
  1001.             }  
  1002.         } else {  
  1003.             for (k = 0; k < ksize; k++) {  
  1004.                 alpha[dx*cn*ksize + k] = cbuf[k];  
  1005.             }  
  1006.             for (; k < cn*ksize; k++) {  
  1007.                 alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];  
  1008.             }  
  1009.         }  
  1010.     }  
  1011.   
  1012.     for (dy = 0; dy < dsize.height; dy++) {  
  1013.         fy = (float)((dy + 0.5)*scale_y - 0.5);  
  1014.         sy = fbcFloor(fy);  
  1015.         fy -= sy;  
  1016.   
  1017.         yofs[dy] = sy;  
  1018.         cbuf[0] = 1.f - fy;  
  1019.         cbuf[1] = fy;  
  1020.   
  1021.         if (fixpt) {  
  1022.             for (k = 0; k < ksize; k++) {  
  1023.                 ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1024.             }  
  1025.         } else {  
  1026.             for (k = 0; k < ksize; k++) {  
  1027.                 beta[dy*ksize + k] = cbuf[k];  
  1028.             }  
  1029.         }  
  1030.     }  
  1031.   
  1032.     if (sizeof(_Tp) == 1) { // uchar  
  1033.         typedef uchar value_type; // HResizeLinear/VResizeLinear  
  1034.         typedef int buf_type;  
  1035.         typedef short alpha_type;  
  1036.         int ONE = INTER_RESIZE_COEF_SCALE;  
  1037.   
  1038.         resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1039.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);  
  1040.     } else if (sizeof(_Tp) == 4) { // float  
  1041.         typedef float value_type; // HResizeLinear/VResizeLinear  
  1042.         typedef float buf_type;  
  1043.         typedef float alpha_type;  
  1044.         int ONE = 1;  
  1045.   
  1046.         resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1047.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);  
  1048.     } else {  
  1049.         fprintf(stderr, "not support type\n");  
  1050.         return -1;  
  1051.     }  
  1052.   
  1053.     return 0;  
  1054. }  
  1055.   
  1056. template<typename _Tp, int chs>  
  1057. static int resize_cubic(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)  
  1058. {  
  1059.     Size ssize = src.size();  
  1060.     Size dsize = dst.size();  
  1061.   
  1062.     double inv_scale_x = (double)dsize.width / ssize.width;  
  1063.     double inv_scale_y = (double)dsize.height / ssize.height;  
  1064.     double scale_x = 1. / inv_scale_x, scale_y = 1. / inv_scale_y;  
  1065.   
  1066.     int cn = dst.channels;  
  1067.     int k, sx, sy, dx, dy;  
  1068.     int xmin = 0, xmax = dsize.width, width = dsize.width*cn;  
  1069.     bool fixpt = sizeof(_Tp) == 1 ? true : false;  
  1070.     float fx, fy;  
  1071.     int ksize = 4, ksize2;  
  1072.     ksize2 = ksize / 2;  
  1073.   
  1074.     AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));  
  1075.     int* xofs = (int*)(uchar*)_buffer;  
  1076.     int* yofs = xofs + width;  
  1077.     float* alpha = (float*)(yofs + dsize.height);  
  1078.     short* ialpha = (short*)alpha;  
  1079.     float* beta = alpha + width*ksize;  
  1080.     short* ibeta = ialpha + width*ksize;  
  1081.     float cbuf[MAX_ESIZE];  
  1082.   
  1083.     for (dx = 0; dx < dsize.width; dx++) {  
  1084.         fx = (float)((dx + 0.5)*scale_x - 0.5);  
  1085.         sx = fbcFloor(fx);  
  1086.         fx -= sx;  
  1087.   
  1088.         if (sx < ksize2 - 1) {  
  1089.             xmin = dx + 1;  
  1090.         }  
  1091.   
  1092.         if (sx + ksize2 >= ssize.width) {  
  1093.             xmax = std::min(xmax, dx);  
  1094.         }  
  1095.   
  1096.         for (k = 0, sx *= cn; k < cn; k++) {  
  1097.             xofs[dx*cn + k] = sx + k;  
  1098.         }  
  1099.   
  1100.         interpolateCubic<float>(fx, cbuf);  
  1101.   
  1102.         if (fixpt) {  
  1103.             for (k = 0; k < ksize; k++) {  
  1104.                 ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1105.             }  
  1106.             for (; k < cn*ksize; k++) {  
  1107.                 ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];  
  1108.             }  
  1109.         } else {  
  1110.             for (k = 0; k < ksize; k++) {  
  1111.                 alpha[dx*cn*ksize + k] = cbuf[k];  
  1112.             }  
  1113.             for (; k < cn*ksize; k++) {  
  1114.                 alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];  
  1115.             }  
  1116.         }  
  1117.     }  
  1118.   
  1119.     for (dy = 0; dy < dsize.height; dy++) {  
  1120.         fy = (float)((dy + 0.5)*scale_y - 0.5);  
  1121.         sy = cvFloor(fy);  
  1122.         fy -= sy;  
  1123.   
  1124.         yofs[dy] = sy;  
  1125.         interpolateCubic<float>(fy, cbuf);  
  1126.   
  1127.         if (fixpt) {  
  1128.             for (k = 0; k < ksize; k++) {  
  1129.                 ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1130.             }  
  1131.         } else {  
  1132.             for (k = 0; k < ksize; k++) {  
  1133.                 beta[dy*ksize + k] = cbuf[k];  
  1134.             }  
  1135.         }  
  1136.     }  
  1137.   
  1138.     if (sizeof(_Tp) == 1) { // uchar  
  1139.         typedef uchar value_type; // HResizeCubic/VResizeCubic  
  1140.         typedef int buf_type;  
  1141.         typedef short alpha_type;  
  1142.   
  1143.         resizeGeneric_Cubic<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1144.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize);  
  1145.     } else if (sizeof(_Tp) == 4) { // float  
  1146.         typedef float value_type; // HResizeCubic/VResizeCubic  
  1147.         typedef float buf_type;  
  1148.         typedef float alpha_type;  
  1149.   
  1150.         resizeGeneric_Cubic<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1151.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize);  
  1152.     } else {  
  1153.         fprintf(stderr, "not support type\n");  
  1154.         return -1;  
  1155.     }  
  1156.   
  1157.     return 0;  
  1158. }  
  1159.   
  1160. template<typename _Tp, int chs>  
  1161. static int resize_area(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)  
  1162. {  
  1163.     Size ssize = src.size();  
  1164.     Size dsize = dst.size();  
  1165.     int cn = dst.channels;  
  1166.   
  1167.     double inv_scale_x = (double)dsize.width / ssize.width;  
  1168.     double inv_scale_y = (double)dsize.height / ssize.height;  
  1169.     double scale_x = 1. / inv_scale_x, scale_y = 1. / inv_scale_y;  
  1170.   
  1171.     int iscale_x = saturate_cast<int>(scale_x);  
  1172.     int iscale_y = saturate_cast<int>(scale_y);  
  1173.   
  1174.     bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;  
  1175.   
  1176.     int k, sx, sy, dx, dy;  
  1177.   
  1178.     // 仅对于情况(scale_x <= 1 && scale_y <= 1)才实现真实的“区域”插值。
  1179.     // 在其他情况下,使用双线性插值的一些变体进行仿真
  1180.     if (scale_x >= 1 && scale_y >= 1) {  
  1181.         if (is_area_fast) {  
  1182.             int area = iscale_x*iscale_y;  
  1183.             size_t srcstep = src.step / sizeof(_Tp);  
  1184.             AutoBuffer<int> _ofs(area + dsize.width*cn);  
  1185.             int* ofs = _ofs;  
  1186.             int* xofs = ofs + area;  
  1187.   
  1188.             for (sy = 0, k = 0; sy < iscale_y; sy++) {  
  1189.                 for (sx = 0; sx < iscale_x; sx++) {  
  1190.                     ofs[k++] = (int)(sy*srcstep + sx*cn);  
  1191.                 }  
  1192.             }  
  1193.   
  1194.             for (dx = 0; dx < dsize.width; dx++) {  
  1195.                 int j = dx * cn;  
  1196.                 sx = iscale_x * j;  
  1197.                 for (k = 0; k < cn; k++) {  
  1198.                     xofs[j + k] = sx + k;  
  1199.                 }  
  1200.             }  
  1201.   
  1202.             if (sizeof(_Tp) == 1) { // uchar  
  1203.                 typedef uchar T;  
  1204.                 typedef int WT;  
  1205.   
  1206.                 resizeGeneric_AreaFast<_Tp, T, WT, chs>(src, dst, ofs, xofs, iscale_x, iscale_y);  
  1207.             } else if (sizeof(_Tp) == 4) { // float  
  1208.                 typedef float T;  
  1209.                 typedef float WT;  
  1210.   
  1211.                 resizeGeneric_AreaFast<_Tp, T, WT, chs>(src, dst, ofs, xofs, iscale_x, iscale_y);  
  1212.             } else {  
  1213.                 fprintf(stderr, "not support type\n");  
  1214.                 return -1;  
  1215.             }  
  1216.   
  1217.             return 0;  
  1218.         }  
  1219.   
  1220.         FBC_Assert(cn <= 4);  
  1221.   
  1222.         AutoBuffer<DecimateAlpha> _xytab((ssize.width + ssize.height) * 2);  
  1223.         DecimateAlpha* xtab = _xytab, *ytab = xtab + ssize.width * 2;  
  1224.   
  1225.         int xtab_size = computeResizeAreaTab<int>(ssize.width, dsize.width, cn, scale_x, xtab);  
  1226.         int ytab_size = computeResizeAreaTab<int>(ssize.height, dsize.height, 1, scale_y, ytab);  
  1227.   
  1228.         AutoBuffer<int> _tabofs(dsize.height + 1);  
  1229.         int* tabofs = _tabofs;  
  1230.         for (k = 0, dy = 0; k < ytab_size; k++) {  
  1231.             if (k == 0 || ytab[k].di != ytab[k - 1].di) {  
  1232.                 assert(ytab[k].di == dy);  
  1233.                 tabofs[dy++] = k;  
  1234.             }  
  1235.         }  
  1236.         tabofs[dy] = ytab_size;  
  1237.   
  1238.         if (sizeof(_Tp) == 1) { // uchar  
  1239.             typedef uchar T;  
  1240.             typedef float WT;  
  1241.   
  1242.             resizeGeneric_Area<_Tp, T, WT, chs>(src, dst, xtab, xtab_size, ytab, ytab_size, tabofs);  
  1243.         } else if (sizeof(_Tp) == 4) { // float  
  1244.             typedef float T;  
  1245.             typedef float WT;  
  1246.   
  1247.             resizeGeneric_Area<_Tp, T, WT, chs>(src, dst, xtab, xtab_size, ytab, ytab_size, tabofs);  
  1248.         } else {  
  1249.             fprintf(stderr, "not support type\n");  
  1250.             return -1;  
  1251.         }  
  1252.   
  1253.         return 0;  
  1254.     }  
  1255.   
  1256.     int xmin = 0, xmax = dsize.width, width = dsize.width*cn;  
  1257.     bool fixpt = sizeof(_Tp) == 1 ? true : false;  
  1258.     float fx, fy;  
  1259.     int ksize = 2, ksize2;  
  1260.     ksize2 = ksize / 2;  
  1261.   
  1262.     AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));  
  1263.     int* xofs = (int*)(uchar*)_buffer;  
  1264.     int* yofs = xofs + width;  
  1265.     float* alpha = (float*)(yofs + dsize.height);  
  1266.     short* ialpha = (short*)alpha;  
  1267.     float* beta = alpha + width*ksize;  
  1268.     short* ibeta = ialpha + width*ksize;  
  1269.     float cbuf[MAX_ESIZE];  
  1270.   
  1271.     for (dx = 0; dx < dsize.width; dx++) {  
  1272.         sx = fbcFloor(dx*scale_x);  
  1273.         fx = (float)((dx + 1) - (sx + 1)*inv_scale_x);  
  1274.         fx = fx <= 0 ? 0.f : fx - fbcFloor(fx);  
  1275.   
  1276.         if (sx < ksize2 - 1) {  
  1277.             xmin = dx + 1;  
  1278.             if (sx < 0) {  
  1279.                 fx = 0, sx = 0;  
  1280.             }  
  1281.         }  
  1282.   
  1283.         if (sx + ksize2 >= ssize.width) {  
  1284.             xmax = std::min(xmax, dx);  
  1285.             if (sx >= ssize.width - 1) {  
  1286.                 fx = 0, sx = ssize.width - 1;  
  1287.             }  
  1288.         }  
  1289.   
  1290.         for (k = 0, sx *= cn; k < cn; k++) {  
  1291.             xofs[dx*cn + k] = sx + k;  
  1292.         }  
  1293.   
  1294.         cbuf[0] = 1.f - fx;  
  1295.         cbuf[1] = fx;  
  1296.   
  1297.         if (fixpt) {  
  1298.             for (k = 0; k < ksize; k++) {  
  1299.                 ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1300.             }  
  1301.             for (; k < cn*ksize; k++) {  
  1302.                 ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];  
  1303.             }  
  1304.         } else {  
  1305.             for (k = 0; k < ksize; k++) {  
  1306.                 alpha[dx*cn*ksize + k] = cbuf[k];  
  1307.             }  
  1308.             for (; k < cn*ksize; k++) {  
  1309.                 alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];  
  1310.             }  
  1311.         }  
  1312.     }  
  1313.   
  1314.     for (dy = 0; dy < dsize.height; dy++) {  
  1315.         sy = fbcFloor(dy*scale_y);  
  1316.         fy = (float)((dy + 1) - (sy + 1)*inv_scale_y);  
  1317.         fy = fy <= 0 ? 0.f : fy - fbcFloor(fy);  
  1318.   
  1319.         yofs[dy] = sy;  
  1320.         cbuf[0] = 1.f - fy;  
  1321.         cbuf[1] = fy;  
  1322.   
  1323.         if (fixpt) {  
  1324.             for (k = 0; k < ksize; k++) {  
  1325.                 ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1326.             }  
  1327.         } else {  
  1328.             for (k = 0; k < ksize; k++) {  
  1329.                 beta[dy*ksize + k] = cbuf[k];  
  1330.             }  
  1331.         }  
  1332.     }  
  1333.   
  1334.     if (sizeof(_Tp) == 1) { // uchar  
  1335.         typedef uchar value_type; // HResizeLinear/VResizeLinear  
  1336.         typedef int buf_type;  
  1337.         typedef short alpha_type;  
  1338.         int ONE = INTER_RESIZE_COEF_SCALE;  
  1339.   
  1340.         resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1341.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);  
  1342.     } else if (sizeof(_Tp) == 4) { // float  
  1343.         typedef float value_type; // HResizeLinear/VResizeLinear  
  1344.         typedef float buf_type;  
  1345.         typedef float alpha_type;  
  1346.         int ONE = 1;  
  1347.   
  1348.         resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1349.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);  
  1350.     } else {  
  1351.         fprintf(stderr, "not support type\n");  
  1352.         return -1;  
  1353.     }  
  1354.   
  1355.     return 0;  
  1356. }  
  1357.   
  1358. template<typename _Tp, int chs>  
  1359. static int resize_lanczos4(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)  
  1360. {  
  1361.     Size ssize = src.size();  
  1362.     Size dsize = dst.size();  
  1363.   
  1364.     double inv_scale_x = (double)dsize.width / ssize.width;  
  1365.     double inv_scale_y = (double)dsize.height / ssize.height;  
  1366.     double scale_x = 1. / inv_scale_x, scale_y = 1. / inv_scale_y;  
  1367.   
  1368.     int cn = dst.channels;  
  1369.     int k, sx, sy, dx, dy;  
  1370.     int xmin = 0, xmax = dsize.width, width = dsize.width*cn;  
  1371.     bool fixpt = sizeof(_Tp) == 1 ? true : false;  
  1372.     float fx, fy;  
  1373.     int ksize = 8, ksize2;  
  1374.     ksize2 = ksize / 2;  
  1375.   
  1376.     AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));  
  1377.     int* xofs = (int*)(uchar*)_buffer;  
  1378.     int* yofs = xofs + width;  
  1379.     float* alpha = (float*)(yofs + dsize.height);  
  1380.     short* ialpha = (short*)alpha;  
  1381.     float* beta = alpha + width*ksize;  
  1382.     short* ibeta = ialpha + width*ksize;  
  1383.     float cbuf[MAX_ESIZE];  
  1384.   
  1385.     for (dx = 0; dx < dsize.width; dx++) {  
  1386.         fx = (float)((dx + 0.5)*scale_x - 0.5);  
  1387.         sx = fbcFloor(fx);  
  1388.         fx -= sx;  
  1389.   
  1390.         if (sx < ksize2 - 1) {  
  1391.             xmin = dx + 1;  
  1392.         }  
  1393.   
  1394.         if (sx + ksize2 >= ssize.width) {  
  1395.             xmax = std::min(xmax, dx);  
  1396.         }  
  1397.   
  1398.         for (k = 0, sx *= cn; k < cn; k++) {  
  1399.             xofs[dx*cn + k] = sx + k;  
  1400.         }  
  1401.   
  1402.         interpolateLanczos4<float>(fx, cbuf);  
  1403.   
  1404.         if (fixpt) {  
  1405.             for (k = 0; k < ksize; k++)  
  1406.                 ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1407.             for (; k < cn*ksize; k++)  
  1408.                 ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];  
  1409.         } else {  
  1410.             for (k = 0; k < ksize; k++)  
  1411.                 alpha[dx*cn*ksize + k] = cbuf[k];  
  1412.             for (; k < cn*ksize; k++)  
  1413.                 alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];  
  1414.         }  
  1415.     }  
  1416.   
  1417.     for (dy = 0; dy < dsize.height; dy++) {  
  1418.         fy = (float)((dy + 0.5)*scale_y - 0.5);  
  1419.         sy = fbcFloor(fy);  
  1420.         fy -= sy;  
  1421.   
  1422.         yofs[dy] = sy;  
  1423.   
  1424.         interpolateLanczos4<float>(fy, cbuf);  
  1425.   
  1426.         if (fixpt){  
  1427.             for (k = 0; k < ksize; k++)  
  1428.                 ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);  
  1429.         } else {  
  1430.             for (k = 0; k < ksize; k++)  
  1431.                 beta[dy*ksize + k] = cbuf[k];  
  1432.         }  
  1433.     }  
  1434.   
  1435.     if (sizeof(_Tp) == 1) { // uchar  
  1436.         typedef uchar value_type; // HResizeLanczos4/VResizeLanczos4  
  1437.         typedef int buf_type;  
  1438.         typedef short alpha_type;  
  1439.   
  1440.         resizeGeneric_Lanczos4<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1441.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize);  
  1442.     } else if (sizeof(_Tp) == 4) { // float  
  1443.         typedef float value_type; // HResizeLanczos4/VResizeLanczos4  
  1444.         typedef float buf_type;  
  1445.         typedef float alpha_type;  
  1446.   
  1447.         resizeGeneric_Lanczos4<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,  
  1448.             xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize);  
  1449.     } else {  
  1450.         fprintf(stderr, "not support type\n");  
  1451.         return -1;  
  1452.     }  
  1453.   
  1454.     return 0;  
  1455. }  
  1456.   
  1457. // namespace fbc  
  1458.   
  1459. #endif // FBC_CV_RESIZE_HPP_  

 

除特别注明外,本站所有文章均为 赢咖4注册 原创,转载请注明出处来自OpenCV代码提取:resize函数的实现

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]