插值(Interpolation)

article/2025/10/2 17:25:50

前言

插值计算普遍存在于图像处理中,最近在做畸变优化时,看了一些资料中提到了插值&双线性插值,开始没明白,觉得一定很难,直接跳过,到最终写代码时,又不得不使用.于是就这里对这个功能进行学习,记录,并使用vs2017进行实际验证,验证后发现这个原理其实并不复杂.

插值

:n(xk,yk),k=1,2,...,n.xxk,k=1,2,...,n,xy
f(x)[a,b].x1,x2,x3...xn,[a,b]nG
Gg(x):g(xi)=f(xi),k=1,2,...n,g(x)f(x)x1,x2,x3...xn,G.
(这里听起来就不太好理解,暂时心里有点印象即可,后面会对这个进行举例说明).
在数值分析的数学领域,插值是在已知数据点的离散集合的范围内构建新的数据点的方法.例如在图片放大时,如果直接放大2倍,那么就会出现有很多像素点为空的情况,这时候就需要对这些空值进行填充,插值广泛的引用到图像处理当中.

线性插值

线性插值介绍

线LA(x0,y0),B(x1,y1),C线L,Cx,y,:
这里写图片描述
tanBAD=|CE||AE|=|BD||AD|yy0xx0=y1y0x1x0, :
y=x1xx1x0y0+xx0x1x0y1
y0y1k1,k2,yy0y1:
y=k1y0+k2y1
同时可以看出C离A,B哪个点越近,哪个点的权重系数k值就越大,最终y值受它的影响也越大.

线性插值验证

假设直线L:y=2x+1,点A(1,3),点B(3,7)在直线L上.若有一点C,X轴坐标为2,求点C的坐标.
这里验证较为简单,将数据带入公式①中可得C为(2,5),此点满足y=2x+1.

双线性插值&多线性插值

双线性插值介绍

双线性插值是对线性插值的扩展,主要用于2D图像处理中,”双”是指在两个方向上进行分别进行线性插值,关键思想是先在一个方向上进行线性插值,然后在另一个方向上进行线性插值(这2个方向进行线性插值的顺序可以颠倒).这里直接引用维基百科中的图片,然后对算法描述
这里写图片描述
,Q11(x1,y1),Q21(x2,y1),Q12(x1,y2),Q22(x2,y2),P(x,y)f(x,y).
我们首先在x方向进行两次线性插值(步骤与上节”线性插值介绍”一致),得出结果:
f(x,y1)x2xx2x1f(Q11)+xx1x2x1f(Q21)
f(x,y2)x2xx2x1f(Q12)+xx1x2x1f(Q22)
我们继续在y方向插值以获得所需的估计:
这里写图片描述
请注意,如果首先沿着y方向,然后沿x方向进行插值,我们将得到相同的结果。

这里总共进行了2次X轴的线性插值和1次Y轴的线性插值.

双线性插值验证

这里以维基百科上的图片,添加了一些辅助信息:
这里写图片描述
如上图中所示,已知:
Q11(14,21)162
Q21(15,21)95
Q12(14,20)91
Q22(15,20)210
:P(14.5,20.2)?
步骤是这样的:

  • 处理X轴方向的线性插值,这里包括两个插值过程.
    • Q11Q21线线,P11(14.5,21):
      P11(14.5,21)=1514.51514×162+14.5141514×95=128.5
    • Q12Q22线线,P12(14.5,20):
      P12(14.5,20)=1514.51514×91+14.5141514×210=150.5
  • X,Y线,P11(14.5,21)P12(14.5,20)线,P(14.5,20.2):
    P(14.5,20.2)=2120.22120×150.5+20.2202120×128.5=146.1

上面这个双线性计算的步骤,建议手动算一遍,确保理解了之前的线性插值,以及双线性插值,对后面代码实例中图片的处理会有很大的帮助,同时有利于理解三线性插值,因为双线性插值相对于线性插值上的步骤与三线性插值相对于双线性插值的意义是一样的.

插值的使用

我们对原图进行放大两倍的操作,以不使用插值算法和使用双线性插值算法进行比较,来说明插值在处理图像时的优势.

