起因
我看到了一个别人的作业,他们老师让不使用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
这是效果图:
...缩放图像看不出来效果
如果写的有哪里不好欢迎在评论区指出