Puc*_*acz 10 interpolation image image-processing linear-interpolation image-scaling
我想问你一些双线性插值/缩放细节.我们假设我们有这个矩阵:
|100 | 50 |
|70 | 20 |
Run Code Online (Sandbox Code Playgroud)
这是一个2 x 2灰度图像.现在,我想将它缩放两倍,我的矩阵看起来像这样:
| 100 | f1 | 50 | f2 |
| f3 | f4 | f5 | f6 |
| 70 | f7 | 20 | f8 |
Run Code Online (Sandbox Code Playgroud)
所以如果我们想计算f4,计算定义为
f1 = 100 + 0.5(50 - 100) = 75
f7 = 70 + 0.5(20 - 70) = 45
Run Code Online (Sandbox Code Playgroud)
现在终于:
f4 = 75 + 0.5(45 - 75) = 60
Run Code Online (Sandbox Code Playgroud)
但是,我无法真正理解f3或f1适合的计算
我们是否分别在每个方向进行双线性缩放?因此,这意味着:
f3 = 100 + 0.5(70 - 100) = 85
f1 = 100 + 0.5(50 - 100) = 75
Run Code Online (Sandbox Code Playgroud)
另外,我应该如何对待f2,f6,f8.这些点是否像最近邻算法一样被复制?
ray*_*ica 33
我想向您指出维基百科中这个非常有见地的图形,它说明了如何对一点进行双线性插值:

资料来源:维基百科
如您所见,这四个红点是众所周知的.这些你事先知道P的点是我们想要插入的点.因此,我们必须做两个步骤(正如您在帖子中指出的那样).要处理x坐标(水平),我们必须计算内插值对于红点的顶行和红点的底行的行.这导致两个蓝点R1和R2.为了处理y坐标(垂直),我们使用两个蓝点并垂直插值以获得最终P点.
当您调整图像大小时,即使我们没有在视觉上看到我要说的内容,但想象这个图像是3D信号 f.矩阵中的每个点实际上是3D坐标,其中列位置是x值,行位置是y值,z值是矩阵本身的数量/灰度值.因此,do 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))
Run Code Online (Sandbox Code Playgroud)
需要注意的是很重要的(x - x1) / (x2 - x1)是重量/比例如何混合的多输出包括在看到这两个值之间f(x1,y1)并f(x2,y1)用于R1或f(x1,y2)和f(x2,y2)的R2.具体来说,x1是起点,(x2 - x1)是x值的差异.您可以验证代x1作为x给我们0,而x2作为x为我们提供了1这个重量之间波动,[0,1]这为计算工作是必需的.
应该注意的是,图像的原点位于左上角,左上角也是如此(1,1).一旦找到R1并且R2,我们可以P通过行插入来找到:
P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)
Run Code Online (Sandbox Code Playgroud)
再次,(y - y2) / (y2 - y1)表示多少的比例/组合R1以及R2对最终输出的贡献P.因此,您f5正确计算,因为您使用了四个已知点:左上角是100,右上角是50,左下角是70,右下角是20.具体来说,如果你想计算f5,这意味着(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这两种情况下给予:
f3R1 = 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
Run Code Online (Sandbox Code Playgroud)
f5R1 = 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
Run Code Online (Sandbox Code Playgroud)
那告诉我们什么呢?这意味着您仅沿y方向进行插值.当我们看一看时,这是显而易见的P.更彻底的检查计算P为每个f3和f5,你看,我们正在考虑只沿着垂直方向的值.
因此,如果您想要一个明确的答案,f1并且只能沿着/ column方向沿同一行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.我将调用您定义的矩阵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
Run Code Online (Sandbox Code Playgroud)
(x,y)点的原始网格看起来像:
>> X
X =
1 2
1 2
>> Y
Y =
1 1
2 2
Run Code Online (Sandbox Code Playgroud)
扩展网格将矩阵的大小扩展两倍,如下所示:
>> 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
Run Code Online (Sandbox Code Playgroud)
B是使用X和Y作为原始网格点的输出,X2并且Y2是我们想要插入的点.
我们得到:
>> B
B =
100 75 50 NaN
85 60 35 NaN
70 45 20 NaN
NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)