原理说明

图片由MxN个像素组成,这里将原图分割成若干个3x3方格,对其进行扩大两倍的操作进行说明:
这里写图片描述
其中’●’表示扩大前的像素点,’X’为扩大后需要填充的像素点,无线性插值的情况,这里填充像素为0(即黑色),线性插值的情况类似与本文上小节中介绍”双线性插值验证”那样,即 Q11,Q21,Q12,Q22 通过线性插值计算出,P1,P2,P3,P4的像素,在通过双线性插值计算出P5点的像素,其他四个区域同理,然后将这种3x3方格推广到整个图片区域(MxN)中,完成线性插值的工作.

代码实现

这里使用Visual Studio 2017工具,基于MFC,制作了一个工程,有需要的可以到这里下载使用,主要代码如下:

...(省略无关部分)//加载并显示原图CPaintDC paint_dc(this);CDC dcMem;BITMAP bit_map;dcMem.CreateCompatibleDC(&paint_dc);origin_bitmap.LoadBitmap(IDB_BITMAP1);origin_bitmap.GetBitmap(&bit_map);CBitmap *pbmpOld = dcMem.SelectObject(&origin_bitmap);paint_dc.StretchBlt(10, 10, bit_map.bmWidth, bit_map.bmHeight, &dcMem, 0, 0, bit_map.bmWidth, bit_map.bmHeight, SRCCOPY);dcMem.SelectObject(pbmpOld);dcMem.DeleteDC();CDialogEx::OnPaint();CImage origin_image;HBITMAP hbmp = (HBITMAP)origin_bitmap.GetSafeHandle();origin_image.Attach(hbmp);//获取图片宽和高int width = origin_image.GetWidth();int height = origin_image.GetHeight();//每张图片显示的间隔.int picture_interval = 50;CDC *pDC = GetDC();        COLORREF color;COLORREF clr;int ***origin_pixel;origin_pixel = new int **[RGB_TYPES];for( int i=0; i<RGB_TYPES; i++ ){origin_pixel[i] = new int *[width];for( int j=0; j<width; j++ ){origin_pixel[i][j] = new int [height];}}//获取原图像的所有像素for (int i = 0; i<width; i++){for (int j = 0; j<height; j++){color = origin_image.GetPixel(i, j);origin_pixel[RGB_R][i][j] = GetRValue(color);origin_pixel[RGB_G][i][j] = GetGValue(color);origin_pixel[RGB_B][i][j] = GetBValue(color);}}int ***large_2_pixel;large_2_pixel = new int **[RGB_TYPES];for (int i = 0; i<3; i++){large_2_pixel[i] = new int *[width*2];for (int j = 0; j<width*2; j++){large_2_pixel[i][j] = new int[height * 2];}}for(int index = 0; index < RGB_TYPES;index++){for (int i = 0; i<width*2; i++){for (int j = 0; j<height*2; j++){large_2_pixel[index][i][j] = 0x00;//默认填充黑色}}}//将图片放大两倍后的像素表for (int i = 0; i<width; i++){for (int j = 0; j<height; j++){large_2_pixel[RGB_R][i * 2][j * 2] = origin_pixel[RGB_R][i][j];large_2_pixel[RGB_G][i * 2][j * 2] = origin_pixel[RGB_G][i][j];large_2_pixel[RGB_B][i * 2][j * 2] = origin_pixel[RGB_B][i][j];}}//显示被放大两倍后未进行插值处理的图片for (int i = 0; i<width * 2; i++){for (int j = 0; j<height * 2; j++){int r_pixel, g_pixel, b_pixel;r_pixel = large_2_pixel[RGB_R][i][j];g_pixel = large_2_pixel[RGB_G][i][j];b_pixel = large_2_pixel[RGB_B][i][j];clr = RGB(r_pixel, g_pixel, b_pixel);//逐个像素点绘制pDC->SetPixel(i+width+picture_interval, j+10, clr);}}//对放大两倍的图片进行线性&双线性插值处理,方格3x3int ***bilinear_interpolation_pixel = large_2_pixel;for (int i = 0; i<width * 2 - 2; i += 2){for (int j = 0; j<height * 2 - 2; j += 2){bilinear_interpolation_pixel[RGB_R][i][j + 1] = (bilinear_interpolation_pixel[RGB_R][i][j] + bilinear_interpolation_pixel[RGB_R][i][j + 2]) / 2;bilinear_interpolation_pixel[RGB_R][i + 2][j + 1] = (bilinear_interpolation_pixel[RGB_R][i + 2][j] + bilinear_interpolation_pixel[RGB_R][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_R][i + 1][j] = (bilinear_interpolation_pixel[RGB_R][i][j] + bilinear_interpolation_pixel[RGB_R][i + 2][j]) / 2;bilinear_interpolation_pixel[RGB_R][i + 1][j + 2] = (bilinear_interpolation_pixel[RGB_R][i][j + 2] + bilinear_interpolation_pixel[RGB_R][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_R][i + 1][j + 1] = (bilinear_interpolation_pixel[RGB_R][i + 1][j] + bilinear_interpolation_pixel[RGB_R][i + 1][j + 2]) / 2;bilinear_interpolation_pixel[RGB_G][i][j + 1] = (bilinear_interpolation_pixel[RGB_G][i][j] + bilinear_interpolation_pixel[RGB_G][i][j + 2]) / 2;bilinear_interpolation_pixel[RGB_G][i + 2][j + 1] = (bilinear_interpolation_pixel[RGB_G][i + 2][j] + bilinear_interpolation_pixel[RGB_G][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_G][i + 1][j] = (bilinear_interpolation_pixel[RGB_G][i][j] + bilinear_interpolation_pixel[RGB_G][i + 2][j]) / 2;bilinear_interpolation_pixel[RGB_G][i + 1][j + 2] = (bilinear_interpolation_pixel[RGB_G][i][j + 2] + bilinear_interpolation_pixel[RGB_G][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_G][i + 1][j + 1] = (bilinear_interpolation_pixel[RGB_G][i + 1][j] + bilinear_interpolation_pixel[RGB_G][i + 1][j + 2]) / 2;bilinear_interpolation_pixel[RGB_B][i][j + 1] = (bilinear_interpolation_pixel[RGB_B][i][j] + bilinear_interpolation_pixel[RGB_B][i][j + 2]) / 2;bilinear_interpolation_pixel[RGB_B][i + 2][j + 1] = (bilinear_interpolation_pixel[RGB_B][i + 2][j] + bilinear_interpolation_pixel[RGB_B][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_B][i + 1][j] = (bilinear_interpolation_pixel[RGB_B][i][j] + bilinear_interpolation_pixel[RGB_B][i + 2][j]) / 2;bilinear_interpolation_pixel[RGB_B][i + 1][j + 2] = (bilinear_interpolation_pixel[RGB_B][i][j + 2] + bilinear_interpolation_pixel[RGB_B][i + 2][j + 2]) / 2;bilinear_interpolation_pixel[RGB_B][i + 1][j + 1] = (bilinear_interpolation_pixel[RGB_B][i + 1][j] + bilinear_interpolation_pixel[RGB_B][i + 1][j + 2]) / 2;}}//显示经过线性&双线性插值处理后的图片for (int i = 0; i<width * 2; i++){for (int j = 0; j<height * 2; j++){int r_pixel, g_pixel, b_pixel;r_pixel = large_2_pixel[RGB_R][i][j];g_pixel = large_2_pixel[RGB_G][i][j];b_pixel = large_2_pixel[RGB_B][i][j];clr = RGB(r_pixel, g_pixel, b_pixel);//逐个像素点绘制pDC->SetPixel(i + width + picture_interval + width*2 + picture_interval, j + 10, clr); }}//释放占用的资源for( int i=0; i<3; i++ ){for( int j=0; j<width * 2; j++ ){delete bilinear_interpolation_pixel[i][j];}delete bilinear_interpolation_pixel[i];}delete bilinear_interpolation_pixel;ReleaseDC(pDC);         origin_image.Detach();
...(省略无关部分)

