双线性插值

双线性插值问题描述:
给定矩形四个点,求矩形内部任意一点的颜色。
设某一点的颜色为f(x,y)=a+bx+cy+dxy,四个变量四个未知数,可以解此方程

插值的目的是为了显得平滑。
也可以自己设计插值,比如:求出点(x,y)到矩形四个点的距离,用这个距离作为每个点的权值,距离越小,权重越大。

import matplotlib.pyplot as plt
import numpy as np
from skimage import data, io

"""
STN:Spatial Transform Network

里面用到了双线性插值,难点就是使用tensorflow实现
"""
a = data.astronaut()[19:168, 140:316]


def get(a, x, y, method):
    xx = a.shape[0] * x
    yy = a.shape[1] * y
    (fx, fy), (tx, ty) = np.floor([xx, yy]), np.ceil([xx, yy])
    fx, fy, tx, ty = np.int32([fx, fy, tx, ty])
    tx = min(tx, a.shape[0] - 1)
    ty = min(ty, a.shape[1] - 1)
    if fx == tx and fy == ty:
        return a[fx, fy]
    elif fx == tx:
        w = (yy - fy) / (ty - fy)
        return w * a[fx, fy] + (1 - w) * a[fx, ty]
    elif fy == ty:
        w = (xx - fx) / (tx - fx)
        return w * a[fx, fy] + (1 - w) * a[tx, ty]
    c = np.empty(3, np.int32)
    if method == 'bilinear':
        A = [
            [1, fx, fy, fx * fy],
            [1, fx, ty, fx * ty],
            [1, tx, fy, tx * fy],
            [1, tx, ty, tx * ty]
        ]
        for i in range(3):
            args = np.linalg.solve(A, [a[fx, fy, i], a[fx, ty, i], a[tx, fy, i], a[tx, ty, i]])
            c[i] = np.dot([1, xx, yy, xx * yy], args)
    elif method == 'distance':
        """
        我自己发明的,按照点到四个点的距离进行加权求和
        """
        ps = np.array([[fx, fy], [fx, ty], [tx, fy], [tx, ty]])
        dis = np.linalg.norm(np.array([xx, yy]) - ps, ord=2, axis=1)
        d = np.sum(dis)
        weight = (d - dis) / d
        weight = weight / np.sum(weight)
        c = np.matmul(weight.reshape(1, 4), a[ps[:, 0], ps[:, 1], :])
    return c


def scale(x_scale, y_scale, a, method='bilinear'):
    assert len(a.shape) == 3 and a.shape[2] == 3
    b = np.empty([a.shape[0] * x_scale, a.shape[1] * y_scale, a.shape[2]])
    for i in range(b.shape[0]):
        for j in range(b.shape[1]):
            b[i, j] = np.int32(get(a, i / b.shape[0], j / b.shape[1], method))
    return b.astype(np.uint8)


larger = scale(4, 4, a, 'bilinear')
dis_image = scale(4, 4, a, 'distance')
fig, axis = plt.subplots(1, 3)
for ax, img, title in zip(axis, [a, larger, dis_image], ['original', 'bilinear', 'distance']):
    ax.imshow(img)
    ax.axis('off')
    ax.set_title(title)
plt.show()
io.imsave('linear.jpg', larger)
io.imsave('distance.jpg', dis_image)
io.imsave('original.jpg', a)

原文地址:https://www.cnblogs.com/weiyinfu/p/9638322.html