我想问你一些双线性插值/缩放细节。我们假设我们有这个矩阵:
|100 | 50 |
|70 | 20 |
这是一个2 x 2灰度图像。现在,我想将它缩放两倍,我的矩阵看起来像这样:
| 100 | f1 | 50 | f2 |
| f3 | f4 | f5 | f6 |
| 70 | f7 | 20 | f8 |
因此,如果我们想要计算f4
,则计算定义为
f1 = 100 + 0.5(50 - 100) = 75
f7 = 70 + 0.5(20 - 70) = 45
现在终于:
f4 = 75 + 0.5(45 - 75) = 60
但是,我无法真正理解 f3 或 f1
的计算方法是什么我们是否分别在每个方向进行双线性缩放?因此,这意味着:
f3 = 100 + 0.5(70 - 100) = 85
f1 = 100 + 0.5(50 - 100) = 75
另外,我应该如何对待 f2,f6,f8 。这些点是否像最近邻算法一样被复制?
答案 0 :(得分:28)
我想向您介绍维基百科这个非常富有洞察力的图片,该图解说明了如何对一点进行双线性插值:
来源:Wikipedia
如您所见,四个红点是已知的。您事先知道的这些点和P
是我们希望插值的点。因此,我们必须做两个步骤(正如您在帖子中指出的那样)。要处理x
坐标(水平),我们必须计算内插值对于红色顶行和红色底行的行。这会产生两个蓝点R1
和R2
。要处理y
坐标(垂直),我们使用两个蓝点并垂直插值以获得最终的P
点。
当你调整图像大小时,即使我们没有直观地看到我要说的内容,但想象这个图像是 3D信号 f
。矩阵中的每个点实际上都是一个3D坐标,其中列位置是x
值,行位置是y
值,z
值是数量/灰度值矩阵本身。因此,执行z = f(x,y)
是矩阵中位置(x,y)
处的矩阵的值。在我们的情况下,因为您正在处理图片,(x,y)
的每个值都是整数,从我们的行数/列数到1行,具体取决于您正在查看的维度。
因此,给定您要在(x,y)
处插入的坐标,并给出上图中的红色坐标,我们称之为x1,y1,x2,y2
,如图所示 - 具体遵循惯例图表和参考图像的访问方式:x1 = 1, x2 = 2, y1 = 2, y2 = 1
,蓝色坐标R1
和R2
通过1D插值列使用相同的行计算两个点重合:
R1 = f(x1,y1) + (x - x1)/(x2 - x1)*(f(x2,y1) - f(x1,y1))
R2 = f(x1,y2) + (x - x1)/(x2 - x1)*(f(x2,y2) - f(x1,y2))
值得注意的是,(x - x1) / (x2 - x1)
是权重/比例,表示在f(x1,y1)
处看到的两个值之间的输出组合的混合程度和f(x2,y1)
R1
或f(x1,y2)
和f(x2,y2)
R2
。具体而言,x1
是起点,(x2 - x1)
是x
值的差异。您可以验证将x1
替换为x
而x2
代替x
,[0,1]
给我们1.此权重在(1,1)
之间波动,这是计算所需的工作。
应注意,图像的原点位于左上角,因此R1
位于左上角。找到R2
和P
后,我们可以通过逐行插值找到P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)
:
(y - y2) / (y2 - y1)
同样,R1
表示R2
和P
对最终输出f5
的贡献的比例/组合。因此,您正确计算了f5
,因为您使用了四个已知点:左上角为100,右上角为50,左下角为70,右下角为20.具体来说,如果要计算{{1} },这意味着(x,y) = (1.5,1.5)
,因为我们在100到50之间中途,因为您将图像缩放了两倍。如果将这些值插入上述计算中,您将获得预期的值60。两次计算的权重也会产生0.5
,这是您在计算中得到的,也是我们所期望的。
如果你计算f1
,这相当于(x,y) = (1.5,1)
,如果你将其替换为上面的等式,你会看到(y - y2)/(y2 - y1)
给你0或权重是0,所以计算的只是R2
,对应于仅沿顶行的线性插值。同样,如果我们计算f7
,这意味着我们想要在(x,y) = (1.5,2)
进行插值。在这种情况下,您会看到(y - y2) / (y2 - y1)
为1或权重为1,因此P = R2 + (R1 - R2)
,这简化为R1
,并且仅沿底行进行线性插值。
现在有f3
和f5
的情况。这两者分别对应(x,y) = (1,1.5)
和(x,y) = (2,1.5)
。对于这两种情况,将这些值替换为R1
和R2
以及P
会给出:
f3
R1 = f(1,2) + (1 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(1,2)
R2 = f(1,1) + (1 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,1)
P = R1 + (1.5 - 1)*(R1 - R2) = f(1,2) + 0.5*(f(1,2) - f(1,1))
P = 70 + 0.5*(100 - 70) = 85
f5
R1 = f(1,2) + (2 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(2,2)
R2 = f(1,1) + (2 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,2)
P = R1 + (1.5 - 1)*(R1 - R2) = f(2,2) + 0.5*(f(2,2) - f(1,2))
P = 20 + 0.5*(50 - 20) = 35
那么这告诉我们什么?这意味着您只沿y方向插入 。当我们看一下P
时,这一点很明显。对P
和f3
中的每一个f5
进行更彻底的计算检查,您会看到我们只考虑垂直方向的值。
因此,如果您想要一个明确的答案,f1
和f7
只能通过x
/列方向沿同一行进行插值来找到。通过在同一列中插入f3
/行方向找到f5
和y
。 f4
使用f1
和f7
的混合来计算您已经看到的最终值。
要回答您的最终问题,f2
,f6
和f8
会根据个人喜好填写。这些值被视为超出范围,x
和y
值均为2.5
,而[1,2]
网格之外的值为(x,y)
}}。在MATLAB中,默认实现是将定义边界之外的任何值填充为非数字(NaN
),但有时,人们使用线性插值进行外推,复制边界值或执行某些操作精心填充,如对称或圆形填充。这取决于您处于什么状况,但没有关于如何填写f2
,f6
和f8
的正确和明确答案 - 这一切都取决于您的申请和什么对你最有意义。
作为奖励,我们可以在MATLAB中验证我的计算是否正确。我们首先在(x,y)
范围内定义[1,2]
点的网格,然后调整图像的大小,使其大两倍,我们指定每点0.5的分辨率,而不是1. I&# 39;我将调用你定义的矩阵A
:
A = [100 50; 70 20]; %// Define original matrix
[X,Y] = meshgrid(1:2,1:2); %// Define original grid of points
[X2,Y2] = meshgrid(1:0.5:2.5,1:0.5:2.5) %// Define expanded grid of points
B = interp2(X,Y,A,X2,Y2,'linear'); %// Perform bilinear interpolation
原始(x,y)
点网格如下:
>> X
X =
1 2
1 2
>> Y
Y =
1 1
2 2
展开的网格将矩阵的大小扩展两倍:
>> X2
X2 =
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
>> Y2
Y2 =
1.0000 1.0000 1.0000 1.0000
1.5000 1.5000 1.5000 1.5000
2.0000 2.0000 2.0000 2.0000
2.5000 2.5000 2.5000 2.5000
B
是使用X
和Y
作为原始网格点的输出,X2
和Y2
是我们想要插入的点。
我们得到:
>> B
B =
100 75 50 NaN
85 60 35 NaN
70 45 20 NaN
NaN NaN NaN NaN