从Nearest插值到Bilinear插值的分析与python实现

这篇主要是想分析一下Nearest差值和Bilinear差值的计算细节,然后附上对应的Python实现代码,希望对你有帮助:https://github.com/LonglongaaaGo/ComputerVision

效果

先给出实现效果。
首先我们有一张小狗狗:
请添加图片描述

然后用Nearest 上采样,能够得到:
请添加图片描述
可以看到,有很多的锯齿,看起来不是很完美。
然后试试这个实现的Bilinear 上采样:
请添加图片描述
能够看到整体上柔和很多~虽然有点模糊,但是比Nearest好了很多。

正文

图像在计算机当中进行表示的话,是离散的,形式如下:
在这里插入图片描述
就是 x , y x,y x,y能够表示对应在图像中的坐标,而 F F F看成对应的函数。 F [ x , y ] F[x,y] F[x,y]表示的就是对应的像素信息。为了方便 讨论,就从1通道进行解释。
但是如果我们想做变换的话,如果直接用离散的点进行变换,肯定会丢失很多信息,所以我们就要考虑在连续的空间里进行变换。对应的,表现形式可以如下:
在这里插入图片描述
如果我们将 F [ 0 , 0 ] F[0,0] F[0,0]的中心点作为坐标 ( 0 , 0 ) (0,0) (0,0)的话,那么对应的左对角的点就是 ( − 0.5 , − 0.5 ) (-0.5,-0.5) (0.5,0.5)。这种做法比较常见,也是比较推荐的一种形式。接下来就是要对图像进行缩放,缩放的公式就是:
(srcX+0.5) ⁡ = ( d s t X + 0.5 ) ∗ ( s r c W i d t h / d s t W i d t h ) \operatorname{(srcX+0.5)}=\mathrm{(dstX+0.5)} *(\mathrm{srcWidth} / \mathrm{dstWidth}) (srcX+0.5)=(dstX+0.5)(srcWidth/dstWidth)
(srcY+0.5) ⁡ = ( d s t Y + 0.5 ) ∗ ( s r c H e i g h t / d s t H e i g h t ) \operatorname{(srcY+0.5)}=\mathrm{(dstY+0.5)} *(\mathrm{srcHeight} / \mathrm{dstHeight}) (srcY+0.5)=(dstY+0.5)(srcHeight/dstHeight)
这里定义
(srcX,srcY) ⁡ \operatorname{(srcX,srcY)} (srcX,srcY)就是对应的原始图像的坐标
(dstX,dstY) ⁡ \operatorname{(dstX,dstY)} (dstX,dstY)就是对应的缩放后的图像的坐标
s r c W i d t h , s r c H e i g h t \mathrm{srcWidth,srcHeight} srcWidth,srcHeight就是原始图像的宽和高
d s t W i d t h , d s t H e i g h t \mathrm{dstWidth,dstHeight} dstWidth,dstHeight就是缩放后的图像的宽和高

通过上述公式和定义,我们可以很快地计算出缩放后的图片和原图之间的关系。根据上面公式得到各个点的位置之后,就需要将连续点转化成离散的点。而Nearest差值和Bilinear差值方法的区别,也主要在这一步:
Nearest 插值方法就比较简单,就是直接四舍五入将连续地点变成离散的整数。这样的做法存在的问题上面也看到了,就是会产生明显的锯齿。如果还不明白的话,看一眼代码会更加直观。形式如下图所示:
灰色代表要插入的点
就是说,假设灰色的点代表是插值的点,那么就是取其最近的颜色,作为插值后的颜色。所以在这里表示就是亮黄色。直接赋值。

双线性插值 Bilinear Interpolation,直观理解如下图所示:
在这里插入图片描述
我们还是建立在上述情况,这个时候,灰色的点 q q q位于 ( x , y ) (x,y) (x,y),不再是直接考虑最近的点,而是和其相近的四个点,然后通过面积的比重,来分配权重。所以公式可以表示成:
q = V 1 ∗ A 1 + V 2 ∗ A 2 + V 3 ∗ A 3 + V 4 ∗ A 4 q=V 1* A 1+V 2 * A 2+V 3*A 3+V 4* A 4 q=V1A1+V2A2+V3A3+V4A4
对应的计算就可以这么写(请参照图上的坐标进行一一对应):
f ( x , y ) ≈ f ( V 1 ) ( x 2 − x 1 ) ( y 2 − y 1 ) ( x 2 − x ) ( y 2 − y ) + f ( V 2 ) ( x 2 − x 1 ) ( y 2 − y 1 ) ( x − x 1 ) ( y 2 − y ) + f ( V 3 ) ( x 2 − x 1 ) ( y 2 − y 1 ) ( x 2 − x ) ( y − y 1 ) + f ( V 4 ) ( x 2 − x 1 ) ( y 2 − y 1 ) ( x − x 1 ) ( y − y 1 ) . \begin{aligned} &f(x, y) \approx \frac{f\left(V_{1}\right)}{\left(x_{2}-x_{1}\right)\left(y_{2}-y_{1}\right)}\left(x_{2}-x\right)\left(y_{2}-y\right)+\frac{f\left(V_{2}\right)}{\left(x_{2}-x_{1}\right)\left(y_{2}-y_{1}\right)}\left(x-x_{1}\right)\left(y_{2}-y\right) \\ &+\frac{f\left(V_{3}\right)}{\left(x_{2}-x_{1}\right)\left(y_{2}-y_{1}\right)}\left(x_{2}-x\right)\left(y-y_{1}\right)+\frac{f\left(V_{4}\right)}{\left(x_{2}-x_{1}\right)\left(y_{2}-y_{1}\right)}\left(x-x_{1}\right)\left(y-y_{1}\right) . \end{aligned} f(x,y)(x2x1)(y2y1)f(V1)(x2x)(y2y)+(x2x1)(y2y1)f(V2)(xx1)(y2y)+(x2x1)(y2y1)f(V3)(x2x)(yy1)+(x2x1)(y2y1)f(V4)(xx1)(yy1).

这样就能直接得到当前点 f ( x , y ) f(x,y) f(x,y)的值。
注意, f ( x , y ) f(x,y) f(x,y)表示的就是像素,以函数的形式来进行表示。 ( x 2 − x 1 ) ( y 2 − y 1 ) \left(x_{2}-x_{1}\right)\left(y_{2}-y_{1}\right) (x2x1)(y2y1)表示的就是总面积。
至此,Nearest差值和Bilinear差值讲解就结束了,可以看一下代码,更能够容易理解一点。在这里插入图片描述
如果觉得不错,记得关注哟!一起来学习深度学习,机器学习等前沿算法!!
欢迎转载!
参考:https://www.cnblogs.com/wojianxin/p/12516029.html

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