顾名思义,最近邻,跟哪个邻居最近,那插入的这个像素值,就和这个最近的邻居像素一样。是的,一模一样,copy 像素。
优点:计算量少,效率高、速度快缺点:直接插值,像素无过度,易形成锯齿状
代码实现:
import cv2
import numpy as np
import time
def nearest_interpolation(img, out_dim):
"""
最近邻插值
:param img:原图
:return:插值后的图
"""
src_h, src_w, src_channel = img.shape
dst_h, dst_w = out_dim[1], out_dim[0]
print("src_h, src_w = ", src_h, src_w)
print("dst_h, dst_w = ", dst_h, dst_w)
if src_h == dst_h and src_w == dst_w:
return img.copy()
emptyImage = np.zeros((dst_h, dst_w, src_channel), np.uint8)
# 求新尺寸与旧尺寸间的比值(x-w, y-h)
scale_x = dst_w / src_w
scale_y = dst_h / src_h
for j in range(dst_h):
for i in range(dst_w):
# 找到新点坐标对应的最近位置
x = int(i/scale_x)
y = int(j/scale_y)
# 将距离新坐标最近原像素点的像素值,赋值给新点,作为新点像素值
emptyImage[i, j] = img[x, y]
return emptyImage
if __name__ == '__main__':
org_img = cv2.imread("lenna.png")
start_time = time.time()
dst = nearest_interpolation(org_img, out_dim=(800, 800))
end_time = time.time()
print('总耗时为:{} s'.format(end_time - start_time))
cv2.imshow("org_image", org_img)
cv2.imshow("nearest interp", dst)
cv2.waitKey()
2.单线性插值(简单,只在一个方向上进行插值)
单线性插值,顾名思义,有两个关键的词
单线性
根据下面的图,已知(x0,y0)和(x1, y1)点的像素坐标,求(x, y)的像素坐标,在一条直线上,就是一个线性的关系。相似三角形,直接求(x, y)点对应的坐标。
(不再是简单粗暴的copy了,而是稍微动了下脑子,做了一次线性插值,类似于0和2像素值的中点,插入一个像素值,那就是1)
评价:失真相比于最近邻插值,失真会小一点。
每个方向做单线性插值,再做插值,记为双线性插值。
计算方式:
代码实现:
import numpy as np
import cv2
import time
def bilinear_interpolation(img, out_dim):
"""
双线性插值
:param img:原图
:return:插值后的图
"""
src_h, src_w, channel = img.shape
dst_h, dst_w = out_dim[1], out_dim[0]
print("src_h, src_w = ", src_h, src_w)
print("dst_h, dst_w = ", dst_h, dst_w)
if src_h == dst_h and src_w == dst_w:
return img.copy()
dst_img = np.zeros((dst_h, dst_w, channel), dtype=np.uint8)
scale_x, scale_y = float(src_w) / dst_w, float(src_h) / dst_h
for i in range(channel):
for dst_y in range(dst_h):
for dst_x in range(dst_w):
# find the origin x and y coordinates of dst image x and y
# use geometric center symmetry (几何中心对称)
# if use direct way, src_x = dst_x * scale_x
src_x = (dst_x + 0.5) * scale_x - 0.5
src_y = (dst_y + 0.5) * scale_y - 0.5
# 找出将被用来计算插值的点的坐标
src_x0 = int(np.floor(src_x))
src_x1 = min(src_x0 + 1, src_w - 1)
src_y0 = int(np.floor(src_y))
src_y1 = min(src_y0 + 1, src_h - 1)
# calculate the interpolation, x2-x1=1; y2-y1=1.忽略分母
temp0 = (src_x1 - src_x) * img[src_y0, src_x0, i] + (src_x - src_x0) * img[src_y0, src_x1, i]
temp1 = (src_x1 - src_x) * img[src_y1, src_x0, i] + (src_x - src_x0) * img[src_y1, src_x1, i]
dst_img[dst_y, dst_x, i] = int((src_y1 - src_y) * temp0 + (src_y - src_y0) * temp1)
return dst_img
if __name__ == '__main__':
img = cv2.imread('lenna.png')
start_time = time.time()
dst = bilinear_interpolation(img, (800, 800))
end_time = time.time()
print('总耗时为:{} s'.format(end_time - start_time))
cv2.imshow('bilinear interp', dst)
cv2.waitKey()
注意事项:
插值不仅仅用于上采样,也可以用于下采样(采样完后,丢失原来像素点),以上采样为主先做中心对齐(原图像与采样后图像的中心对齐),再做双线性插值,避免出现图像失真。(未做中心对齐,是以左上角为起始点的,导致部分像素不参与插值训练)中心对齐操作非必须,不是插值前的必须步骤最近邻插值,没必要做中心对齐



