基于Python实现二维图像双线性插值
作者:为为为什么 发布时间:2023-08-13 07:46:45
在对二维数据进行 resize / mapping / 坐标转换等操作时,经常会将原本的整数坐标变换为小数坐标,对于非整数的坐标值一种直观有效的插值方式为双线性插值。
插值简介
双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
双线性插值作为数值分析中的一种插值算法,广泛应用在信号处理,数字图像和视频处理等方面。
假设我们出现了需要在四个相邻正方形整数点(A,B,C,D)坐标中间(正方形范围内)选择一个点(a,b)取近似值的情形。
此时我们已知的是四个点的数值VA,VB,VC,VD,给定小数坐标E(a,b),0≤a,b≤1,如何插值求解E点的数值呢,解决类似问题的方法统称为插值,上图展示公式为双线性插值的计算方法。
最近邻法 (Nearest Interpolation)
一种最简便的方法为最近邻法,直接取与当前点距离最近的点的值作为插值结果:
其中 roundroundround 为四舍五入的取整操作,方法简便速度极快,但往往不够精细
双三次插值 (Bicubic interpolation)
双三次插值是用原图像中16(4*4)个点计算新图像中1个点,效果比较好,但是计算代价过大。
双线性插值 (Bilinear Interpolation)
使用一个点进行插值过于粗暴,16个点又过于繁琐,那就使用EEE点周围4个点的数值来近似求解,这是一种平衡了计算代价和插值效果的折中方案,也是各大变换库的默认插值操作。
双线性插值
通过观察上述动图(可以动手挪一挪)可以清晰地看到,双线性插值本质就是把四个角落的数值按照正方形面积的比例线性加权后的结果。
好吧一句话已经把数学的核心部分讲完了
那么既然理解了本质,数学公式就好写了:
python实现
在实现时当然 for 循环 * 可以解决一切问题,但总归是不太优雅,我们尝试使用 numpy 操作完成双线性插值
假设原始图像 image
,变换后的小数坐标 X 矩阵 x_grid
,Y 矩阵 y_grid
,那么可以使用如下的 bilinear_by_meshgrid
函数快速双线性插值,已经处理好了边界,可以放心使用。
def bilinear_by_meshgrid(image, x_grid, y_grid):
# Ia, Wd Ic, Wb
# (floor_x, floor_y) (ceil_x, floor_y)
#
# (x, y)
#
# Ib , Wc Id, Wa
# (floor_x, ceil_y) (ceil_x, ceil_y)
#
assert image.shape == x_grid.shape == y_grid.shape
assert image.ndim == 2
H, W = image.shape[:2]
floor_x_grid = np.floor(x_grid).astype('int32')
floor_y_grid = np.floor(y_grid).astype('int32')
ceil_x_grid = floor_x_grid + 1
ceil_y_grid = floor_y_grid + 1
if np.max(ceil_x_grid) > W -1 or np.max(ceil_y_grid) > H -1 or np.min(floor_x_grid) < 0 or np.min(floor_y_grid) < 0:
print("Warning: index value out of original matrix, a crop operation will be applied.")
floor_x_grid = np.clip(floor_x_grid, 0, W-1).astype('int32')
ceil_x_grid = np.clip(ceil_x_grid, 0, W-1).astype('int32')
floor_y_grid = np.clip(floor_y_grid, 0, H-1).astype('int32')
ceil_y_grid = np.clip(ceil_y_grid, 0, H-1).astype('int32')
Ia = image[ floor_y_grid, floor_x_grid ]
Ib = image[ ceil_y_grid, floor_x_grid ]
Ic = image[ floor_y_grid, ceil_x_grid ]
Id = image[ ceil_y_grid, ceil_x_grid ]
wa = (ceil_x_grid - x_grid) * (ceil_y_grid - y_grid)
wb = (ceil_x_grid - x_grid) * (y_grid - floor_y_grid)
wc = (x_grid - floor_x_grid) * (ceil_y_grid - y_grid)
wd = (x_grid - floor_x_grid) * (y_grid - floor_y_grid)
assert np.min(wa) >=0 and np.min(wb) >=0 and np.min(wc) >=0 and np.min(wd) >=0
W = wa + wb + wc + wd
assert np.sum(W[:, -1]) + np.sum(W[-1, :]) == 0
wa[:-1, -1] = ceil_y_grid[:-1, -1] - y_grid[:-1, -1]
wb[:-1, -1] = y_grid[:-1, -1] - floor_y_grid[:-1, -1]
wb[-1, :-1] = ceil_x_grid[-1, :-1] - x_grid[-1, :-1]
wd[-1, :-1] = x_grid[-1, :-1] - floor_x_grid[-1, :-1]
wd[-1, -1] = 1
W = wa + wb + wc + wd
assert np.max(W) == np.min(W) == 1
res_image = wa*Ia + wb*Ib + wc*Ic + wd*Id
return res_image
该函数集成在我自己的python库 mtutils
中,可以通过:
pip install mtutils
直接安装,之后可以直接引用:
from mtutils import bilinear_by_meshgrid
来源:https://juejin.cn/post/7107479950084538376


