Preface

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

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

原图是这样子:

空间双线性插值 python 用双线性插值计算gk l_线性插值


空间双线性插值 python 用双线性插值计算gk l_计算机视觉_02

空间双线性插值 python 用双线性插值计算gk l_计算机视觉_03


空间双线性插值 python 用双线性插值计算gk l_线性插值_04


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

空间双线性插值 python 用双线性插值计算gk l_opencv_05

Introduction

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

下面介绍具体算法步骤:

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

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

空间双线性插值 python 用双线性插值计算gk l_算法_06

Code

# 导入图片
img = cv2.imread('src/pic/1.jpg')
plt.imshow(img)
# 输出图片尺寸
print(img.shape)

# 设置图片的参数
sh = 260
sw = 460
rate = 2
th = sh * rate
tw = 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]) * fr1

plt.imshow(outpic)     
cv2.imwrite("outpic.jpg", outpic)
print(outpic.shape)

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

空间双线性插值 python 用双线性插值计算gk l_算法_07


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

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

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

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

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

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

加油!

空间双线性插值 python 用双线性插值计算gk l_opencv_08