最近邻插值、双线性插值、双三次插值

 

1.最近邻插值

越是简单的模型越适合用来举例子,我们就举个简单的图像:3X3 的256级灰度图,也就是高为3个象素,宽也是3个象素的图像,每个象素的取值可以是 0-255,代表该像素的亮度,255代表最亮,也就是白色,0代表最暗,即黑色。假如图像的象素矩阵如下图所示(这个原始图把它叫做源图,Source):
234   38    22
67     44    12
89     65    63

这个矩阵中,元素坐标(x,y)是这样确定的,x从左到右,从0开始,y从上到下,也是从零开始,这是图象处理中最常用的坐标系,就是这样一个坐标:

  ---------------------->X
  |
  |
  |
  |
  |
∨Y

如果想把这副图放大为 4X4大小的图像,那么该怎么做呢?那么第一步肯定想到的是先把4X4的矩阵先画出来再说,好了矩阵画出来了,如下所示,当然,矩阵的每个像素都是未知数,等待着我们去填充(这个将要被填充的图的叫做目标图,Destination):
?        ?        ?       ?
?        ?        ?       ?
?        ?        ?       ?
?        ?        ?       ? 
               
        然后要往这个空的矩阵里面填值了,要填的值从哪里来来呢?是从源图中来,好,先填写目标图最左上角的象素,坐标为(0,0),那么该坐标对应源图中的坐标可以由如下公式得出:                                      
srcX=dstX* (srcWidth/dstWidth) , srcY = dstY * (srcHeight/dstHeight)
好了,套用公式,就可以找到对应的原图的坐标了(0*(3/4),0*(3/4))=>(0*0.75,0*0.75)=>(0,0)
,找到了源图的对应坐标,就可以把源图中坐标为(0,0)处的234象素值填进去目标图的(0,0)这个位置了。

接下来,如法炮制,寻找目标图中坐标为(1,0)的象素对应源图中的坐标,套用公式:
(1*0.75,0*0.75)=>(0.75,0)
结果发现,得到的坐标里面竟然有小数,这可怎么办?计算机里的图像可是数字图像,象素就是最小单位了,象素的坐标都是整数,从来没有小数坐标。这时候采用的一种策略就是采用四舍五入的方法(也可以采用直接舍掉小数位的方法),把非整数坐标转换成整数,好,那么按照四舍五入的方法就得到坐标(1,0),完整的运算过程就是这样的:
(1*0.75,0*0.75)=>(0.75,0)=>(1,0)
那么就可以再填一个象素到目标矩阵中了,同样是把源图中坐标为(1,0)处的像素值38填入目标图中的坐标。
         
依次填完每个象素,一幅放大后的图像就诞生了,像素矩阵如下所示:
234    38     22     22  
67      44     12     12  
89      65     63     63  
89      65     63     63  

这种放大图像的方法叫做最临近插值算法,这是一种最基本、最简单的图像缩放算法,效果也是最不好的,放大后的图像有很严重的马赛克,缩小后的图像有很严重的失真;效果不好的根源就是其简单的最临近插值方法引入了严重的图像失真,比如,当由目标图的坐标反推得到的源图的的坐标是一个浮点数的时候,采用了四舍五入的方法,直接采用了和这个浮点数最接近的象素的值,这种方法是很不科学的,当推得坐标值为 0.75的时候,不应该就简单的取为1,既然是0.75,比1要小0.25 ,比0要大0.75 ,那么目标象素值其实应该根据这个源图中虚拟的点四周的四个真实的点来按照一定的规律计算出来的,这样才能达到更好的缩放效果。双线型内插值算法就是一种比较好的图像缩放算法,它充分的利用了源图中虚拟点四周的四个真实存在的像素值来共同决定目标图中的一个像素值,因此缩放效果比简单的最邻近插值要好很多。

 

2.双线性插值

根据于待求点P最近4个点的像素值,计算出P点的像素值。

1)简单理解

对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v) (其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:

  f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)

其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。

2)一般性

如上图,已知Q12,Q22,Q11,Q21,但是要插值的点为P点,这就要用双线性插值了,首先在x轴方向上,对R1和R2两个点进行插值,这个很简单,然后根据R1和R2对P点进行插值,这就是所谓的双线性插值。说明:下式中f(*)为*点处像素值。

首先在 x 方向进行线性插值,得到:

然后在 y 方向进行线性插值,得到:

也即点P处像素值:

 

3.双三次插值

假设源图像A大小为m*n,缩放K倍后的目标图像B的大小为M*N,即K=M/m。A的每一个像素点是已知的,B是未知的,我们想要求出目标图像B中每一像素点(X,Y)的值,必须先找出像素(X,Y)在源图像A中对应的像素(x,y),再根据源图像A距离像素(x,y)最近的16个像素点作为计算目标图像B(X,Y)处像素值的参数,利用BiCubic基函数求出16个像素点的权重,图B像素(x,y)的值就等于16个像素点的加权叠加。

根据比例关系x/X=m/M=1/K,我们可以得到B(X,Y)在A上的对应坐标为A(x,y)=A(X*(m/M),Y*(n/N))=A(X/K,Y/K)。如图所示P点就是目标图像B在(X,Y)处对应于源图像A中的位置,P的坐标位置会出现小数部分,所以我们假设 P的坐标为P(x+u,y+v),其中x,y分别表示整数部分,u,v分别表示小数部分(蓝点到a11方格中红点的距离)。那么我们就可以得到如图所示的最近16个像素的位置,在这里用a(i,j)(i,j=0,1,2,3)来表示,如上图。

 

 我们要做的就是求出BiCubic函数中的参数x,从而获得上面所说的16个像素所对应的权重W(x)。BiCubic基函数是一维的,而像素是二维的,所以我们将像素点的行与列分开计算。BiCubic函数中的参数x表示该像素点到P点的距离,例如a00距离P(x+u,y+v)的距离为(1+u,1+v),因此a00的横坐标权重i_0=W(1+u),纵坐标权重j_0=W(1+v),a00对B(X,Y)的贡献值为:(a00像素值)* i_0* j_0。因此,a0X的横坐标权重分别为W(1+u),W(u),W(1-u),W(2-u);ay0的纵坐标权重分别为W(1+v),W(v),W(1-v),W(2-v);B(X,Y)像素值为:

对待插值的像素点(x,y)(x和y可以为浮点数),取其附近的4x4邻域点(xi,yj), i,j = 0,1,2,3。按如下公式进行插值计算:

https://img-my.csdn.net/uploads/201301/21/1358782084_2539.PNG

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java map转json字符串_Java-Gso-json字符串解析-php后台返回字段类型可能为字符串(/空字符串)或者对象的情况...

其实本来android前端定义的对象类型是对象,如果后台没有值的情况下,理论上给null,如果是数组给[]或者null都可以的。这样Gson再解析转换的时候就不会出问题!但是最近重构发现后台如果没有字段值给的是""空字符串&#x…

oracle中时间加减一年的写法

select add_months(date2019-5-15,-12) from dual; -- 2018-5-15 通过add_months(x,y)函数,在给定的时间x固定的月份y select date2019-5-15 interval -1 year from dual; --2018-5-15 通过interval函数,这个用来表示一段时间间隔,有固定的格式,这里用来加一年&a…

'fopen' This function or variable may be unsafe

1>...error C4996: fopen: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> 正在生成代码... 生成: 成功 0 个,失败 1 个,最…

python3捕获异常_python中异常捕获方法详解

在Python中处理异常使用的是try-except代码块,try-except代码块放入让python执行的操作,同时告诉python程序如果发生了异常该怎么办,try-except这个功能其实很多入门书籍中都放到了高级篇幅里,在入门的时候一般不会讲这个使用&…

自定义java线程池_我的Java自定义线程池执行器

自定义java线程池ThreadPoolExecutor是Java并发api添加的一项功能,可以有效地维护和重用线程,因此我们的程序不必担心创建和销毁线程,也不必关注核心功能。 我创建了一个自定义线程池执行程序,以更好地了解线程池执行程序的工作方…

es6方法过滤掉两个数组中对象id值相等的项