猜你喜欢
- 目录Ⅰ. 简介Ⅱ. 注意事项Ⅲ. 使用方法Ⅳ. 教程首先spring自带了mongodb的orm,spring data mongodb,但
- 1969年8月8日,在北京协和医院降生了一个漂亮的小女孩。接生的阿姨说,她的声音这么大,好象想要全世界的人都听到。后来,她的父亲为她取了一个
- 刚刚心血来潮,编了一个国际域名查询的功能页面,比较简单,没有做什么美化和修饰,主要利用了服务器端的XMLHTTP访问第三方服务器实现域名查询
- <html><head><meta http-equiv="Content-Type" c
- python matplotlib画图产生的Type 3 fonts字体不兼容更改措施:使用Type 42字体来生成PostScript 和
- 在使用reflect包获取函数,并调用时,总出现这个报错:panic: reflect: call of reflect.Value.Cal
- 原作者:Nik Piepenbreier翻译&内容补充:费弗里原文地址:https://towardsdatascience.com
- 说明1、利用_slots__类属性,可以将实例属性存储在元zu中,大大节省了存储空间。2、所有属性都必须定义为__slots__元组,子类还
- 本文实例为大家分享了Python3连接MySQL模拟转账的具体实现代码,供大家参考,具体内容如下# coding:utf8import sy
- 有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用
- ASP开发中有用的function集合,挺有用处的!希望大家保留!<% '**
- 本文实例讲述了Python实现网络端口转发和重定向的方法。分享给大家供大家参考,具体如下:【任务】需要将某个网络端口转发到另一个主机(for
- KindEditor简介: KindEditor是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用
- 前言前几天写了一篇MySQL高并发生成唯一订单号的方法,有人私信问有没有SQL server版本的,今天中午特地写了SQL server版本
- python保存图片时和原图大小一致之前遇到过一次这个问题,当时解决了但是忘了记录,这里再记录一次好了。1. matplotlib系列的整体
- 桑基图桑基图(Sankey diagram),即桑基能量分流图,也叫桑基能量平衡图。它是一种特定类型的流程图,图中延伸的分支的宽度对应数据流
- 前面我们用python实现了贪吃蛇、坦克大战、飞船大战、五子棋等游戏今天我们用python来实现一下扫雷游戏本游戏代码量和源文件较多可以从我
- 英文的文档在这里,详细全面,本文仅为自己的学习笔记,只是试图通过转述加深自己的学习,不详细不全面。由于浏览器之间的差异,所以在JS中监听事件
- 引言最近在工作中写一个批处理脚本,令人抓狂的是每次都不知道脚本要跑到啥时候结束,于是想到给程序添加个进度条。逛了一圈,没找到特别趁手的轮子,
- windows server 2019安装了SQL2016,启动sql agent代理时候,提示“尚未定义空闲cpu条件 onidle作业计