糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 双线性插值算法 -- 个人学习思路及方法分享

双线性插值算法 -- 个人学习思路及方法分享

时间:2022-06-03 15:51:53

相关推荐

双线性插值算法 -- 个人学习思路及方法分享

Preface

最期待的数字图像课开课啦,然后第一次上机课老师让我们动手写双线性插值算法,有一点懵逼,然后陆陆续续学了几天终于把他实现出来了,花了这么多天还是归功于网上清一色一模一样的教程,鉴于此,我决定自己动手写一个教程。

下面先展示我学习过程的艰辛历程:

原图是这样子:

最终,经过一次次的失败,我终于成功了!对比原图,是不是效果还蛮不错呢!

Introduction

关于双线性插值的介绍,这里不过多赘述,简单描述一下就是对原图进行缩放时,将多出来或少出来的像素最优处理的算法。我们还可以使用KNN最近邻算法,但是效果很差,不够连续化,所以看着特别生硬,当然也可以选择三次线性插值,原理同二次类似。

下面介绍具体算法步骤:

首先我们知道图片是一个如下的矩阵,但是彩色图像是由三个颜色,三个通道的矩阵组成而来的,我们先研究一个矩阵的情况。

如下图,当我们要将一个33的图放大至66,即图像扩大2倍时,得到的目标矩阵是怎么样的呢?我们看图,我们将原图的每个像素看成四个四个像素,这四个像素分别对应着目标像素里的在一起的四个像素,这样我们很容易想到,直接将原矩阵的1、2、3、4的灰度值赋值给目标矩阵的1、2、3、4就行了吗?不太合适!这样会导致马赛克效果。于是我们利用双线性插值,来计算目标像素的灰度值,具体详细过程我们看代码!

Code

# 导入图片img = cv2.imread('src/pic/1.jpg')plt.imshow(img)# 输出图片尺寸print(img.shape)# 设置图片的参数sh = 260sw = 460rate = 2th = sh * ratetw = sw * rate# 生成输出矩阵outpic = np.zeros((th, tw, 3), np.uint8)# 循环计算for k in range(3):print("Please wait",(2-k)*5,"seconds!")for i in range(th-2):for j in range(tw-2):# 输出图上的点对应原图的坐标cur_x = (float)((i + 0.5) / rate)cur_y = (float)((j + 0.5) / rate)# 设置周围四个点的属性p1 = (math.floor(cur_x), math.floor(cur_y))p2 = (p1[0] + 1, p1[1])p3 = (p1[0], p1[1] + 1)p4 = (p1[0] + 1, p1[1] + 1)# 计算第一个方向的线性插值fr1 = (p3[1] - cur_y) * img[p1[0], p1[1], k] + (cur_y - p1[1]) * img[p3[0], p3[1], k]fr2 = (p4[1] - cur_y) * img[p2[0], p2[1], k] + (cur_y - p2[1]) * img[p4[0], p4[1], k]# 计算第二个方向的线性插值outpic[i, j, k] = (p2[0] - cur_x) * fr2 + (cur_x - p1[0]) * fr1plt.imshow(outpic)cv2.imwrite("outpic.jpg", outpic)print(outpic.shape)

首先单线性插值,耐心看下就能明白,重点在于一个权重的思想。

双线性插值无非是对一个点进行两个方向上的线性插值,先对横向上P1、P3两个点进行插值得到R1的值,对应代码中的fr1,再对P2、P4两个点进行插值得到R2,对应代码中的fr2,最后利用R1、R2求出X点的灰度值。具体计算公式参见代码。

最后我们对三个通道的矩阵统一处理,得到目标图片。

其实我更想点出几处细节:

1、一定要注意数组的下标越界问题

2、一开始一定要弄明白原始矩阵与目标矩阵的对应关系!代码中减去0.5是因为我选取的是图片的中心。

3、点的坐标一定要搞明白,不然减着减着就晕了hhhhh

加油!

如果觉得《双线性插值算法 -- 个人学习思路及方法分享》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。