新人学习opencv图像处理的笔记,一:c++操作图像放大

新人学习opencv图像处理的笔记,一:c++操作图像放大

笔者最近开始接触opencv,并且上学期学了一点数值计算,所以觉得计算机图像挺有意思的,故而诞生了写笔记的想法

好了,废话不多说,由于笔者水平有有限,如有错误,敬请指正(!^ _ ^!)

一些入门基础点

首先,在实践操作前,我们得了解下,什么是计算机图像,对通常的彩色图像而言,计算机图像就是一个个紧密排列的像素点组成,这些像素点呈现不同的颜色,共同组成了一个完整的画面如下图所示

在这里插入图片描述
值得注意的是,图像在计算机内,是以矩阵的方式保存的,矩阵的行列代表图像的长宽,其中每个元素代表一个像素点,而每一个元素的组成,则代表了该像素点的颜色(三通道RGB的矩阵分别有红绿蓝三个颜色的通道,每个通道上的数值又代表了该颜色的深浅。例如:(255,255,255)代表的是黑色,(0,0,0)代表的是白色)。

实现图像放大需要面临的问题

这个问题其实笔者大一就想过,但是当时觉得图像既然是像素点保存的,那么就应该是一个离散的数据,当时了解的不多也就不了了之,直到上学期,笔者上了数值计算这门课,才有了思路

问题1:在我们眼中的图像颜色是连续的,渐变的, 这个渐变可以用导数的思维来思考,正是因为导数的存在,使得图像的局部色差不会太大,从而有渐变连续的视觉效果。但正如前面所说,计算机图像是以离散的数据保存下来的,所以我们需要想一个办法,来给离散的数据求导------插值拟合,通过给离散的数据点拟合一个连续的函数,从而可以求导,使得像素是连续的。

问题2:图像放大后,新图会比原图多出很多像素点,我们该如何去定位和确定像素值?比如,上图中,是4x4,而在放大两倍后,会变成8x8的图像,这么多的像素点,我们该如何去确定呢?

解决方法

1:怎么解决第一个问题,那就是插值拟合函数,几种拟合方法,会在后文介绍。

2:怎么解决第二个问题,那我们就需要定义一个映射含函数。把新图中的点和原途中的点,通过一个函数 : f(x) 联系起来。然后通过拟合出的函数来确定像素值。

三种拟合办法

双线性插值法

双线性插值的思想是分别在 x 和 y方向做一次插值,从而实现像素值的填充。这里笔者提供一种简单的方法。
假设原图矩阵 R行 C列,即 RXC,在放大 m 倍数后变成 Rm * Cm,即 r * c 。首先创建一个 r * c的矩阵,然后把原途中的像素均匀有间隔的平铺在新途中,那我需要寻找的像素点就只有 r * c - R * C个了。
在这里插入图片描述
然后通过构造一次函数,来计算空白点的值。上图中,从横坐标方向上看,绿色点的值和红色点的值可以通过 像素值Pixle 和 横坐标x来构造一个一次函数。而两点中间空白点的值,则通过这个一次函数来确定。
比如红绿点,构造一次函数。以绿点为起点,有 P = (PR - PG)/(XR - XG) * (X - XG) + PG。公式的意思是,用已知的两点确定一条直线,在直线中确定未知点的值(边界点可以自己设置一个较合适的数值进行处理)。通过第一次循环遍历后,我们处理了有颜色横向像素如图
在这里插入图片描述
接下来的工作就是处理纵向像素,操作方法同上
在这里插入图片描述
这是笔者的结果图,很明显,数值插值公式的选择的问题,导致像素点间变化生硬,效果不行。

最邻近插值法

先上效果图
在这里插入图片描述
这个方法就比双线性插值更粗暴,更简单,但是笔者的效果图比双线性更好,这里是为什么,笔者也没找到答案。可能是写的双线性的程序有点问题,这里先存疑。
这个方法的操作,把新图上的点,重新映射到原图上。通过公式计算
在这里插入图片描述
其中i,j是新图中的坐标,XY是原图中对应的整数坐标,R是小数部分。这里解释一下,为什么会有小数和整数之分,因为放大的关系,新的像素点比原图多,那么两者之间的映射就不一定是一一对应的,新图中的整数坐标点不一定对应原图中整数坐标点,所以会有小数部分的存在。
在这里插入图片描述
如图,红圈点在原图中对应的不是整数(正中心), 而是有偏差R的。有了这个偏差就好办了。用整数部分去对应原图中的整数点,然后根据这个偏差,看这个还原在原图中的映射靠哪个点近,就把这个邻近点的值赋给新点。(注意,不要看上图来理解,要根据R大小来确定,R>0.5,就取下一个点,否则取这个整数点。)

二次插值(存疑)

由于有双线性插值,笔者就在想,会不会二次插值效果更好一点,结果并非如此。
笔者同样采用多点构造的方法,只不过使用的拟合函数是用三个点确定的二次函数,用二次拉格朗日插值公式得到。看起来合理,但是得到效果图惨不忍睹。
在这里插入图片描述
在这里插入图片描述
下面是效果图,我写报告时心血来潮的产物,结果不忍直视。

笔者真不知道这是代码错误还是插值错误

双三插值法

这个插值法笔者也说不清楚是怎么回事,也是在老师提示下,查了这个方法
由于笔者水平有限所以只给了一个公式截图,具体详情请看下方超链接。
在这里插入图片描述

参考资料

总结和思考

笔者也是初次写博客,如果有什么不对,还请多多指教。
笔者觉得,对于图像的resize,主要是对于离散数据的操作,要通过一些比较好的插值方法还原函数,尽可能地在导数上做一些优化,使得局部像素变化平滑。对于那些突变地像素点,则可以使用梯度来算法来进行边缘检测(笔者用了一个很笨的方法实现了轮廓检测,感觉自己好蠢,(* ^ _ ^ * ))。一个risize的好坏取决于函数的否平滑,而函数的平滑取决于导数和梯度,所以笔者在想,除开突变点,如果一个函数在满足所有离散点的情况下,且变化平稳,那一定就是最好的办法了。
总之,还是感谢大家看了我的博客。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值