三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法

三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法在数学上 双线性插值是有两个变量的插值函数的线性插值扩展 其核心思想是在两个方向分别进行一次线性插值

线性插值

先讲一下线性插值:已知数据 (x0, y0) 与 (x1, y1),要计算 [x0, x1] 区间内某一位置 x 在直线上的y值(反过来也是一样,略):

yy0xx0=y1y0x1x0

y=x1xx1x0y0+xx0x1x0y1

上面比较好理解吧,仔细看就是用x和x0,x1的距离作为一个权重,用于y0和y1的加权。双线性插值本质上就是在两个方向上做线性插值。

双线性插值

在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值[1]。见下图:

这里写图片描述

假如我们想得到未知函数 f 在点 P = (x, y) 的值,假设我们已知函数 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四个点的值。最常见的情况,f就是一个像素点的像素值。首先在 x 方向进行线性插值,得到

这里写图片描述
这里写图片描述

然后在 y 方向进行线性插值,得到

这里写图片描述

综合起来就是双线性插值最后的结果:

这里写图片描述
这里写图片描述

这个要重点说一下,源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素,假设你需要将一幅5×5的图像缩小成3×3,那么源图像和目标图像各个像素之间的对应关系如下。如果没有这个中心对齐,根据基本公式去算,就会得到左边这样的结果;而用了对齐,就会得到右边的结果:

这里写图片描述这里写图片描述

cv::Mat matSrc, matDst1, matDst2; matSrc = cv::imread("lena.jpg", 2 | 4); matDst1 = cv::Mat(cv::Size(800, 1000), matSrc.type(), cv::Scalar::all(0)); matDst2 = cv::Mat(matDst1.size(), matSrc.type(), cv::Scalar::all(0)); double scale_x = (double)matSrc.cols / matDst1.cols; double scale_y = (double)matSrc.rows / matDst1.rows; uchar* dataDst = matDst1.data; int stepDst = matDst1.step; uchar* dataSrc = matSrc.data; int stepSrc = matSrc.step; int iWidthSrc = matSrc.cols; int iHiehgtSrc = matSrc.rows; for (int j = 0; j < matDst1.rows; ++j) { float fy = (float)((j + 0.5) * scale_y - 0.5); int sy = cvFloor(fy); fy -= sy; sy = std::min(sy, iHiehgtSrc - 2); sy = std::max(0, sy); short cbufy[2]; cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048); cbufy[1] = 2048 - cbufy[0]; for (int i = 0; i < matDst1.cols; ++i) { float fx = (float)((i + 0.5) * scale_x - 0.5); int sx = cvFloor(fx); fx -= sx; if (sx < 0) { fx = 0, sx = 0; } if (sx >= iWidthSrc - 1) { fx = 0, sx = iWidthSrc - 2; } short cbufx[2]; cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048); cbufx[1] = 2048 - cbufx[0]; for (int k = 0; k < matSrc.channels(); ++k) { *(dataDst+ j*stepDst + 3*i + k) = (*(dataSrc + sy*stepSrc + 3*sx + k) * cbufx[0] * cbufy[0] + *(dataSrc + (sy+1)*stepSrc + 3*sx + k) * cbufx[0] * cbufy[1] + *(dataSrc + sy*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[0] + *(dataSrc + (sy+1)*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[1]) >> 22; } } } cv::imwrite("linear_1.jpg", matDst1); cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1); cv::imwrite("linear_2.jpg", matDst2); 

好了,本篇到这里,欢迎大家分享转载,注明出处即可。

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205987.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午4:44
下一篇 2026年3月19日 下午4:44


相关推荐

  • OpenClaw 3.8重磅发布,修复200多个bug

    OpenClaw 3.8重磅发布,修复200多个bug

    2026年3月16日
    2
  • matlab2016a下载包及安装教程

    matlab2016a下载包及安装教程链接:https://pan.baidu.com/s/1wMGK5jYxYdqs1IxRDfJl8A 提取码:y72e 复制这段内容后打开百度网盘手机App,操作更方便哦1 下载R2016a_win64.iso(安装文件,包括part1以及part2两部分,只需解压part1)及Matlab2016aWin64Crack.rar(破解文件),百度云盘的提取地址及密码如上所示2 解…

    2022年5月25日
    50
  • bp神经网络应用实例(简述bp神经网络)

    原理clear;clc;TestSamNum=20;%学习样本数量ForcastSamNum=2;%预测样本数量HiddenUnitNum=8;%隐含层InDim=3;%输入层OutDim=2;…

    2022年4月15日
    140
  • java8 Lambda Stream collect Collectors 常用详细实例代码汇总

    java8 Lambda Stream collect Collectors 常用详细实例代码汇总Collectorsto collect Collectors toList List amp amp amp amp amp amp amp amp amp amp amp amp amp amp amp lt Integer amp amp amp amp amp amp amp amp amp amp amp amp amp amp amp gt collectList Stream of 1 2 3

    2026年3月19日
    2
  • opencv滤波、图像形运算、Sober算子

    opencv滤波、图像形运算、Sober算子1.opencv中滤波操作:ksize必须是奇数1.均值操作:选定图像上的行数和列数,求出总和,除以总个数,然后将这个数放到这个选定区的中间区域中。数学表达式:4上的值=(5+6+6+7+4+…..+55)/25;函数:result=cv2.blur(src,ksize)importcv2o=cv2.imread(‘D:\cc1\lenacolor.png’)#进行图片的读取s1=cv2.blur(o,(10,10))#进行均值操作cv2.imshow(‘oringle’,o)#进行

    2022年7月14日
    20
  • xshell 连接虚拟机「建议收藏」

    xshell 连接虚拟机「建议收藏」首先先下载Xshell无论什么版本的Xshell都可以再用Xshell连接虚拟机的时候首先你需要在虚拟机里面查看自己的ip如图所示输入命令ipa 拿到这个ip之后在Xshell里面新建会话 把ip输入进去。然后左边有一个登录验证点击进去验证你在虚拟机上面的登录账号和密码然后连接最后接受验证就可以啦…

    2026年2月16日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号