在不使用cv2等库的情况下利用numpy实现双线性插值缩放图像

时间:2023-01-18 15:12:09

我看到了一个别人的作业,他们老师让不使用cv2等图像处理库缩放图像

算法介绍

如果你仔细看过一些库里缩放图像的方法参数会发现有很多可选项,其中一般默认是使用双线性插值。具体步骤:

  • 计算目标图坐标对应原图中哪些坐标来填充
  • 根据双线性插值的公式写出代码

其中缩放函数使用numpy来加快速度,使用for循环缩放图像到1024*1024我的cpu运行了36s,使用numpy运行了0.38秒快了近100倍

代码

重点在于写一个函数 def resize(src, width,height):,参数是目标图像的宽高

import cv2
import numpy as np
import time

def resize(src, width,height):
    dst_w =  width
    dst_h = height
    src_h, src_w = src.shape[:2] # 源图像宽高
    if src_h == dst_h and src_w == dst_w:
        return src.copy()
    scale_x = float(src_w) / dst_w # x缩放比例
    scale_y = float(src_h) / dst_h # y缩放比例
    dst = np.zeros((dst_h, dst_w, 3), dtype=np.uint8)

下面可能比较难理解,np_src_x代表目标图像的x坐标,src_x也是代表目标图像的x坐标只是它有3个维度,是为了之后的索引做准备。从src_x_dst开始是计算目标图坐标需要哪些原始图坐标来填充。

    np_src_x = np.arange(0, dst.shape[1])
    np_src_y = np.arange(0, dst.shape[0]).reshape((dst.shape[0], 1))
    src_x = (np_src_x + np.zeros(dst.shape[:2]))[:, :, np.newaxis] + np.zeros(dst.shape)
    src_y = (np_src_y + np.zeros(dst.shape[:2]))[:, :, np.newaxis] + np.zeros(dst.shape)
    # 计算目标图坐标对应的原始图坐标
    src_x_dst = src_x * scale_x
    src_y_dst = src_y * scale_y
    srcX0 = np.floor(src_x_dst).astype(int)
    srcY0 = np.floor(src_y_dst).astype(int)
    srcX1 = np.minimum(srcX0 + 1, src_w - 1)
    srcY1 = np.minimum(srcY0 + 1, src_h - 1)

three_axis也是为之后的索引做准备,对了,这个函数只能处理有RGB或BGR这种有3个通道的图形,其实改进应该也不难有想法的同学可以试一下。后面的value0就是具体的公式计算了

    three_axis = np.zeros(dst.shape, dtype=int)
    three_axis[:, :, 1] = 1
    three_axis[:, :, 2] = 2
    # 根据公式计算值
    value0 = (srcX1 - src_x_dst) * src[srcY0, srcX0, three_axis] + (src_x_dst - srcX0) * src[srcY0, srcX1, three_axis]
    value1 = (srcX1 - src_x_dst) * src[srcY1, srcX0, three_axis] + (src_x_dst - srcX0) * src[srcY1, srcX1, three_axis]
    dst = ((srcY1 - src_y_dst) * value0 + (src_y_dst - srcY0) * value1).astype(np.uint8)
    return dst

完整的代码在这里ScaleImage.py

这是效果图:
在不使用cv2等库的情况下利用numpy实现双线性插值缩放图像
...缩放图像看不出来效果