双线性插值(python实现)

线性插值

线性插值从字面上的意思理解就是,采用线性关系计算新插入的值的大小。更直观的,给定一个一元一次函数 f ( x ) f(x) f(x)以及两个已知的点 f ( x 1 ) , f ( x 2 ) f(x_1),f(x_2) f(x1),f(x2),计算未知点 f ( x ) f(x) f(x)
双线性插值(python实现)_第1张图片
使用斜率的关系
f ( x 2 ) − f ( x 1 ) x 2 − x 1 = f ( x ) − f ( x 1 ) x − x 1 f ( x ) = ( x 2 − x ) x 2 − x 1 f ( x 1 ) + ( x − x 1 ) x 2 − x 1 f ( x 2 ) \frac{f(x_2)-f(x_1)}{x_2-x_1}=\frac{f(x)-f(x_1)}{x-x_1} \\ f(x)=\frac{(x_2-x)}{x_2-x_1}f(x_1)+\frac{(x-x_1)}{x_2-x_1}f(x_2) x2x1f(x2)f(x1)=xx1f(x)f(x1)f(x)=x2x1(x2x)f(x1)+x2x1(xx1)f(x2)

双线性插值

双线性插值也就是在线性插值的基础上进行了两个方向的计算:

1.通过 Q 00 和 Q 01 Q00和Q01 Q00Q01线性插值计算出 R 0 R0 R0

2.通过 Q 10 和 Q 11 Q10和Q11 Q10Q11线性插值计算出 R 1 R1 R1

3.通过 R 0 和 R 1 R0和R1 R0R1线性插值计算出 P P P

双线性插值(python实现)_第2张图片

整理后可得
f ( R 0 ) = ( f ( Q 01 ) − f ( Q 00 ) ) ( w − w 0 ) w 1 − w 0 + f ( Q 00 ) f ( R 1 ) = ( f ( Q 11 ) − f ( Q 10 ) ) ( w − w 0 ) w 1 − w 0 + f ( Q 10 ) f ( P ) = ( f ( R 1 ) − f ( R 0 ) ) ( h − h 0 ) h 1 − h 0 + f ( R 0 ) f(R0)=\frac{(f(Q01)-f(Q00))(w-w0)}{w1-w0}+f(Q00) \\ f(R1)=\frac{(f(Q11)-f(Q10))(w-w0)}{w1-w0}+f(Q10) \\ f(P)=\frac{(f(R1)-f(R0))(h-h0)}{h1-h0}+f(R0) f(R0)=w1w0(f(Q01)f(Q00))(ww0)+f(Q00)f(R1)=w1w0(f(Q11)f(Q10))(ww0)+f(Q10)f(P)=h1h0(f(R1)f(R0))(hh0)+f(R0)
最终
f ( P ) = ( h − h 1 ) ( w − w 1 ) ( h 1 − h 0 ) ( w 1 − w 0 ) f ( Q 00 ) + ( h 1 − h ) ( w − w 0 ) ( h 1 − h 0 ) ( w 1 − w 0 ) f ( Q 01 ) + ( h − h 0 ) ( w 1 − w ) ( h 1 − h 0 ) ( w 1 − w 0 ) f ( Q 10 ) + ( h − h 0 ) ( w − w 0 ) ( h 1 − h 0 ) ( w 1 − w 0 ) f ( Q 11 ) f(P)=\frac{(h-h1)(w-w1)}{(h1-h0)(w1-w0)}f(Q00)+\frac{(h1-h)(w-w0)}{(h1-h0)(w1-w0)}f(Q01)\\ +\frac{(h-h0)(w1-w)}{(h1-h0)(w1-w0)}f(Q10)+\frac{(h-h0)(w-w0)}{(h1-h0)(w1-w0)}f(Q11) f(P)=h1h0)(w1w0)(hh1)(ww1)f(Q00)+h1h0)(w1w0)(h1h)(ww0)f(Q01)+h1h0)(w1w0)(hh0)(w1w)f(Q10)+h1h0)(w1w0)(hh0)(ww0)f(Q11)
细心观察可以发现四个系数之和为1。

要解决图像中的双线性插值的问题,只需要取距离 P P P点最近的四个点就可以直接带入公式求解,有了计算公式,现在只需要搞定 ( h , w ) (h,w) (h,w)从何而来?

直接除以倍数

既然线性插值一般都是要把图像放大,最简单的做法就是把放大后的图像的坐标点除以放大倍数。但是这样会导致几个问题:

  1. 放大的图像与原图不是中心匹配的;
  2. 放大后的图像坐标有一些无法投影到原图。
    1. 例如:在[0,1,2,3]->[0,1,2,3,4,5,6,7,8,9,10,11]中,10/3=3.33, 11/3=3.67 均无法映射到原图

解决方案:

使用numpy的linspace可以均匀的将放大后的坐标值映射到原始坐标范围。

import numpy as np
import imageio
import matplotlib.pyplot as plt



def bilinear_interpolation(image,rate=1.1):
    h,w,c = img.shape
    # 计算放大后的尺寸
    new_h = int(h*rate)
    new_w = int(w*rate)
    # 将放大后的坐标映射到原始坐标范围
    h_s = np.linspace(0,h-1,new_h-1)
    w_s = np.linspace(0,w-1,new_w-1)
    # 创建一个空白的放大后尺寸的图像
    new_img = np.zeros([new_h,new_w,c],dtype=np.uint8)
    # 逐像素的进行计算
    for i in range(new_h-2):
        for j in range(new_w-2):
            for k in range(c):
                # 左上角坐标
                h0,w0 = int(h_s[i]),int(w_s[j])
                # 获得四个点的像素值
                q_00 = img[h0][w0][k]
                q_01 = img[h0][w0+1][k]
                q_10 = img[h0][w0][k]
                q_11 = img[h0+1][w0+1][k]
                # 使用公式计算映射点像素值
                new_img[i][j][k] = (h_s[i]-h0-1) * (w_s[j]-w0-1) * q_00 \
                                 + (h0+1-h_s[i]) * (w_s[j]-w0) * q_01 \
                                 + (h_s[i]-h0) * (w0+1-w_s[j]) * q_10 \
                                 + (h_s[i]-h0) * (w_s[j]-w0) * q_11 
    return new_img

img = plt.imread('0.jpg')
dst = bilinear_interpolation(img,1.5)
imageio.imwrite('4.jpg',dst)

你可能感兴趣的:(计算机视觉,Python)