效果展示

如下图所示,左边是原图,中间的是原图放大2倍后未进行插值的图片,右边是原图放大2倍后进行双线性插值的图片:
这里写图片描述
很明显看出,未经过任何处理的放大后的图(中间)与原图(最左边)匹配度低,经过双线性插值的图片(最右边)与原图(最左边)匹配度很高.
最后想说的是CSDN里的markdown使用MathJax渲染真是不顺手,整理数学公式比整理思路时间还多!

参考资料

Linear interpolation
Bilinear interpolation
image-interpolation
digital-photo-enlargement


http://chatgpt.dhexx.cn/article/DXl51bau.shtml

相关文章

三点线性插值

问题&#xff1a; 在三角形的三个顶点具有3个不同颜色&#xff0c;如何通过插值计算出三角形中每个点的颜色&#xff1f; 应用实例&#xff1a;高洛德着色使用3个顶点的颜色进行线性插值&#xff0c;结果如下图&#xff1a; 解决方案&#xff1a; 显然&#xff0c;无论是线性…

线性插值和双线性插值

最近在学数字图像处理中旋转变换的问题,发现旋转以后图片有一些不连续点,于是试着用双线性插值法进行解决。下面就介绍下插值的原理: 线性插值 如果你只处理分离的数据、想知道分离点之间的某些值,需要用到某种类型的插值。这种情况如图5-17坐标所示。对某些分离的(整数)…

