插值算法
在对图像经过仿射变换(拉伸,旋转)后,图像的形状和位置发生了变化,那么变化过后的图像,每一个像素点的像素值该是多少呢??
一般是通过仿射变换的逆变换计算出原来对应的像素值,例如
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]])
- 1
- 2
现在我要把它放大两倍,结果应该是什么样呢,下面是一种可能的答案
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
- 2
- 3
- 4
这只是一种可能答案,因为(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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
plt.imshow(nn_interpolation(lena1, ax=2, ay=1))
- 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)),(x1,f(x1)),现在有点
x
^
hat{x}
x^在点
[
x
0
,
x
1
]
[x_0, x_1]
[x0,x1]之间,求
f
(
x
^
)
f(hat{x})
f(x^)。现实问题中,一般
x
0
x_0
x0和
x
1
x_1
x1距离很近很近以至于曲线
f
(
x
)
f(x)
f(x)在
[
x
0
,
x
1
]
[x_0, x_1]
[x0,x1]这一小段近似直线,然后就开始线性插值。
这就是简单的求斜率,做直线,再填充的步骤。
f
(
x
^
)
=
f
(
x
1
)
−
f
(
x
0
)
x
1
−
x
0
×
(
x
^
−
x
0
)
+
f
(
x
0
)
f(hat{x}) = frac{f(x_1) - f(x_0)}{x_1 - x_0} imes (hat{x}-x_0) + f(x_0)
f(x^)=x1−x0f(x1)−f(x0)×(x^−x0)+f(x0)
f
(
x
^
)
=
f
(
x
1
)
−
f
(
x
0
)
x
1
−
x
0
×
(
x
^
−
x
0
)
+
x
1
−
x
0
x
1
−
x
0
f
(
x
0
)
f(hat{x}) = frac{f(x_1) - f(x_0)}{x_1 - x_0} imes (hat{x}-x_0) + frac{x_1 - x_0}{x_1 - x_0} f(x_0)
f(x^)=x1−x0f(x1)−f(x0)×(x^−x0)+x1−x0x1−x0f(x0)
然后化简
f
(
x
^
)
=
(
x
^
−
x
0
)
x
1
−
x
0
×
f
(
x
1
)
+
x
^
−
x
1
x
0
−
x
1
×
f
(
x
0
)
f(hat{x}) = frac{(hat{x}-x_0)}{x_1 - x_0} imes f(x_1) + frac{hat{x} - x_1}{x_0 - x_1} imes f(x_0)
f(x^)=x1−x0(x^−x0)×f(x1)+x0−x1x^−x1×f(x0)
继续化简
回到原来的问题:
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)这个像素点。
我们不会观察
f
i
n
p
u
t
(
0
,
0
)
f_{input}(0,0)
finput(0,0)或者
f
i
n
p
u
t
(
3
,
3
)
f_{input}(3,3)
finput(3,3)的值来计算
f
i
n
p
u
t
(
1.5
,
1.5
)
f_{input}(1.5,1.5)
finput(1.5,1.5)的值,而是去看
f
i
n
p
u
t
(
1
,
1
)
f_{input}(1,1)
finput(1,1)和
f
i
n
p
u
t
(
2
,
2
)
f_{input}(2,2)
finput(2,2)的值。
所以在现实中当我们求
f
(
x
^
)
f(hat{x})
f(x^)时,我们会观察
f
(
[
x
^
]
)
f([hat{x}])
f([x^])和
f
(
[
x
^
]
+
1
)
f([hat{x}]+1)
f([x^]+1)的值,有以下的大小关系:
[
x
^
]
≤
x
^
≤
[
x
^
]
+
1
,
x
0
=
[
x
^
]
,
x
1
=
[
x
^
]
+
1
[hat{x}] leq hat{x} leq [hat{x}]+1, x_0=[hat{x}], x_1=[hat{x}]+1
[x^]≤x^≤[x^]+1,x0=[x^],x1=[x^]+1
得到
f
(
x
^
)
=
(
x
^
−
x
0
)
×
f
(
x
1
)
−
(
x
^
−
x
1
)
×
f
(
x
0
)
f(hat{x}) = (hat{x}-x_0) imes f(x_1) - (hat{x} - x_1) imes f(x_0)
f(x^)=(x^−x0)×f(x1)−(x^−x1)×f(x0)
f
(
x
^
)
=
(
x
^
−
x
0
)
×
f
(
x
1
)
+
(
1
−
(
x
^
−
x
0
)
)
×
f
(
x
0
)
f(hat{x}) = (hat{x}-x_0) imes f(x_1) + (1- (hat{x} - x_0)) imes f(x_0)
f(x^)=(x^−x0)×f(x1)+(1−(x^−x0))×f(x0)
令
x
^
−
x
0
=
a
hat{x}-x_0 = a
x^−x0=a
f
(
x
^
)
=
a
×
f
(
x
1
)
+
(
1
−
a
)
×
f
(
x
0
)
f(hat{x}) = a imes f(x_1) +(1 - a) imes f(x_0)
f(x^)=a×f(x1)+(1−a)×f(x0)
双线性插值
这个就要在三维坐标系中作图了,图像函数
z
=
f
(
x
,
y
)
z = f(x,y)
z=f(x,y),给定坐标
(
x
,
y
)
(x,y)
(x,y),求对应的
z
z
z。
(
x
,
y
)
(x,y)
(x,y)周围的四个点
(
[
x
]
,
[
y
]
)
,
(
[
x
]
+
1
,
[
y
]
)
([x],[y]), ([x]+1, [y])
([x],[y]),([x]+1,[y])
(
[
x
]
,
[
y
]
+
1
)
,
(
[
x
]
+
1
,
[
y
]
+
1
)
([x], [y]+1), ([x]+1, [y]+1)
([x],[y]+1),([x]+1,[y]+1)
我们可以先根据 ( [ x ] , [ y ] ) , ( [ x ] + 1 , [ y ] ) ([x],[y]), ([x]+1, [y]) ([x],[y]),([x]+1,[y])求 f ( x , [ y ] ) f(x, [y]) f(x,[y])
同理再根据 ( [ x ] , [ y ] + 1 ) , ( [ x ] + 1 , [ y ] + 1 ) ([x], [y]+1), ([x]+1, [y]+1) ([x],[y]+1),([x]+1,[y]+1)求 f ( x , [ y ] + 1 ) f(x, [y]+1) f(x,[y]+1)
最后根据 f ( x , [ y ] ) f(x, [y]) f(x,[y])和 f ( x , [ y ] + 1 ) f(x, [y]+1) f(x,[y]+1)求得 f ( x , y ) f(x, y) f(x,y)
就是把双线性插值换成单线性插值问题
欢迎一起来参与leetcode刷题项目
刷题的GitHub: github链接.
评论记录:
回复评论: