一、双线性插值原理
双线性插值就是线性插值在二维时的推广,在两个方向上做三次线性插值
1.1 在线段 [(0,0), (0,1)]
上的插值
f ( x , 0 ) = x [ f ( 1 , 0 ) − f ( 0 , 0 ) ] + f ( 0 , 0 ) − − − ( 1 ) f(x,0)=x[f(1,0) - f(0, 0)] + f(0, 0) ---(1) f(x,0)=x[f(1,0)−f(0,0)]+f(0,0)−−−(1)
1.2 在线段 [(0,1), (1,1)]
上的插值
f
(
x
,
1
)
=
x
[
f
(
1
,
1
)
−
f
(
0
,
1
)
]
+
f
(
0
,
1
)
−
−
−
(
2
)
f(x,1)=x[f(1,1) - f(0, 1)] + f(0, 1) ---(2)
f(x,1)=x[f(1,1)−f(0,1)]+f(0,1)−−−(2)
1.3 在线段 [(x,0), (x,1)]
上的插值
f ( x , y ) = y [ f ( x , 1 ) − f ( x , 0 ) ] + f ( x , 0 ) − − − ( 3 ) f(x,y)=y[f(x,1) - f(x, 0)] + f(x, 0) ---(3) f(x,y)=y[f(x,1)−f(x,0)]+f(x,0)−−−(3)
根据(1)(2)(3) :
f
(
x
,
y
)
=
y
[
x
[
f
(
1
,
1
)
−
f
(
0
,
1
)
]
+
f
(
0
,
1
)
−
(
x
[
f
(
1
,
0
)
−
f
(
0
,
0
)
]
+
f
(
0
,
0
)
]
+
x
[
f
(
1
,
0
)
−
f
(
0
,
0
)
]
+
f
(
0
,
0
)
f(x,y)=y[ x[f(1,1) - f(0, 1)] + f(0, 1) - (x[f(1,0) - f(0, 0)] + f(0, 0) ]+ x[f(1,0) - f(0, 0)] + f(0, 0)
f(x,y)=y[x[f(1,1)−f(0,1)]+f(0,1)−(x[f(1,0)−f(0,0)]+f(0,0)]+x[f(1,0)−f(0,0)]+f(0,0)
得出:
f
(
x
,
y
)
=
[
f
(
1
,
0
)
−
f
(
0
,
0
)
]
x
+
[
f
(
0
,
1
)
−
f
(
0
,
0
)
]
y
+
[
f
(
1
,
1
)
+
f
(
0
,
0
)
−
f
(
0
,
1
)
−
f
(
1
,
0
)
]
x
y
+
f
(
0
,
0
)
f(x,y)=[f(1,0)-f(0,0)]x+[f(0,1)-f(0,0)]y+ [f(1,1)+f(0,0)-f(0,1)-f(1,0)]xy+f(0,0)
f(x,y)=[f(1,0)−f(0,0)]x+[f(0,1)−f(0,0)]y+[f(1,1)+f(0,0)−f(0,1)−f(1,0)]xy+f(0,0)
二、numpy实现
主要分为三部分
1-找位置,及位置周围四个像素点
2-双线性插值算法
3-三通道分开处理
def insert_linear_pos(img_dt, resize, x_scale=None, y_scale=None):
m_, n_ = img_dt.shape
# 获取新的图像的大小
if resize is None:
n_new, m_new = np.round(x_scale * n_).astype(int), np.round(y_scale * m_).astype(int)
else:
n_new, m_new = resize
n_scale, m_scale = n_ / n_new, m_ / m_new # src_with/dst_with, Src_height/dst_heaight
# 一、获取位置对应的四个点
# 1-1- 初始化位置
m_indxs = np.repeat(np.arange(m_new), n_new).reshape(m_new, n_new)
n_indxs = np.array(list(range(n_new))*m_new).reshape(m_new, n_new)
# 1-2- 初始化位置
m_indxs_c = (m_indxs + 0.5 ) * m_scale - 0.5
n_indxs_c = (n_indxs + 0.5 ) * n_scale - 0.5
### 将小于零的数处理成0
m_indxs_c[np.where(m_indxs_c < 0)] = 0.0
n_indxs_c[np.where(n_indxs_c < 0)] = 0.0
# 1-3 获取正方形顶点坐标
m_indxs_c_down = m_indxs_c.astype(int)
n_indxs_c_down = n_indxs_c.astype(int)
m_indxs_c_up = m_indxs_c_down + 1
n_indxs_c_up = n_indxs_c_down + 1
### 溢出部分修正
m_max = m_ - 1
n_max = n_ - 1
m_indxs_c_up[np.where(m_indxs_c_up > m_max)] = m_max
n_indxs_c_up[np.where(n_indxs_c_up > n_max)] = n_max
# 1-4 获取正方形四个顶点的位置
pos_0_0 = img_dt[m_indxs_c_down, n_indxs_c_down].astype(int)
pos_0_1 = img_dt[m_indxs_c_up, n_indxs_c_down].astype(int)
pos_1_1 = img_dt[m_indxs_c_up, n_indxs_c_up].astype(int)
pos_1_0 = img_dt[m_indxs_c_down, n_indxs_c_up].astype(int)
# 1-5 获取浮点位置
m, n = np.modf(m_indxs_c)[0], np.modf(n_indxs_c)[0]
return pos_0_0, pos_0_1, pos_1_1, pos_1_0, m, n
def linear_insert_1color(img_dt, resize, fx=None, fy=None):
pos_0_0, pos_0_1, pos_1_1, pos_1_0, m, n = insert_linear_pos(img_dt=img_dt, resize=resize, x_scale=fx, y_scale=fy)
a = (pos_1_0 - pos_0_0)
b = (pos_0_1 - pos_0_0)
c = pos_1_1 + pos_0_0 - pos_1_0 - pos_0_1
return np.round(a * n + b * m + c * n * m + pos_0_0).astype(int)
def linear_insert(img_dt, resize, fx=None, fy=None):
# 三个通道分开处理再合并
if len(img_dt.shape) == 3:
out_img0 = linear_insert_1color(img_dt[:,:,0], resize=resize, fx=fx, fy=fy)
out_img1 = linear_insert_1color(img_dt[:,:,1], resize=resize, fx=fx, fy=fy)
out_img2 = linear_insert_1color(img_dt[:,:,2], resize=resize, fx=fx, fy=fy)
out_img_all = np.c_[out_img0[:,:,np.newaxis], out_img1[:,:,np.newaxis], out_img2[:,:,np.newaxis]]
else:
out_img_all = linear_insert_1color(img_dt, resize=resize, fx=fx, fy=fy)
return out_img_all.astype(np.uint8)
三、实现比对
out_img_all = linear_insert(img, resize=None, fx=1.5, fy=1.5)
resized1_5_img_linear = cv2.resize(img, dsize=None, fx=1.5, fy=1.5, interpolation=cv2.INTER_LINEAR)
cv2.imshow('Origin', img)
cv2.imshow('linear_insert*1.5', out_img_all)
cv2.imshow('Origin-[INTER_LINEAR] * 1.5', resized1_5_img_linear)
cv2.waitKey(0)