没想到会用到:线性插值(Linear Interpolation)原理及使用

各位博友们大家好&#xff0c;小弟遇到一些问题经常会去看大家的博客&#xff0c;所以也想加入大伙的阵营&#xff0c;每每看到一些好的东西&#xff0c;有些心得体会什么的也想与大伙分享。 1.关于插值 插值&#xff0c;它根据已知的数据序列&#xff08;也可以理解为坐标中一…

线性插值 多项式插值 样条插值 牛顿插值总结

项目github地址&#xff1a;bitcarmanlee easy-algorithm-interview-and-practice 欢迎大家star&#xff0c;留言&#xff0c;一起学习进步 1.什么是插值 在数值分析中&#xff0c;插值(interpolation)是一种通过已知的、离散的数据点&#xff0c;在范围内推求新数据点的过程…

常用线性插值的介绍和应用(双线性插值,三线性插值,平滑曲线插值)

常用线性插值的介绍和应用 线性插值 插值是计算机图形学中非常常用的技术。通常&#xff0c;数据是在常规网格上指定的&#xff08;值写在2D或3D网格的顶点位置&#xff09;或在线上&#xff08;在一维的情况下&#xff09;&#xff0c;但是程序需要在该网格上的随机位置求值。…

线性插值 np.interp()

线性插值是指插值函数为一次多项式的插值方式&#xff0c;其在插值节点上的插值误差为零。线性插值相比其他插值方式&#xff0c;如抛物线插值&#xff0c;具有简单、方便的特点。线性插值的几何意义即为概述图中利用过A点和B点的直线来近似表示原函数。 线性插值法是认为现象…

我与插值萍水相逢:线性插值(Linear Interpolation)原理及使用

各位博友们大家好&#xff0c;小弟遇到一些问题经常会去看大家的博客&#xff0c;所以也想加入大伙的阵营&#xff0c;每每看到一些好的东西&#xff0c;有些心得体会什么的也想与大伙分享。 1.关于插值 插值&#xff0c;它根据已知的数据序列&#xff08;也可以理解为坐标中一…

对线性插值的理解

【插值】 插值是用已知点求未知点的一种方法&#xff0c;而且通常是用两个已知点求一个未知点。&#xff08;如果是用很多已知点求未知点一般用曲线拟合&#xff09; 既然是用两个已知点求一个未知点&#xff0c;那么两个已知点之间的距离要尽可能的小&#xff0c;这样求出来…

python判断是否为数字类型_python判断字符串是否为数字

以下实例通过创建自定义函数 is_number() 方法来判断字符串是否为数字:# -*- coding: UTF-8 -*- # Filename : test.py # author by : www.runoob.com def is_number(s): try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.…

使用正则表达式判断字符串是否为数字类型

