图像缩放是我们在进行图像处理时非常常用的一个手段,例如进行机深度学习时都需要将训练集中的图片调整到相同的尺寸大小。通常描述图片缩放有两种方式,第一种是PIL.Image.resize(height, width),输入调整后的尺寸;另一种是给出在x方向和y方向的缩放比率,我们先讨论第二种。
假设在x方向上的缩放比率是,在y方向上的缩放比率是
。用矩阵来描述映射关系,下标0表示输入图像,下标1表示输出图像,二者之间的关系为
所以例如,输出图像上(0,1)的点映射到输入图像上就是(0,0.5)。这也是我们执行的思路,先确定输出图像的尺寸,然后确定每个输出图像像素点映射到输入图像上的位置,如果该位置是整数的也对应了某个像素点那就直接用该像素点的数值,如果不是的话就要使用插值算法来计算。最简单的则是最近邻插值法。
最近邻插值法的思路很简单,例如输出图像上(0,1)的点映射到输入图像上就是(0,0.5),我们对(0,0.5)进行最近邻插值,它的数值等于距离最近的像素点的数值,根据四舍五入的原则也就是(0,1)。这种方法没有什么弊端,不过在具体的程序实现中有一个问题,因为python的数组的索引是从0开始的,也就是例如长度为8的序列的索引是[0,1,2,3,4,5,6,7],扩张两倍之后长度是16,索引为[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],其中最后一个下标15根据缩放比率应该是对应7.5,而7.5四舍五入之后是8便超过了原序列中的上限,这也就是我们直接使用python自带的round函数可能会发生的一个问题。
所以实际上我们在python中应该使用的映射函数应为
实现图像缩放的代码为
from PIL import Image
import numpy as np
def Resize(src, tar, sx = 1, sy = 1):
if sx == 1 and sy == 1:
print("NO CHANGE NEEDED.")
else:
im = Image.open(src)
imarray = np.array(im)
height, width = imarray.shape
output_h = round(height * sx)
output_w = round(width * sy)
new_arr = np.zeros((output_h, output_w), dtype = "uint8")
for i in range(output_h):
for j in range(output_w):
new_arr[i, j] = imarray[round((i+1)/sx-1), round((j+1)/sy-1)]
new_im = Image.fromarray(new_arr)
new_im.save(tar)
gray_girl = "C:/Users/60214/Desktop/python_work/DigitalExecution/gray_girl.jpg"
tar = "C:/Users/60214/Desktop/python_work/DigitalExecution/gray_girl_resize.jpg&