之前在http://blog.csdn.net/fengbingchun/article/details/17335477 中有过对cv::resize函数五种插值算法的介绍。这里将OpenCV3.1中五种插值算法的代码进行了提取调整。支持N通道uchar和float类型。经测试,与OpenCV3.1结果完全一致。
实现代码resize.hpp:
// fbc_cv is free software and uses the same licence as OpenCV// Email: fengbingchun@163.com#ifndef FBC_CV_RESIZE_HPP_#define FBC_CV_RESIZE_HPP_/* reference: imgproc/include/opencv2/imgproc.hpp imgproc/src/imgwarp.cpp*/#include "core/mat.hpp"#include "core/base.hpp"#include "core/saturate.hpp"#include "core/utility.hpp"#include "imgproc.hpp"namespace fbc {
static const int MAX_ESIZE = 16;// interpolation formulas and tablesconst int INTER_RESIZE_COEF_BITS = 11;const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;template<typename _Tp, int chs> static int resize_nearest(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);template<typename _Tp, int chs> static int resize_linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);template<typename _Tp, int chs> static int resize_cubic(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);template<typename _Tp, int chs> static int resize_area(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);template<typename _Tp, int chs> static int resize_lanczos4(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);// resize the image src down to or up to the specified size// support type: uchar/floattemplate<typename _Tp, int chs>int resize(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, int interpolation = NTER_LINEAR){ FBC_Assert((interpolation >= 0) && (interpolation < 5)); FBC_Assert((src.rows >= 4 && src.cols >= 4) && (dst.rows >= 4 && dst.cols >= 4)); FBC_Assert((sizeof(_Tp) == 1) || sizeof(_Tp) == 4); // uchar || float Size ssize = src.size(); Size dsize = dst.size(); if (dsize == ssize) { // Source and destination are of same size. Use simple copy. src.copyTo(dst); return 0; } switch (interpolation) { case 0: { resize_nearest(src, dst); break; } case 1: { resize_linear(src, dst); break; } case 2: { resize_cubic(src, dst); break; } case 3: { resize_area(src, dst); break; } case 4: { resize_lanczos4(src, dst); break; } default: return -1; } return 0;}struct DecimateAlpha{
int si, di; float alpha;};template<typename type>static int computeResizeAreaTab(int ssize, int dsize, int cn, double scale, DecimateAlpha* tab){ int k = 0; for (int dx = 0; dx < dsize; dx++) { double fsx1 = dx * scale; double fsx2 = fsx1 + scale; double cellWidth = std::min(scale, ssize - fsx1); int sx1 = fbcCeil(fsx1), sx2 = fbcFloor(fsx2); sx2 = std::min(sx2, ssize - 1); sx1 = std::min(sx1, sx2); if (sx1 - fsx1 > 1e-3) { assert(k < ssize * 2); tab[k].di = dx * cn; tab[k].si = (sx1 - 1) * cn; tab[k++].alpha = (float)((sx1 - fsx1) / cellWidth); } for (int sx = sx1; sx < sx2; sx++) { assert(k < ssize * 2); tab[k].di = dx * cn; tab[k].si = sx * cn; tab[k++].alpha = float(1.0 / cellWidth); } if (fsx2 - sx2 > 1e-3) { assert(k < ssize * 2); tab[k].di = dx * cn; tab[k].si = sx2 * cn; tab[k++].alpha = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth); } } return k;}template<typename ST, typename DT> struct Cast{
typedef ST type1; typedef DT rtype; DT operator()(ST val) const { return saturate_cast<DT>(val); }};template<typename ST, typename DT, int bits> struct FixedPtCast{
typedef ST type1; typedef DT rtype; enum { SHIFT = bits, DELTA = 1 << (bits - 1) }; DT operator()(ST val) const { return saturate_cast<DT>((val + DELTA) >> SHIFT); }};template<typename type>static type clip(type x, type a, type b){ return x >= a ? (x < b ? x : b - 1) : a;}template<typename T, typename WT, typename AT>struct HResizeLinear{
typedef T value_type; typedef WT buf_type; typedef AT alpha_type; void operator()(const T** src, WT** dst, int count, const int* xofs, const AT* alpha, int swidth, int dwidth, int cn, int xmin, int xmax, int ONE) const { int dx, k; int dx0 = 0; for (k = 0; k <= count - 2; k++) { const T *S0 = src[k], *S1 = src[k + 1]; WT *D0 = dst[k], *D1 = dst[k + 1]; for (dx = dx0; dx < xmax; dx++) { int sx = xofs[dx]; WT a0 = alpha[dx * 2], a1 = alpha[dx * 2 + 1]; WT t0 = S0[sx] * a0 + S0[sx + cn] * a1; WT t1 = S1[sx] * a0 + S1[sx + cn] * a1; D0[dx] = t0; D1[dx] = t1; } for (; dx < dwidth; dx++) { int sx = xofs[dx]; D0[dx] = WT(S0[sx] * ONE); D1[dx] = WT(S1[sx] * ONE); } } for (; k < count; k++) { const T *S = src[k]; WT *D = dst[k]; for (dx = 0; dx < xmax; dx++) { int sx = xofs[dx]; D[dx] = S[sx] * alpha[dx * 2] + S[sx + cn] * alpha[dx * 2 + 1]; } for (; dx < dwidth; dx++) { D[dx] = WT(S[xofs[dx]] * ONE); } } }};template<typename T, typename WT, typename AT, class CastOp>struct VResizeLinear{
typedef T value_type; typedef WT buf_type; typedef AT alpha_type; void operator()(const WT** src, T* dst, const AT* beta, int width) const { WT b0 = beta[0], b1 = beta[1]; const WT *S0 = src[0], *S1 = src[1]; CastOp castOp; int x = 0; for (; x <= width - 4; x += 4) { WT t0, t1; t0 = S0[x] * b0 + S1[x] * b1; t1 = S0[x + 1] * b0 + S1[x + 1] * b1; dst[x] = castOp(t0); dst[x + 1] = castOp(t1); t0 = S0[x + 2] * b0 + S1[x + 2] * b1; t1 = S0[x + 3] * b0 + S1[x + 3] * b1; dst[x + 2] = castOp(t0); dst[x + 3] = castOp(t1); } for (; x < width; x++) { dst[x] = castOp(S0[x] * b0 + S1[x] * b1); } }};template<>struct VResizeLinear<uchar, int, short, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>>{
typedef uchar value_type; typedef int buf_type; typedef short alpha_type; void operator()(const buf_type** src, value_type* dst, const alpha_type* beta, int width) const { alpha_type b0 = beta[0], b1 = beta[1]; const buf_type *S0 = src[0], *S1 = src[1]; int x = 0; for (; x <= width - 4; x += 4) { dst[x + 0] = uchar((((b0 * (S0[x + 0] >> 4)) >> 16) + ((b1 * (S1[x + 0] >> 4)) >> 16) + 2) >> 2); dst[x + 1] = uchar((((b0 * (S0[x + 1] >> 4)) >> 16) + ((b1 * (S1[x + 1] >> 4)) >> 16) + 2) >> 2); dst[x + 2] = uchar((((b0 * (S0[x + 2] >> 4)) >> 16) + ((b1 * (S1[x + 2] >> 4)) >> 16) + 2) >> 2); dst[x + 3] = uchar((((b0 * (S0[x + 3] >> 4)) >> 16) + ((b1 * (S1[x + 3] >> 4)) >> 16) + 2) >> 2); } for (; x < width; x++) { dst[x] = uchar((((b0 * (S0[x] >> 4)) >> 16) + ((b1 * (S1[x] >> 4)) >> 16) + 2) >> 2); } }};template<typename T, typename WT, typename AT>struct HResizeCubic{
typedef T value_type; typedef WT buf_type; typedef AT alpha_type;