let arr1[{id:1,name:张三},{id:2,name:李四}] let arr2[{id:1,name:张三},{id:3,name:王五},{id:44,name:王柳},{id:45,name:王琦},] let addarr2.filter(item>!arr1.some(ele>ele.iditem.id)) console.log(add) const arr1 [{ id: 1, name: 网 }, { id: 2, name: 二位…

大尾和小尾

字节存放有大尾和小尾之分。如果对应数据的高字节存放在低地址就是大尾,反之,高字节存放在高地址的就是小尾。 比如 short int a 0x1234 大尾存放时: 偏移地址 存放内容 0x0000 0x12 0x0001 0x34 小尾存放: 偏移…

jedis使用_Redis的三个框架:Jedis,Redisson,Lettuce

Jedis api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.htmlredisson 官网地址:https://redisson.org/redisson git项目地址:https://github.com/redisson/redissonlettuce 官网地址:https://le…

端到端BPM(带有DMN标记)

下周的红帽峰会即将成为有史以来最好的峰会之一! 而且,如果您是Drools或jBPM的狂热者,您会很忙 :Signavio和Red Hat之间的合作伙伴关系是我们为您准备的另一个顶级演讲。 邓肯道尔(Duncan Doyle)和汤姆德贝…

pycharm写python字典_pythonpycharm安装基础语法

1.python安装安装python3,建议安装python3.7,不要安装python2安装时需要注意的地方:安装完成后,验证python是否安装成功,在cmd下输入python,出现python的版本则表明安装成功验证pip是否安装成功&#xff0c…

模板库 | 销售管理类报表,邀您提反馈

“葡萄城报表模板库是一款免费的报表制作、学习和参考工具,包含了超过 200 张高质量报表模板,涵盖了 16 大行业和 50 多种报表类型,为 30 余万报表开发者提供价值参考。” 近期,葡萄城推出了“寻找真正的报表大师”活动&#xff0…

矩阵的逆、伪逆

1、矩阵的逆 定义: 设A是数域上的一个n阶方阵,若在相同数域上存在另一个n阶矩阵B,使得: ABBAI。 则我们称B是A的逆矩阵,而A则被称为可逆矩阵。 可逆条件: A是可逆矩阵的充分必要条件是,即可…

PLSQL登录报错ORA-12154

https://blog.csdn.net/naomi_qing/article/details/79583453 转载于:https://www.cnblogs.com/2016-cxp/p/10878952.html

python将dataframe导出为csv_python将dataframe转换为csv,为每列导出一个格式独特的文本文件...

我正在Win7 64位上使用Python2.7.7和熊猫。我的输入数据最初是以空格分隔的,右对齐的。我现在有数据作为熊猫数据帧,我导出为一个csv。我想写一个空格分隔的右对齐文本文件。列有字符串、int和float。我试图用这个来格式化其中一个列:df_fg[M…

jax-rs/jersey_在Oracle Cloud上的Prime-UI,JAX-RS和Jersey和Gson

jax-rs/jersey如今,Oracle云无处不在。 最初,拉里(Larry)否认在很长一段时间内都需要云,并且在去年的开放世界(Open World)之后就发布了一些非常早的公告,而且可用性很差&#xff0c…

OpenCV copyMakeBorder()来拓展边界

使用OpenCV提供的函数copyMakeBorder()来拓展边界,其原型如下 void copyMakeBorder( InputArray src, OutputArray dst,int top, int bottom, int left, int right, int borderType,const Scalar& value Scalar())​ src:输入的数组。 dst&…

Flutter-现有iOS工程引入Flutter

前言 Flutter 是一个很有潜力的框架,但是目前使用Flutter的APP并不算很多,相关资料并不丰富,介绍现有工程引入Flutter的相关文章也比较少。项目从零开始,引入Flutter操作比较简单,但是现有工程引入Flutter 需要费很多精…

python有什么隐藏功能_Python的隐藏功能

文章目录Python编程语言的鲜为人知的但有用的功能是什么?尝试限制Python核心的答案。每个答案的一个功能给出一个功能的例子和简短描述,而不仅仅是文档的链接。使用标题作为第一行标记该功能。Quick links to answers:Chaining comparison operators:>…

Spring Boot –适合您的靴子!

您需要一点弹簧吗? 厌倦了所有繁琐的Web服务器并部署WAR文件? 好吧,你很幸运。 Spring Boot对构建可用于生产的Spring应用程序持坚定态度。 Spring Boot倾向于使用约定而非配置,它旨在使您尽快启动并运行。 在此博客中&#xff0…

OpenCV 像素的读取与操作

像素读取和操作 1. 利用cv::Mat的at函数,直接访问具体地址 void get_setImagePixel(char *imagePath, int x, int y){// Mat image imread(imagePath , 0);Mat image imread(imagePath, 1);//得宽高int w image.cols;int h image.rows;int channels image.c…