复盘图像双线性插值推导细节

您所在的位置:网站首页 双线性插值公式推导 复盘图像双线性插值推导细节

复盘图像双线性插值推导细节

2023-08-13 16:31| 来源: 网络整理| 查看: 265

双线性插值概念

双线性插值在图像领域经常用来修改图像尺寸的过程,简单来说,插值指利用已知的点来“猜”未知的点,由旧的图像矩阵中的点计算新图像矩阵中的点并插入。本文旨在复盘双线性插值的所有实现细节。

单线性插值

线性插值顾名思义,就是根据一个线性关系来在两点之间插入一个点,利用直线任意点斜率不变来求得插入点的值。如下图,Q11和Q21两点的坐标和值,求R1点的值,根据斜率不变可得:

                    

 

双线性插值

单线性插值是已知两个点,求一个点的值,坐标只是一维空间,而双线性插值则多数为二维空间,即坐标为(x,y)的形式。如下图,如果想知道点P的值,此时则需要找到插值点相邻的四个点。

求解思路:

1,先找到点P相邻的四个点Q11,Q21,Q12, Q22。

2,将x,y坐标拆分成两个一维的单线性插值,求出R1,R2的值,如上面的单线性插值示意推理公式。

3,点P在y方向上进行单线性插值。

最后合在一起,即:

 

图像的双线性插值

根据上面合并的公式,运用到图像的双线性插值时候,我们找到插值的四个点Q11,Q21,Q12, Q22一般是相邻的,即坐标关系是(x1,y1),(x1+1,y1),(x1,y1+1),(x1+1,y1+1)。所以f(x,y)的公式中x2=x1+1, y2=y1+1又可以化简为:

   

对一张RGB的3通道图像,(1)中的x,y就是图像单通道上weights,heights上的坐标点,f(x,y)则是该通道的像素值,得到了目标点dstX,dstY在原图上对应近邻的四个点坐标srcX, srcY后,三个通道重复代入公式计算f(x,y)就是对应RGB通道的插值结果。

srcX=dstX* (srcWidth/dstWidth),srcY = dstY * (srcHeight/dstHeight)

根据上面公式,目标点dstX,dstY的像素值:f(dstX,dstY)=f(srcX,srcY),而srcX,srcY一般是一个浮点数,srcX,srcY 分别向上和向下取整就得到了原图中四个点的坐标。利用(1)双线性插值推理公式就得到了dstX, dstY的像素值。

 

当代码实现时,(1)可以有更简单的实现。

已知srcX,srcY是一个浮点数,令i,u指代srcX的整数和小数部分,j,v指代srcY的整数和小数部分,则(1)公式还可以化简为:

  

 

图像的双线性插值流程示意如下,注意当求目标像素坐标和原图像的像素坐标时候,一般不用

srcX=dstX* (srcWidth/dstWidth),srcY = dstY * (srcHeight/dstHeight)

而使用

srcX=(dstX+0.5)* (srcWidth/dstWidth)-0.5srcY = (dstY+0.5) * (srcHeight/dstHeight)-0.5

这是因为上面定义源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素,假设你需要将一幅5x5的图像缩小成3x3,那么源图像和目标图像各个像素之间的对应关系如下。如果没有这个中心对齐,根据基本公式去算,就会得到左边这样的结果,这时原图的最后一个像素不参与插值计算;而用了对齐,就会得到右边的结果,原图的每一个像素都进行了插值计算。左边的结果好像是目标图像进行了左上的平移,而右边则更贴近原图的中间位置线性插值效果。

preview

scale_x = src_Width / dst_Width scale_y = src_Height / dst_Height for n in range(3): # 对channel循环 for dst_y in range(dst_h): # 对height循环 for dst_x in range(dst_w): # 对width循环 # 目标在源上的坐标 src_x = (dst_x + 0.5) * scale_x - 0.5 src_y = (dst_y + 0.5) * scale_y - 0.5 # 计算在源图上四个近邻点的位置 src_x_0 = int(np.floor(src_x)) src_y_0 = int(np.floor(src_y)) src_x_1 = min(src_x_0 + 1, src_w - 1) src_y_1 = min(src_y_0 + 1, src_h - 1) # 双线性插值,方法(1) value0 = (src_x_1 - src_x) * src[src_y_0, src_x_0, n] + (src_x - src_x_0) * src[src_y_0, src_x_1, n] value1 = (src_x_1 - src_x) * src[src_y_1, src_x_0, n] + (src_x - src_x_0) * src[src_y_1, src_x_1, n] dst[dst_y, dst_x, n] = int((src_y_1 - src_y) * value0 + (src_y - src_y_0) * value1) # 双线性插值,方法(2) u=src_y-int(src_y) v=src_x-int(src_x) dst[dst_y,dst_x,n]=(1-u)*(1-v)*src[src_y_0, src_x_0,n]+u*(1-v)*src[src_y_1, src_x_0,n]+(1-u)*v*src[src_y_0, src_x_1,n]+u*v*src[src_y_1, src_x_1,n] return dst

 

 

 

参考

https://blog.csdn.net/qq_37577735/article/details/80041586

https://zhuanlan.zhihu.com/p/49832888

https://zhuanlan.zhihu.com/p/110754637



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3