1 |; e' i2 ^" S0 y, U$ F1)使用文章开头的公式,通过dst_x,dst_y计算出src_x,src_y,此时一般src_x,src_y是小数,可记为src_x=i+u,src_y=j+v,以(i,j)及周围的16个邻近点构成矩形网格;* D! `+ U; \" k2 I; Z
2)因为Bicubic函数是一维函数,所以我们需要分别沿着X、Y方向计算每个点对应的权重,每个点权重记为wij(w_x,w_y),计算过程为: . X% i# c+ j; e. ~2 i3 j c/ y # M# L: H9 G: o. M* D明确该点X、Y方向与P点之间的距离lij(l_x,l_y),如a00(i-1,j-1)与P(i+u,j+v)之间距离为l00(i+u-i+1,j+v-j+1)=l00(u+1,v+1),a33(i+2,j+2)与P(i+u,j+v)之间距离为l33(i+2-i-u,j+2-j-v)=l33(2-u,2-v);& _# z1 k( I- A C$ \
所以每个邻近点对应的权重为w(w_x,w_y)=w(W(l_x),W(l_y)),此处W指Bicubic函数; . t! `- E/ T/ C3)得到每个点对应的权重后,通过插值公式即可得到插值结果B(dst_x,dst_y);" T B, O+ C; O7 L
& U* E" e" X$ Y; ]8 g0 S* a1 y* e+ Z( Q
很容易计算从a00到a33共16个点到P点的距离l(l_x,l_y)为:2 g3 J* x. h: P* {( ]5 U+ M; R: B
% X0 G$ u" T; T* t3 [( L9 K8 S0 p& A比如a00与P之间的距离为:l00(l_0,l_0)=l00(u+1,v+1),a33与P之间的距离为:l33(l_3,l_3)=l33(2-u,2-v),到这里大家应该理解双三次插值的过程了吧! , X/ k. O$ q, I" T* ~/ c6 ^% ~-------------------------------------------------------------------------------------------------------------------------- 4 L1 \- z+ U- N( \其实在插值计算时还可以使用矩阵表示,如下: 2 I" H: O; H% F* J/ M! @ ) Z. [- k+ e* _0 N! |4 A5 U% K4 E0 X( F: Z) l
其中f(i+u,j+v)即为要计算的值,而A、C分别表示权重也就是第一种方式中的w_x,w_y,B为原图中16个邻近点构成的矩阵,计算权重的函数使用S(x)去近似。 S8 R3 o- N2 b' k
( K' [; E* o+ F+ W+ O2.举个例子 f# g8 G, O2 n1 t, T- b5 ?' V z4 b输入为Src:5×5,输出为Dst:10×10,我们去求Dst中点(5,5)的值: : e6 l' m3 ^( C% y, Y' y+ A! P% L5 P2 Q4 s7 m# S; a: d3 G+ J
我手动实现上述矩阵运算方式的计算过程(计算结果总是和Pytorch内置函数计算出的结果存在一定偏差,我也是很纳闷):' p$ f- R) Y4 V! N1 P* r3 O( O
3 H* G6 }, ]# e- U, t* d ?4 y
import numpy as np1 F- h3 W( v6 `% t+ e
import math $ F. E1 q( W( i' X3 O 3 H- y- M1 l% D. M7 U" Dsrc_w=src_h=5& B' k" Y9 ^0 X6 D
dst_w=dst_h=10 2 w6 V1 D; T8 j# G; H; Y8 d4 k( Q9 g9 b2 Q
dst_x=dst_y=5+ V+ L$ o. z0 u( E! L
src_x=dst_x*(src_h/dst_h) 3 Y& k, O+ K# j9 asrc_y=dst_y*(src_w/dst_w)! v+ y' u4 ?. Q& q' @. f! B
( P. d- [' t7 l0 A& yi=math.floor(src_x) * S6 a4 [* ?/ a! g% F( K4 Hj=math.floor(src_y)* i! M3 I/ r( w
9 q& I+ z: N, B4 p0 `
u=src_x-i% X5 D) U8 |7 U1 O" V" M9 F
v=src_y-j' j. P' ]7 d/ ?7 l2 g0 i; J+ @
# print(i,j,u,v)2 p6 x \+ i# \' e. C
# l_x=np.array([[1.5,0.5,0.5,1.5]])$ w- |- W, U8 K9 N
# l_y=np.array([[1.5,0.5,0.5,1.5]]) / H. ]# D" v( W: Xbase=[1,0,-1,-2]- h' r& D( _6 M8 t
! R/ L# [$ T+ {9 I% `6 b- _+ Z$ k" G , Z# a9 o }* q# v' P) u3 v* \def l_(r): ' h. x$ f) p+ Z( y& C a=np.zeros((1,4)) 1 p g) A: n& g! @0 {9 r for j in range(4):: E i L6 k! P9 B1 V8 I6 y1 l
a[0,j]=r+base[j] / ^! g; Y' S' `# }- G: I+ A0 \ z return a, u) j& S7 F. M U
3 A1 u: S2 z' w6 e4 s V Y- _
l_x,l_y=l_(u),l_(v) - x1 [# [3 l( i2 L# print(l_x)' J- x* {. J% ?2 z( P" D$ M
# print(l_y) ( ?& X# ^) D, m) T; D" z$ O" Z9 G7 Q+ P, c/ ?! F; ]& \9 Q% p
# # print(l_x.shape) - H: C# B* c; w, \) J# 1 X0 E @; P9 {4 l: _0 Z, O9 V# a3 a" \: r9 d% d* t3 o' H$ Wdef S_x(l_): ! B' ?' ]* o4 W& Z9 [ s=np.zeros(shape=(1,4))* c$ [2 G) Z3 K% o
for j in range(4): & U* n/ ~7 K% V) ?- w! y1 p4 L) M6 ^ x_abs=math.fabs(l_[0,j]) 3 a. P) s" n+ f6 I+ B if x_abs <= 1: 3 q8 T/ ^7 @& p' O% C: b s[0,j] = 1-2* math.pow(x_abs, 2)+math.pow(x_abs, 3)4 o' L- e( Y: b" b, b, l7 C
elif x_abs < 2 and x_abs > 1:% p( \6 G/ d6 H- N A
s[0,j] = 4-8*x_abs+5*math.pow(x_abs, 2) - math.pow(x_abs, 3)( Y0 T9 R7 o) O" O H' V
return s ' G/ e7 }4 f4 d* U 1 X: W: A6 G: O! J5 U B' k" J$ j0 p4 m4 e! x! P, c% Y6 T
A,C=S_x(l_x),S_x(l_y); r% G: b3 L% W, E1 B- L) f
! Z4 n" @+ c' |
B=np.array([2 x5 W' {# F* E
[9., 0., 7., 3.], 2 V% i3 o0 f1 S6 o3 k% O [7., 0., 1., 8.],/ ?) r# Y& s4 K0 ]
[1., 8., 1., 3.], * ^9 s Y/ {* E4 I' J' j [5., 5., 1., 1.]])+ J: b% n/ f# [
b=np.matmul(np.matmul(A,B),np.transpose(C)) % b+ E9 {4 @; _$ ]; }2 n4 jprint(b)" g' B! d% `7 ?. t
1 - Z! \0 ^ W0 Z0 c22 R, _1 p0 D* S3 {# E" D: Q+ R$ B
3: g I, }! R3 Q* ^: [" F2 ]
4' Z( I8 ~/ V; ]
5 ( h0 \% Y& w! S n; \6 u" r! ?. w6: a1 v6 E1 y9 [2 k
7! b1 t Y6 G( H5 o' v
8$ ^, Y) h3 o( j8 r5 Y' P
9 % s# s1 y' j1 d, R5 a9 P100 c+ L4 T9 ^+ }+ f: d
11# P/ |- {+ ~3 h3 e: p
127 r; |+ o( C F
13 9 k: j) _/ E8 N142 q; ~# h: V& @) Z8 x6 B
15 & a0 ?# ~# M) ?9 L& W; F7 e16( c& c" r6 T4 y5 l
17% n$ u1 a2 X" W8 S/ g2 A
18 . D0 f* K) }) S* t; [19 - ]' D( G/ F; m6 R' T* m20 & p0 `+ ~: S( b9 c1 {1 H! W h21 u% ?' p; V1 D" x# l* p+ O22 % d) B2 |4 w, W% Z& O233 ]6 W3 q+ J. B3 {3 f; V# x9 U
24: r7 z; Y# {" T) o9 K+ k
257 i: p0 ^+ Y7 k- K0 i4 B6 }( q. {2 H
261 N+ D F1 t3 w5 d9 L( B6 ]
27 & y+ V6 P. |4 J' [3 a28 & _$ e% J% q! }. K- o$ K0 B29 ) \$ j, S( V6 X4 Y' ]( M300 N1 G$ ]) [& O; c; T
31 7 L, J( N; m$ \0 `# J( X* E7 a327 P9 S) p1 |0 Q8 D* g% e1 w
33- E8 C0 X. m0 F1 G" |
34 ; }+ C: ]6 U' C35 3 X" y u/ }$ { b/ W3 u6 {36 $ }& O4 j; J7 F& e p370 y% M; C# r4 `
383 n. t. r7 q, Y8 i% e
39 4 M& R3 n' V1 P2 ~8 G' g; X40 : w0 ]; W* W/ R- N41 . k- t5 h( Z1 v427 x& Y- B* {# F* G
43 9 F/ O# m# J+ T44 ) Q* _( o( K( w2 a% F45 2 T0 T; O9 c. f) Z; {* A46 $ z4 d$ G$ n) F) o7 Y5 k7 v47 6 W5 F! U: a) ^1 M( U48/ \0 Y- e1 e2 @! y# N/ V; Y
49 8 C6 `& R5 @$ o50 & q, F2 ]6 _+ i8 t- d) P51( Z5 e h. J* j% O6 D) i( W
522 ]# ~+ f" A" J# r, O I' U+ E+ o. O
53 9 J; s9 t* @9 `# @+ H& d3 J54* S+ N5 f' F+ W y# Y
552 z' p" y' u7 ~7 m( c& X
3.代码实现 ( O% m5 [6 t6 N# s- l, uimport torch # e( P( V; Y7 B: t! T% u8 }import torch.nn as nn ! `: D( ~& _. m4 U, _2 i; Yfrom torchvision import transforms . e4 i% u$ T) s7 L7 K' j0 G8 s* e
) n" y$ z" p2 X" a; M8 S3 A1 E
img=torch.randint(10,size=(1,4,4),dtype=torch.float32)/ ]7 h: o; s- |2 Y, e7 F9 e) u' W: P
print(img)3 F; g& J5 C( g6 l, F; u2 J
print('---'*5)7 ~3 W9 t9 Q6 r
bicubic_interpolation=transforms.Resize(size=(8,8),* H Q! C5 n8 U/ m
interpolation=transforms.InterpolationMode.BICUBIC) ' K# i: r5 Q% ~resize_img=bicubic_interpolation(img)! C" V3 u4 |4 ]+ i% o
print(resize_img) 1 k$ y' { f& B5 j8 Q$ U+ M1 K1. b3 N1 w8 I% o6 @1 L" q8 P
2 . |; F9 Y' ?; c6 f- _3: D$ w( j+ k3 j: Z7 ]6 I
4 + p2 D$ L3 \8 i# ?" [; M3 s3 U5$ Y) d2 B% b2 O6 {" H. \3 s; a- {
6( V: `1 K$ K- O. @
7* O j- w! d# F
8 7 _5 A! t% f! ^9 p y) f: E9 s$ i e; G9 _5 X3 ~10% ^ A3 [0 e% V
11 4 c7 ~# e5 n+ w" J0 f- V* w5 E12 / H0 f) Z: K, Z W9 h8 f四、Pytorch实现1 O% h1 M: B4 A( s3 J/ S1 Z
大家注意在Pytorch中不同插值方法是通过对transforms.Resize方法中的interpolation参数指定,上面这三种方法只需要依次采用下面三种模式即可: 5 D- S7 V7 b [6 ]; f, W, i9 ?/ N4 A! _- t( D
插值方法 指定方式3 j. R- S9 D* d0 L! m1 i
最近邻插值 transforms.InterpolationMode.NEAREST+ f8 E. M# _% @. r. n9 T
双线性插值 transforms.InterpolationMode.BILINEAR - s3 B6 N8 I- Z/ |9 ~双三次插值 transforms.InterpolationMode.BICUBIC ) m+ E6 V. q0 {& ?7 }: h% c这里我使用周杰伦的一张照片展示一下三种方法对应的插值结果:* r+ H V* y: C d7 M: f1 V
原图如下:' A) ?$ f4 F7 y* G5 u4 o6 o$ U