一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情。
之前介绍了在 1维数组上,通过调整数组大小的做法有点类似,双线性调整 2 维数组主要用到双线性差值方法。那么所谓双线性插值是可以将转为线性差值的问题,假设我们有 A,B,C 和 D 这 4 个点,对应的坐标分别为 、、 和 。如下图,问题是我们要根据给出 A、B、C 和 D 点值来求出 Z 的值,其实这里前提是我们认为 Z 的值是由 A、B、C 和 D 值大小,以及他们与 Z 点空间位置相关的。首先我们先 X 和 Y 位置的值。然后在宽度这个维度上我们计算 X 和 Y 值,然后在 X 和 Y 相对于 Z 位置来计算 Z 的值。
根据上面的图,我们可以列出如下
ratio_y = (img_height - 1) / (height - 1)
ratio_x = (img_width - 1) / (width - 1)
import math
def bilinear_resize(image, height, width):
"""
`image` is a 2-D numpy array
`height` and `width` are the desired spatial dimension of the new 2-D array.
"""
img_height, img_width = image.shape[:2]
resized = np.empty([height, width])
x_ratio = float(img_width - 1) / (width - 1) if width > 1 else 0
y_ratio = float(img_height - 1) / (height - 1) if height > 1 else 0
for i in range(height):
for j in range(width):
x_l, y_l = math.floor(x_ratio * j), math.floor(y_ratio * i)
x_h, y_h = math.ceil(x_ratio * j), math.ceil(y_ratio * i)
x_weight = (x_ratio * j) - x_l
y_weight = (y_ratio * i) - y_l
a = image[y_l, x_l]
b = image[y_l, x_h]
c = image[y_h, x_l]
d = image[y_h, x_h]
pixel = a * (1 - x_weight) * (1 - y_weight) \
+ b * x_weight * (1 - y_weight) + \
c * y_weight * (1 - x_weight) + \
d * x_weight * y_weight
resized[i][j] = pixel
return resized
其中 width 和 height 是新 2 维数组的行和列。假设想计算坐标[i, j] 处的点的内插值,其中0<=i<height,0<=j<width。在原有 2 维数组中的映射坐标被计算为[y_ratio * i, x_ratio * j]。那么 [i, j] 周围最近的 4 个点的坐标是[y_l, x_l], [y_l, x_h], [y_h, x_l], [y_h, x_h]。