双线性图像插值/缩放 - 计算示例

时间:2015-08-20 17:03:18

标签: image image-processing interpolation image-scaling linear-interpolation

我想问你一些双线性插值/缩放细节。我们假设我们有这个矩阵:

|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 。这些点是否像最近邻算法一样被复制?

1 个答案:

答案 0 :(得分:28)

我想向您介绍维基百科这个非常富有洞察力的图片,该图解说明了如何对一点进行双线性插值:

来源:Wikipedia

如您所见,四个红点是已知的。您事先知道的这些点和P是我们希望插值的点。因此,我们必须做两个步骤(正如您在帖子中指出的那样)。要处理x坐标(水平),我们必须计算内插值对于红色顶行和红色底行的行。这会产生两个蓝点R1R2。要处理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,蓝色坐标R1R2通过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) R1f(x1,y2)f(x2,y2) R2。具体而言,x1是起点,(x2 - x1)x值的差异。您可以验证将x1替换为xx2代替x[0,1]给我们1.此权重在(1,1)之间波动,这是计算所需的工作。

应注意,图像的原点位于左上角,因此R1位于左上角。找到R2P后,我们可以通过逐行插值找到P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)

(y - y2) / (y2 - y1)

同样,R1表示R2P对最终输出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,并且仅沿底行进行线性插值。

现在有f3f5的情况。这两者分别对应(x,y) = (1,1.5)(x,y) = (2,1.5)。对于这两种情况,将这些值替换为R1R2以及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时,这一点很明显。对Pf3中的每一个f5进行更彻底的计算检查,您会看到我们只考虑垂直方向的值。

因此,如果您想要一个明确的答案,f1f7只能通过x /列方向沿同一行进行插值来找到。通过在同一列中插入f3 /行方向找到f5yf4使用f1f7的混合来计算您已经看到的最终值。

要回答您的最终问题,f2f6f8会根据个人喜好填写。这些值被视为超出范围,xy值均为2.5,而[1,2]网格之外的值为(x,y) }}。在MATLAB中,默认实现是将定义边界之外的任何值填充为非数字(NaN),但有时,人们使用线性插值进行外推,复制边界值或执行某些操作精心填充,如对称或圆形填充。这取决于您处于什么状况,但没有关于如何填写f2f6f8的正确和明确答案 - 这一切都取决于您的申请和什么对你最有意义。

作为奖励,我们可以在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是使用XY作为原始网格点的输出,X2Y2是我们想要插入的点。

我们得到:

>> B

B =

   100    75    50   NaN
    85    60    35   NaN
    70    45    20   NaN
   NaN   NaN   NaN   NaN