java 判断字符串是否是数字 1.用JAVA自带的函数 publicstaticbooleanisNumeric(Stringstr){ for(inti0;i System.out.println(str.charAt(i)); if(!Character.isDigit(str.charAt(i))){ returnfalse; returntrue; 2.用正则表达式 首先要importjava.util.regex.Pattern和java.ut…

java判断字符串是否为数字

一&#xff1a;判断java中的字符串是否为数字&#xff0c;可以通过正则表达式来判断&#xff1b;其判断逻辑如下&#xff1a; 1、根据阿里巴巴代码规范&#xff0c;将Pattern设置为全局常量&#xff0c;通过 -?[0-9](\\\\.[0-9])? 进行匹配是否为数字 private static final P…

二次型化为标准型

将二次型化为标准形有利于我们了解二次型的简单形式、二次型的各种参数如正负惯性指数、得到二次型的规范形、对称矩阵合同的简单形等等。另外&#xff0c;化标准形也是解析几何化简二次曲线和二次曲面的需要。 下面&#xff0c;我们以两道题目为例说明计算二次型的标准形的2种…

二次型的标准型、规范型

若二次型只有平方项&#xff0c;则称二次型为标准型 如果标准型中&#xff0c;系数只有1&#xff0c;-1和0&#xff0c;那么称为二次型的规范型&#xff0c;因为标准型中&#xff0c;1&#xff0c;-1&#xff0c;0的个数是由正负惯性指数决定的&#xff0c;而合同的矩阵正负惯…

二次型,正定二次型

二次型&#xff1a;含有n个变量 x 1 , x 2 , . . . x n x_1,x_2,...x_n x1​,x2​,...xn​的二次齐次函数: f ( x 1 , x 2 , . . . x n ) a 11 x 1 2 a 12 x 1 x 2 a 13 x 1 x 3 a 14 x 1 x 4 . . . a 1 n x 1 x n f(x_1,x_2,...x_n)a_{11}x_1^2a_{12}x_1x_2a_{13}x_1x_3…

二次型的正定

实数二次型的类型 设为一个实二次型&#xff0c;若 自变量不全为0 若恒成立&#xff0c;则称f为一个正定二次型&#xff0c;称A为正定矩阵 若恒成立&#xff0c;则称f为一个半正定二次型&#xff0c;称A为半正定矩阵 若恒成立&#xff0c;则称f为一个负定二次型&#xff0…

线性代数-二次型及其正定性

二次型及其矩阵表示形式 二次型:含有n个变量的二次齐次多项式 二次型矩阵:xTAx,其中A为实对称矩阵 任给一个实二次型,就唯一确定一个实对称矩阵;反之,任给一个实对称矩阵,也可以唯一确认一个实二次型,因此,实二次型与实对称矩阵之间存在一一对应关系,称实对称矩阵A为二次型f的…

【考研线代】六. 二次型

文章目录 第六章 二次型6.1 二次型及其标准形6.1.1 概念6.1.2 合同基本性质6.1.3 题型 6.2 正定二次型6.2.1 概念6.2.2 定理 6.3 补充&#xff1a;解题技巧6.3.1 惯性定理的理解6.3.2 矩阵合同的充要条件6.3.3 配方法的坐标变换必须可逆6.3.4 正交变化化标准型 &#xff08;&am…

线性代数(10):二次型

一、二次型 &#xff08;1&#xff09;定义 含有 n 个变量 x1&#xff0c;x2&#xff0c;…… &#xff0c;xn 的二次齐次函数称为二次型&#xff1b; 对称矩阵 A 的秩也叫做二次型 f 的秩&#xff1b; &#xff08;2&#xff09; 例&#xff1a; 排列二次型 所对应的矩阵 …

二次型化标准形的三种方法

二次型化标准形的三种方法 将二次型化为标准形有利于我们了解二次型的简单形式、二次型的各种参数如正负惯性指数、得到二次型的规范形、对称矩阵合同的简单形等等。另外&#xff0c;化标准形也是解析几何化简二次曲线和二次曲面的需要。 下面&#xff0c;我们以两道题目为例…