. G4 i8 G0 ] j在进行插值前,首先会通过下面公式计算出目标图像中像素点位置映射回原图的位置是什么,此处分别使用dst、src表示目标图像和原图像,(x,y)为像素点坐标位置,这个公式尤为重要哦:+ S0 B( M9 ~! T) |/ R2 B
) C4 {3 Y% m) W# Y3 M
) e$ K5 e) F( D
一、最近邻插值(Nearest Neighbor Interpolation)6 A" c; w, u7 x
1.相关介绍- ^; D" b% U" T8 L i( Q
最近邻插值,也称为零阶插值,这是最简单的插值方法,计算量较小,对于未知位置,直接采用与它最邻近的像素点的值为其赋值,这种方法通常会造成插值图像中像素点灰度值不连续,在图像边缘产生明显的锯齿状,所以现实中很少使用这种方法。 ; s$ Q1 c7 g1 G9 I此处分别使用Src和Dst表示原图像和目标图像,他们的大小分别为(Src_H,Src_W)和(Dst_H,Dst_W),我们的目的是利用原始图像对目标图像中的像素值进行填充,。 8 Y# j+ b/ _7 L$ d4 z对于每个元素,填充值的计算分为两步: 0 @$ H h2 o( F1)通过上面的公式计算Dst中坐标(dst_x,dst_y)对应到Src中坐标(src_x,src_y)为多少; - w, C8 w8 S, R. W2)对所求(src_x,src_y)坐标进行floor操作(我看很多人说是采用四舍五入round操作,但我通过结果看明显是floor啊),即向下取整得到(dst_x,dst_y)映射在原图中的最近邻点(floor(src_x),floor(src_y));! P" b" i6 C2 d, L+ Y
) P- K8 W: x7 F" G* G* c举个例子,假设原图像Src和目标图像Dst大小分别为(2,2)和(4,4),我们的目的是利用原始图像对目标图像中的像素值进行填充,利用Pytorch得到结果如上图,以目标图像中第一行数据7,7,2,2为例,分别使用f(x,y)、g(x,y)表示目标图和原图中像素点的灰度值,我对“最近邻”的插值方法实现过程进行展示:3 ?1 u, Q& W5 G9 p
5 A- f* e& V6 p4 B. t最近邻插值方法不咋使用,所以大家不必纠结,继续往下看!2 p" E* D7 H( w0 w: B! X9 c5 |% D
, z5 f! N( E& @4 ]& h. h0 y2.代码实现1 A! O l" T* l
import torch5 @8 a5 V. j, k \
import torch.nn as nn" O3 C* E' ]& W( J
from torchvision import transforms ( f. P& P6 S$ U8 S- z1 X) q ) \9 M) ` A4 i+ v- X4 c2 U i4 v! E3 d* ~8 }
img=torch.randint(10,size=(1,2,2),dtype=torch.float32) ; p" ~4 u7 w8 x; K$ Lprint(img) " p/ O; \4 \: Z: b C) w7 p0 iprint('---'*5) & N; R/ O5 I6 v! b& J* hnearest_neighbor_interpolation=transforms.Resize(size=(4,4),& \5 F6 ^7 h3 p: q% a+ T- \
interpolation=transforms.InterpolationMode.NEAREST)- v$ R. @: b% V$ u6 x
resize_img=nearest_neighbor_interpolation(img)- {8 l+ D: B& a4 ?- {
print(resize_img) 6 O8 ~6 {# o4 J$ Q5 H: t2 o1! E# \9 V! Q6 x' p h
2 ' ?' S# p- g+ y& w* {3) [) X/ L' E$ C, F2 b
4 ( d: d7 F: Q5 G% `4 X# B3 M5( _$ q7 ^- |5 U* I: e
6 / f0 n+ C& Z6 B( P6 B6 q7" k2 [ o/ c; f
8 : v* t& x8 U( N: W4 h9( g! e- Q0 u1 p9 w- a+ H
100 a& p1 j% k0 \+ [' j& \( Y
11 ! J4 h5 N: ?8 d# g12$ j2 Y3 o @3 {; j& ]
二、双线性插值(Bilinear Interpolation) ( C0 ^; z; X: u6 M' h: f1.线性插值(Linear Interpolation). L3 T& J% O: q/ b% a
在看双线性插值之前,我们先了解一下线性插值:线性插值应用于一维数据的插值,根据需要插值的点左右的两个已知邻近点,进行插值计算。插值过程为已知两个点,采用两点法表示一条直线,然后已知x求y或者已知y求x的过程,具体看下面公式推导以及图示说明: 0 u' V7 w; Z0 {4 j' C* P8 i. _. E/ r! C" o. q) X% C
图中目的是求插值点(x,y),而该点左右已知两点(x0,y0)和(x1,y1),利用“两点法”表示这条直线: ; @+ i( u" V. v' {$ B$ @* Y2 K5 |5 `- C* y
公式(1)用于已知y求x;公式(2)用于已知x求y;7 C2 X( B. L5 V4 z
( m5 ?' w& J: g& j
2.双线性插值(Bilinear Interpolation)+ }9 t# L& h' D/ p
双线性插值方法对图像起平滑作用,实际是对二维数据的x和y方向都做一维线性插值,共进行3次一维线性插值。+ u; V$ z" x1 U# f; n
这种方法比较常用,采用未知位置邻近的4个像素点计算他的像素值,具体赋值过程通过下面公式计算(这里的f(Qxy)等可以理解为一维插值公式中的yx):2 [6 p1 w- s/ h5 ]+ ^9 n6 g. O
% v. Y( @9 o! Q: A$ G3 ^3 t% f8 H" O t) U4 x( @
假设目标图中未知点(dst_x,dst_y)对应原图中的点为P(x,y)=P(src_x,src_y),Q11、Q12、Q21、Q22为P在原图中邻近的四个点,对P点插值过程分为以下两步:2 m$ X" [ S' c. l' r- L9 A4 `- D
1)沿着X方向,分别对Q11、Q21和Q12、Q22进行一维线性插值(共两次)得到R1(x,y1)、R2(x,y2); . S" a" d" }* i1 c' e1 h5 @2)利用R1、R2沿着Y方向对其进行一维线性插值(共一次)得到最终的二维线性插值结果P;; \3 |$ F. ]7 B8 N. Y