CV基础学习Task1, 图像插值算法

1.1 简介

在图像处理中,平移变换、旋转变换以及放缩变换是一些基础且常用的操作。这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列。在一幅输入图象[u,v]中,灰度值仅在整数位置上有定义。然而,输出图象[x,y]的灰度值一般由处在非整数坐标上的(u,v)值来决定。这就需要插值算法来进行处理,常见的插值算法有最近邻插值、双线性插值和三次样条插值。
(留点疑问:平移和旋转这类的变换,图像变换前后像素数量和大小是不变的,这类变换若平移到非整数部分,例如平移小于1个像素,所以这类变换是不应该使用双线性插值这类能引起像素值变化的方法吗?)

最近邻插值算法

最近邻插值,是指将目标图像中的点,对应到源图像中后,找到最相邻的整数点,作为插值后的输出,类似四舍五入的操作。
CV基础学习Task1, 图像插值算法
在这个图中,P点是目标图像某个像素的左上角,P点离Q11最近,目标图像P点的像素值等于原图Q11点的像素值 f(P)=f(Q11)f(P) = f(Q11)
CV基础学习Task1, 图像插值算法
例子也直接拿过来用了。试想一下,如果我们得到一个3x3的图像,想放大到4x4,那4x4的图像里面的值应该怎么填呢?原图像只有3x3全部肯定是填不够4x4的,用最近邻插值算法的话需要的是知道目标图像的各个像素点在原图上的映射,然后直接把与该目标像素点距离最近的原图像素值赋值即可。请结合例子的公式看,就把3x3原图xy轴都划分4份,每一份距离就是3/4那目标图像映射在原图的点就出来了,目标图的(0,0)就是原图的(0, 0);
(0, 1)=(0, 0.75),原图的(0,1)赋值
(0,2)=(0, 1.5),原图的(0,2)赋值
(0,3)=(0, 2.25),原图的(0,2)赋值

CV基础学习Task1, 图像插值算法
这个缺点我觉得是单纯使用四舍五入的最近邻插值导致像素变化交界处过于生硬不够平滑导致。

双线性插值

CV基础学习Task1, 图像插值算法
看双线性插值前先看单纯的线性插值,从上面公式计算到两个坐标连线上的某个点的y值,可见要计算连线上的y值需要知道的条件是连线两端的xy值以及输入的(x)。
而双线性插值就是线性插值在二维上的推广。
CV基础学习Task1, 图像插值算法
我打算继续用这张图算双线性插值法,可以和最近邻插值法对比一下。如图若要用双线性插值计算目标图像在P点的像素值,从线性插值的条件我们得知,若要计算P点的y值,需要三个条件,1.连线两端的xy值,2.P点的坐标x。这时候已知P点的坐标x,P在两条连线ab上我们则选择连线a(任意选一条),那么我们的目标就很明确了,需要知道连线a两端P1,P2的xy值,两端P1,P2上的x已经知道就是P的x值,求P1,P2的y值。P1,P2的y值就简单了,和单线性插值一样。P1,P2的连线两端xy和P1,P2的x值都是已知,直接用下面的线性插值公式计算即可。
y=y0+(xx0)y1y0x1x0=y0+(xx0)y1(xx0)y0x1x0 y=y_{0}+\left(x-x_{0}\right) \frac{y_{1}-y_{0}}{x_{1}-x_{0}}=y_{0}+\frac{\left(x-x_{0}\right) y_{1}-\left(x-x_{0}\right) y_{0}}{x_{1}-x_{0}}
到现在位置计算P点的像素y值的三个条件1.连线两端的xy值,2.P点的坐标x,都已经知道了,也用上面的公式带进入即可求出P点坐标的像素值,这就是双线性插值法。

映射方法

CV基础学习Task1, 图像插值算法我上面用的例子方法都是向后映射法,从目标图像的坐标映射的原图是非整数坐标,再从坐标周围的原图整数坐标计算出目标图像的该有的插值。

OpenCV实现

CV基础学习Task1, 图像插值算法
Pytorch可用torch.nn.functional.interpolate上下采样方法。
双线性插值法在目标检测的应用:Mask RCNN网络的roi align, YOLOv3的上采样,deformable conv的卷积变换。