插值算法
在对图像经过仿射变换(拉伸,旋转)后,图像的形状和位置发生了变化,那么变化过后的图像,每一个像素点的像素值该是多少呢??
一般是通过仿射变换的逆变换计算出原来对应的像素值,例如 f i n p u t ( 1 , 1 ) = 100 f_{input}(1,1)=100 finput(1,1)=100,现在把图像放大两倍那么输出图像 f o u p u t ( 2 , 2 ) = f i n p u t ( 1 , 1 ) = 100 f_{ouput}(2,2) = f_{input}(1,1)=100 fouput(2,2)=finput(1,1)=100
f o ( x ∗ , y ∗ ) = i n v e r s e ( f i n p u t ( x , y ) ) f_o(x^*,y^*) = inverse(f_{input}(x,y)) fo(x∗,y∗)=inverse(finput(x,y))
但是还有个问题。
f o u t p u t ( 3 , 3 ) f_{output}(3,3) foutput(3,3)是多少??,输入图像可以没有 f i n p u t ( 1.5 , 1.5 ) f_{input}(1.5,1.5) finput(1.5,1.5)这个像素点,这时候就要用到插值算法了。
近邻插值法
这个方法的精度不是很高,应该没有在使用了。但便于理解,
原理
通过输出图像计算出它在原图上的坐标点==(整数)==,如果计算的结果是整数,那直接使用。反之就要看它周围那个点离它最近,就使用最近点的像素值。
假若有一张图像矩阵如下:只有两行三列
array([[40, 41, 42],
[43, 44, 45]])
现在我要把它放大两倍,结果应该是什么样呢,下面是一种可能的答案
array([[40, 40, 41, 41, 42, 42],
[40, 40, 41, 41, 42, 42],
[43, 43, 44, 44, 45, 45],
[43, 43, 44, 44, 45, 45]])
这只是一种可能答案,因为(1.5, 1.5)这个点到它离周围距离一样,选谁都可以了,这里就图方便选择了左上角。
CODE
# Nereset Neighbor interpolation
def nn_interpolation(img: np.ndarray, ax=1, ay=1):
# ax ay表示放大率
H,W,C = img.shape
aH = int(ay * H)
aW = int(ax * W)
# 此处的坐标系是(0,0)在左上角
# 先计算出输出图像的坐标
y = np.arange(aH).repeat(aW).reshape(aH,-1)
x = np.tile(np.arange(aW),(aH,1))
# 再计算出对应输入图像上的坐标
y = np.round(y//ay).astype(np.int)
x = np.round(x//ax).astype(np.int)
# 给输出图像赋值
out = img[y,x]
out = out.astype(np.uint8)
return out
plt.imshow(nn_interpolation(lena1, ax=2, ay=1))
双线性插值
单线性插值
设有函数 f ( x ) f(x) f(x),在二维直角坐标系中给定两个点 ( x 0 , f ( x 0 ) ) , ( x 1 , f ( x 1 ) ) (x_0, f(x_0)), (x_1, f(x_1)) (x0,f(x0)),(x