插值在图像中的应用一般为处理图像的缩放。所谓缩放就是缩小和放大。在所有插值缩放算法中要数最邻近插值最简单最暴力,当然效果也是最不好的。经过该算法进行放大的图片会出现马赛克现象,而进行缩小的图片也会丢失较大的图像信息。下面介绍两种插值法,最邻近插值和双线性插值。
1. 最邻近插值法
最近临插值算法的原理是在原图像中找到最近临的一个点,然后把这个点的像素值插入到目标图像中,最近临插值算法优点是算法简单,易于实现。
算法公式如下:
ori_x = dst_x * (ori_width / dst_width)
ori_y = dst_y * (ori_height / dst_height)
ori_x、ori_y为原图像的横纵点,dst_x、dst_y为缩放后横纵点,ori_witdh/dst_height为缩放比率。对一个图像放大,实际上是先计算原图像中的虚拟位置,比如4x4的图像要缩放到8x8,即在4x4原图像中横坐标4个点生成8个点,虚拟位置可以通过插值求出,出现小数时我们可以用四舍五入或者向下或向上取整的方法来获得对应的原图坐标。正因为这个机制的引入,才导致最后的生成图效果不佳。
2. 双线性插值法
双线性插值公式为:
f(i+u,j+v) = (1-u)(1-v)f(i,j)+u(1-v)f(i+1,j)+(1-u)vf(i,j+1)+ uvf(i+1,j+1)
原理同上,不过双线性插值算法是用四个点进行估计插值,图像较最邻近插值更显细腻,但计算量较大。
python实现:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def resize_nerghbor(src_data, dst_height, dst_width):
ori_height, ori_width, channel = src_data.shape
ratio_height = ori_height / dst_height
ratio_width = ori_width / dst_width
dst_data = np.zeros((dst_height, dst_width, channel), np.uint8)
for i in range(channel):
for y in range(dst_height):
for x in range(dst_width):
x_ori = int(x * ratio_width)
y_ori = int(y * ratio_height) #取整
dst_data[y, x, i] = src_data[y_ori, x_ori, i]
return dst_data
def resize_bilinear(src_data, dst_height, dst_width):
ori_height, ori_width, channel = src_data.shape
ratio_height = ori_height / dst_height
ratio_width = ori_width / dst_width
dst_data = np.zeros((dst_height, dst_width, channel), np.uint8)
for i in range(channel):
for y in range(dst_height):
for x in range(dst_width):
x_ori = x * ratio_width
y_ori = y * ratio_height
u = x_ori - math.floor(x_ori)
v = y_ori - math.floor(y_ori) # 取小数部分
dst_data[y, x, i] = src_data[math.floor(y_ori), math.floor(x_ori),i]*(1 - u) * (1 - v) + \
src_data[math.floor(y_ori), math.ceil(x_ori),i] * (1 - u) * v + \
src_data[math.ceil(y_ori), math.floor(x_ori),i] * u * (1-v) + \
src_data[math.ceil(y_ori), math.ceil(x_ori),i] * u * v #取整、按公式进行运算
return dst_data
m = cv2.imread('xian.jpg')
n = resize_bilinear(m,540,960)
n = cv2.cvtColor(n, cv2.COLOR_BGR2RGB)
plt.imshow(n)
plt.show()
# cv2.imshow('resize_image', n)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
原图缩小后:
参考: 1.Matlab——图像缩放(插值法)
2.使用双线性插值法放大图像(matlab实现)
3.最临近插值和双线性插值