一、原理
参考博客,我也是看这篇文章入门的。
1、单次线性插值
单线性插值就好像初高中的两点法求函数的表达式,利用y0和y1的加权表示y
2、双线性插值
从两个方向分别插值:
合并上式:
3、进阶版本
双线型内插值算法就是一种比较好的图像缩放算法,它充分的利用了源图中虚拟点四周的四个真实存在的像素值来共同决定目标图中的一个像素值,因此缩放效果比简单的最邻近插值要好很多。由于图像双线性插值只会用相邻的4个点,因此以下公式的分母都是1。算法描述:对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v) (其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。单线性插值:已知数据 (x0, y0) 与 (x1, y1),要计算 [x0, x1] 区间内某一位置 x 在直线上的y值。双线性插值:已知函数 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四个点的值。求未知函数 f 在点 P = (x, y) 的值。
二、代码
1、导入相关库函数
from PIL import Image
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
import math
import os
2、基本初始设置
img_path = r'D:\jupyter_py\in50.jpg' #源图的地址
target_size = (600,800, 3) #目标图像的尺寸
img_arr = np.array(Image.open(img_path), np.uint8)
source_img = Image.fromarray(img_arr.astype(np.uint8)) #源图编码
plt.imshow(source_img)
plt.show()
source_size = img_arr.shape #源图尺寸
print(source_size)
ratio_x, ratio_y = source_size[0]/target_size[0], source_size[1]/target_size[1] #源图和目标图像长宽之比
3、定义求值函数
def cal(x, y, c): #传入的是从目标图像转化为原图像中的坐标值,但是并不是整数
x, y = math.modf(x), math.modf(y) #得到输入值得整数部分和小数部分
mod_x, int_x, mod_y, int_y = round(x[0],4),int(x[1]),round(y[0],4),int(y[1]) #小数部分保留4位,索引必须为整数
#print(int_x, int_y)
if int_x<source_size[0]-1 and int_y<source_size[1]-1: #如果不加该条件,索引值会溢出
p1 = (1-mod_x)*(1-mod_y)*img_arr[int_x, int_y, c] + mod_x*(1-mod_y)*img_arr[int_x+1, int_y, c]
p2 = (1-mod_x)*mod_y*img_arr[int_x, int_y+1, c] + mod_x*mod_y*img_arr[int_x+1, int_y+1, c]
else:
p1 = (1-mod_x)*(1-mod_y)*img_arr[int_x, int_y, c] + mod_x*(1-mod_y)*img_arr[int_x, int_y, c]
p2 = (1-mod_x)*mod_y*img_arr[int_x, int_y, c] + mod_x*mod_y*img_arr[int_x, int_y, c]
p = p1 + p2 #原理公式
return p #上述处理比较草率,x,y分别溢出严格应进行三次条件判断
4、mian函数
if __name__ == '__main__':
start = datetime.now() #计算运算时间
resized_img = [cal(i*ratio_x, j*ratio_y, c) for i in range(target_size[0]) for j in range(target_size[1]) for c in range(target_size[2])] #从三个维度依次计算
resized_img = np.array(resized_img).reshape((target_size[0], target_size[1], target_size[2]))
end = datetime.now()
seconds = (end-start).seconds
print('process cost {}s'.format(seconds)) #输出计算时间
resized_show = Image.fromarray(resized_img.astype(np.uint8))
resized_show.save(r"./1.jpg") #保存目标图像
plt.imshow(resized_show) #显示目标图像
plt.show()
5、效果展示