问题:请分别用最近邻法和双线性插值法将附件中80*60的小图放大至800*600,并分别截取边缘区域与原图相比较。
最近邻法是一种最简单的图像缩放方法,它对于每个新像素,都寻找最接近的原始像素,并直接将其值赋给新像素。
对于每个输出像素,都计算与该像素最接近的输入像素位置,并将该像素的值作为输出像素的值。这种方法实现起来简单,计算速度非常快,但缩放后图像的质量可能会受到影响,尤其是在进行放大时会产生锯齿状效果,所以不适用于对图像质量要求较高的应用。
双线性插值法是一种更高级的缩放方法。这种方法首先对输入图像中每个像素周围的四个像素进行加权平均,以确定新像素的值。
对于每个输出像素,其值由位于其四个相邻像素的值插值计算而来。插值公式使用每个相邻像素的距离和这些像素的灰度值进行计算,在距离越远的像素处分配更小的权重,最终得到一个加权平均值,将其作为该像素的值。
这种方法比最近邻法更准确,并能在处理后的图像中产生更平滑的过渡效果,但计算成本较高。
在图像处理中,最近邻法和双线性插值法通常用于缩放、旋转和图像变换等操作。具体使用哪种方法可以根据应用需求和处理速度要求来选择。
import numpy as np
import cv2
def nearest(img, h, w):
height, width, channels = img.shape
emptyImage = np.zeros((h, w, channels), np.uint8)
sh = h / height
sw = w / width
for i in range(h):
for j in range(w):
x = int(i / sh)
y = int(j / sw)
emptyImage[i, j] = img[x, y]
return emptyImage
def bilinear(img, out_dim):
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, 3), dtype=np.uint8)
scale_x, scale_y = float(src_w) / dst_w, float(src_h) / dst_h
for i in range(3):
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
# find the coordinates of the points which will be used to compute the interpolation
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
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('Snoopy-small.jpg')
img1 = bilinear(img, (800, 600))
img2 = nearest(img, 600, 800)
cv2.imshow('bilinear interp', img1)
cv2.imshow('nearest', img2)
cv2.imwrite('bilinear.png', img1)
cv2.imwrite('nearest.png', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果图:
最近邻:
双线性插值法:
通过两张不同方法处理后的图片与原图比较可以显著看出,两者虽然都成功放大了图像,但是最近邻法会产生锯齿状效果,图像质量较低,优点是计算成本低;双线性插值法则能在处理后的图像中产生更平滑的过渡效果,但计算成本较高,耗时较长。