学无疑物-上采样之双线性插值法详解
什么是插值
Interpolation is a method of constructing new data points within the range of a discrete set of known data points. Image interpolation refers to the“guess”of intensity values at missing locations.
简单来说,插值指利用已知的点来“猜”未知的点,图像领域插值常用在修改图像尺寸的过程,由旧的图像矩阵中的点计算新图像矩阵中的点并插入,不同的计算过程就是不同的插值算法
下图是自己实现双线性插值的效果
常用的插值算法
插值算法有很多种,这里列出关联比较密切的三种
最近邻法(Nearest Interpolation):计算速度最快,但是效果最差
双线性插值(Bilinear Interpolation):双线性插值是用原图像中4(2*2)个点计算新图像中1个点,效果略逊于双三次插值,速度比双三次插值快,属于一种平衡美,在很多框架中属于默认算法
双三次插值(Bicubic interpolation):双三次插值是用原图像中16(4*4)个点计算新图像中1个点,效果比较好,但是计算代价过大
最近邻法(Nearest Interpolation)
双线性插值法由原图中4个点计算新图中的1个点,在介绍计算过程前,需要先了解如何找到这4个点,双线性插值法找寻4个点的方式和最近邻法相似,这里顺带的了解下最近邻法的计算流程
最近邻法实际上是不需要计算新图像矩阵中点的数值的,直接找到原图像中对应的点,将数值赋值给新图像矩阵中的点,根据对应关系找到原图像中的对应的坐标,这个坐标可能不是整数,这时候找最近的点进行插值。对应关系如下:
src_x=des_x∗src_w/des_wsrc\_x = des\_x * src\_w / des\_wsrc_x=des_x∗src_w/des_w
src_y=des_y∗src_h/des_hsrc\_y = des\_y * src\_h / des\_hsrc_y=des_y∗src_h/des_h
变量含义如下:
src_xsrc\_xsrc_x : 原图像中像素点x坐标
src_ysrc\_ysrc_y : 原图像中像素点y坐标
des_xdes\_xdes_x : 目标图像中像素点x坐标
des_ydes\_ydes_y : 目标图像中像素点y坐标
src_wsrc\_wsrc_w : 原图像宽度(width)
src_hsrc\_hsrc_h : 原图像高度(height)
des_wdes\_wdes_w : 目标图像宽度(width)
des_hdes\_hdes_h : 目标图像高度(height)
总结
上图效果是最近邻法的计算过程示意图,由上图可见,最近邻法不需要计算只需要寻找原图中对应的点,所以最近邻法速度最快,但是会破坏原图像中像素的渐变关系,原图像中的像素点的值是渐变的,但是在新图像中局部破坏了这种渐变关系。
双线性插值对应关系
双线性插值的对应公式和前面的最近邻法一样,不一样的是根据对应关系不再是找最近的1个点,而是找最近的4个点,如下图所示。
这里可能还会有点小疑问,如果根据对应关系找到原图中的点不是在不同的点之间,而是跟原图像中的点重合,那该如何找4个点?关于这个问题要看一下双线性插值的计算公式,双线性插值实际上是从2个方向一共进行了3次单线性插值,咱们先了解单线性插值的计算方式。
单线性插值
已知中P1点和P2点,坐标分别为(x1, y1)、(x2, y2),要计算 [x1, x2] 区间内某一位置 x 在直线上的y值
根据初中的只是,2点求一条直线公式(这是双线性插值所需要的唯一的基础公式)
y−y1x−x1=y2−y1x2−x1\frac{y - y_1}{x - x_1} = \frac{y_2 - y_1}{x_2 - x_1}x−x1y−y1=x2−x1y2−y1
经过简单整理成下面的格式:
y=x2−xx2−x1y1+x−x1x2−x1y2y = \frac{x_2 - x}{x_2 - x_1} y_1 + \frac{x - x_1}{x_2 - x_1} y_2y=x2−x1x2−xy1+x2−x1x−x1y2
这里没有写成经典的AX+B的形式,因为这种形式从权重的角度更好理解。
首先看分子,分子可以看成xxx与x1x_1x1和x2x_2x2的距离作为权重,这也是很好理解的,P点与P1、P2点符合现行变化关系,所以P离P1近就更接近P1,反之则更接近P2
现在再把公式中的分式看成一个整体,原式可以理解成y1y_1y1与y2y_2y2是加权系数,如何理解这个加权,要返回来思考一下,咱们先要明确一下根本的目的:咱们现在不是在求一个公式,而是在图像中根据2个点的像素值求未知点的像素值。这样一个公式是不满足咱们写代码的要求的。
现在根据实际的目的理解,就很好理解这个加权了,y1y_1y1与y2y_2y2分别代表原图像中的像素值,上面的公式可以写成如下形式:
f(P)=x2−xx2−x1f(P1)+x−x1x2−x1f(P2)f(P) = \frac{x_2 - x}{x_2 - x_1} f(P_1) + \frac{x - x_1}{x_2 - x_1} f(P_2)f(P)=x2−x1x2−xf(P1)+x2−x1x−x1f(P2)
双线性插值
已知Q11(x1,y1)、Q12(x1,y2)、Q21(x2,y1)、Q22(x2,y2),求其中点P(x,y)的值。
前面介绍过双线性插值是分别在两个方向计算了共3次单线性插值,如图所示,先在x方向求2次单线性插值,获得R1(x, y1)、R2(x, y2)两个临时点,再在y方向计算1次单线性插值得出P(x, y)(实际上调换2次轴的方向先y后x也是一样的结果)
- x方向单线性插值
直接带入前一步单线性插值最后的公式
f(R1)=x2−xx2−x1f(Q11)+x−x1x2−x1f(Q21)f(R_1) = \frac{x_2 - x}{x_2 - x_1} f(Q_{11}) + \frac{x - x_1}{x_2 - x_1} f(Q_{21})f(R1)=x2−x1x2−xf(Q11)+x2−x1x−x1f(Q21)
f(R2)=x2−xx2−x1f(Q12)+x−x1x2−x1f(Q22)f(R_2) = \frac{x_2 - x}{x_2 - x_1} f(Q_{12}) + \frac{x - x_1}{x_2 - x_1} f(Q_{22})f(R2)=x2−x1x2−xf(Q12)+x2−x1x−x1f(Q22) - y方向单线性插值
f(P)=y2−yy2−y1f(R1)+y−y1y2−y1f(R2)f(P) = \frac{y_2 - y}{y_2 - y_1} f(R_1) + \frac{y - y_1}{y_2 - y_1} f(R_2)f(P)=y2−y1y2−yf(R1)+y2−y1y−y1f(R2)
将第一步结果带入第二步
f(x,y)=f(Q11)(x2−x1)(y2−y1)(x2−x)(y2−y)+f(Q21)(x2−x1)(y2−y1)(x−x1)(y2−y)+f(Q12)(x2−x1)(y2−y1)(x2−x)(y−y1)+f(Q22)(x2−x1)(y2−y1)(x−x1)(y−y1)f(x, y)=\frac{f(Q_{11})}{(x_2-x_1)(y_2-y_1)} (x_2-x)(y_2-y) + \frac{f(Q_{21})}{(x_2-x_1)(y_2-y_1)} (x-x_1)(y_2-y) + \frac{f(Q_{12})}{(x_2-x_1)(y_2-y_1)} (x_2-x)(y-y_1) + \frac{f(Q_{22})}{(x_2-x_1)(y_2-y_1)} (x-x_1)(y-y_1)f(x,y)=(x2−x1)(y2−y1)f(Q11)(x2−x)(y2−y)+(x2−x1)(y2−y1)f(Q21)(x−x1)(y2−y)+(x2−x1)(y2−y1)f(Q12)(x2−x)(y−y1)+(x2−x1)(y2−y1)f(Q22)(x−x1)(y−y1)
回顾一下上面双线性插值对应关系的图,不难发现,在计算中有这样的关系x2=x1+1x_2 = x_1 + 1x2=x1+1;y2=y1+1y_2 = y_1 + 1y2=y1+1那么上面的公式中的分母全都为0,如下:
f(x,y)=f(Q11)(x2−x)(y2−y)+f(Q21)(x−x1)(y2−y)+f(Q12)(x2−x)(y−y1)+f(Q22)(x−x1)(y−y1)f(x, y)=f(Q_{11})(x_2-x)(y_2-y) + f(Q_{21})(x-x_1)(y_2-y) + f(Q_{12})(x_2-x)(y-y_1) + f(Q_{22})(x-x_1)(y-y_1)f(x,y)=f(Q11)(x2−x)(y2−y)+f(Q21)(x−x1)(y2−y)+f(Q12)(x2−x)(y−y1)+f(Q22)(x−x1)(y−y1)
在有些资料中,会写成权重的形式,上面的展开式是下面的权重表达式的正确求法
f(x,y)=f(Q11)w11+f(Q21)w21+f(Q12)w12+f(Q22)w22f(x, y)=f(Q_{11})w_{11} + f(Q_{21})w_{21} + f(Q_{12})w_{12} + f(Q_{22})w_{22}f(x,y)=f(Q11)w11+f(Q21)w21+f(Q12)w12+f(Q22)w22
这种权重的表达式也不难理解,观察一下可以发现每个点的权重都和待求点和对角点的距离有关,比如f(Q11)f(Q_{11})f(Q11)的权重与f(Q22)f(Q_{22})f(Q22)的坐标有关。
遗留问题
上面遗留了个小问题,就是当对应关系公式带入后跟原图像中的点发生重合后怎么选取剩下3个点,根据上面的公式可以发现,无论我们怎么选取,其实其余3点的权重都至少1项为0,所以不论我们怎么取剩下的3个点,对最终的结果都不会产生影响
总结
到此双线性插值的计算已经完成了,但是我们现在只能说是勉强的完成双线性插值算法,为什么这么说,现在的计算方式有比较大的问题,看下面的内容
双线性插值的优化
原始公式:
src_x=des_x∗src_w/des_wsrc\_x = des\_x * src\_w / des\_wsrc_x=des_x∗src_w/des_w
src_y=des_y∗src_h/des_hsrc\_y = des\_y * src\_h / des\_hsrc_y=des_y∗src_h/des_h
双线性插值的对应关系看似比较清晰,但还是有2个问题,我画图片进行说明
- 根据坐标系的不同,产生的结果不同
这张图是左上角为坐标系原点的情况,我们可以发现最左边x=0的点都会有概率直接复制到目标图像中(至少原点肯定是这样),而且就算不不和原图像中的点重合,也相当于进行了1次单线性插值(仔细想想为什么,带入到权重公式中会发现结果)
现在这张图是右上角为坐标系原点的情况,我们可以发现最右面的点都会有概率直接复制到目标图像中(至少原点肯定是这样),而且就算不不和原图像中的点重合,也相当于进行了1次单线性插值。这样如果我们采用不用的坐标系产生的结果是不一样的,而且无论我们采用什么坐标系,最左侧和最右侧(最上侧和最下侧)的点是不“公平的”,这是第一个问题
- 整体的图像相对位置会发生变化
看下面这张图,左侧是原图像(33),右侧是目标图像(55),原图像的几何中心点是(1, 1),目标图像的几何中心点是(2, 2),根据对应关系,目标图像的几何中心点对应的原图像的位置是(1.2, 1.2),如图所示,那么问题来了,目标图像的原点(0, 0)点和原始图像的原点是重合的,但是目标图像的几何中心点相对于原始图像的几何中心点偏右下,那么整体图像的位置会发生偏移,为什么这样说,其实图像是由1个个的像素点组成,单纯说1个像素点是没有太大的意义的,1个像素点跟相邻像素点的值的渐变或者突变形成图像颜色的渐变或者边界,所以参与计算的点相对都往右下偏移会产生相对的位置信息损失。这是第二个问题
计算机视觉中的蝴蝶效应
其实对于咱们人眼,上面的2个问题都不会产生太大的结果,但是对于现在的基于学习的学习类算法,计算机通过卷积神经网络提取图像中的深层信息,在这个过程中,我们人眼难以发现的变化也许会发生想象之外的变化,所以不要小看这两个问题
解决方案
几何中心点重合对应公式:
src_x=(des_x+0.5)∗src_w/des_w−0.5src\_x = (des\_x + 0.5) * src\_w / des\_w - 0.5src_x=(des_x+0.5)∗src_w/des_w−0.5
src_y=(des_y+0.5)∗src_h/des_h−0.5src\_y = (des\_y + 0.5) * src\_h / des\_h - 0.5src_y=(des_y+0.5)∗src_h/des_h−0.5
再带入到上面的情况,可以发现问题解决了,到此,才算完成完整的双线性插值法,当然如果这样计算发现结果跟OpenCV的结果不一样,是因为OpenCV还进行了很多速度上的优化,比如用整形计算代替浮点数计算
代码
网上代码很多,其实看完上面的内容自己写一个双线性插值十分的简单,这里就不弄代码了
学无疑物-上采样之双线性插值法详解相关推荐
- 上采样之双线性插值法
上采样之双线性插值法 One:上采样的定义 上采样的类型: 一.双线性插值: 二.转置卷积 : 三.上采样(unsampling) 四.上池化(unpooling) 总结: tow:具体的讲解双线性插 ...
- 跟着小马哥学系列之 Spring AOP(Pointcut 组件详解)
学好路更宽,钱多少加班. --小马哥 版本修订 2021.5.19:去除目录 2021.5.21:引用 Spring 官方 Pointcut 概念,修改 Pointcut 功能表述 简介 大家好,我是 ...
- 史上最小白之Transformer详解
1.前言 博客分为上下两篇,您现在阅读的是下篇史上最小白之Transformer详解,在阅读该篇博客之前最好你能够先明白Encoder-Decoder,Attention机制,self-Attenti ...
- python如何做散点图-matplotlib在python上绘制3D散点图实例详解
大家可以先参考官方演示文档: 效果图: ''' ============== 3D scatterplot ============== Demonstration of a basic scatte ...
- python画三维温度散点图-matplotlib在python上绘制3D散点图实例详解
大家可以先参考官方演示文档: 效果图: ''' ============== 3D scatterplot ============== Demonstration of a basic scatte ...
- python绘制散点图-matplotlib在python上绘制3D散点图实例详解
大家可以先参考官方演示文档: 效果图: ''' ============== 3D scatterplot ============== Demonstration of a basic scatte ...
- 史上最简单MySQL教程详解(进阶篇)之存储过程(一)
史上最简单MySQL教程详解(进阶篇)之存储过程(一) 史上最简单MySQL教程详解(进阶篇)之存储过程(一) 什么是存储过程 存储过程的作用 如何使用存储过程 创建存储过程 DELIMITER改变分 ...
- 史上最简单MySQL教程详解(进阶篇)之存储引擎介绍及默认引擎设置
什么是存储引擎? MySQL存储引擎种类 MyISAM 引擎 InnoDB引擎 存储引擎操作 查看存储引擎 存储引擎的变更 修改默认引擎 什么是存储引擎? 与其他数据库例如Oracle 和SQL Se ...
- php设置上传文件大小限制_php修改上传文件大小限制实例详解
php修改上传文件大小限制实例详解 php在默认情况下,只允许上传一定大小的文件,当上传文件大小超过这个值时,将会出错.本文章将向大家讲解php.ini中如何修改上传文件大小限制.需要修改的设置有三个 ...
最新文章
- pytorch 报错No module named torch
- 编码练习——Java-4-字符串
- 发送广播_DHCP服务器什么时候发送?为什么request要广播发送?那还不看?
- 和谐社区,和谐技术:微软的宠儿们,为什么富人的孩子就不能早当家?
- thymealf 高级用法_史上最详 Thymeleaf 使用教程
- 体验 DreamSpark
- 北上广深的请注意,阿里聚安全来找你玩啦~
- [Java] 蓝桥杯ADV-155 算法提高 上帝造题五分钟
- 【C/C++】BOOST 线程完全攻略 - 基础篇
- java解析搜狗词库scel文件到txt
- 数据库中的多表查询总结
- Himall商城普通帮助类(四)
- android软件安装到平板,新人看过来 安卓平板装机必备软件推荐
- 漂亮的网络验证php源码,好用的冰心php网络验证和源码例子
- 怎么管理一个测试团队
- html编辑器如何设置滚动字幕,使用Axure RP为网页添加滚动字幕的具体操作步骤
- WINVNC源码分析(四)——IO之rdr库
- Flask Web学习(5)----Markdown 和Flask -Pagedown的使用
- Java 周日期计算工具,获取当前第几周,按周数获取周一至周日,按日期获取周一至周日
- 当我去了不到 20 人的 IT 公司后。。。