趋近智
在单独修改像素值(例如调整亮度)之外,我们通常需要改变像素自身的空间排列。这属于几何变换的类别,它改变的是图像的几何形状,而不仅仅是其亮度分布。最常用的几何变换之一是缩放,它简单来说就是调整图像的大小。
您可能出于多种原因需要缩放图像:
缩放会改变图像的尺寸:宽度和高度。我们可以均匀地缩放图像,这意味着我们以相同的比例改变宽度和高度,保留原始比例(长宽比)。或者,我们可以非均匀地缩放,以不同的比例改变宽度和高度,这将拉伸或压缩图像。
缩放涉及创建一个具有所需尺寸的新图像网格,然后根据原始图像计算出新网格的像素值。
假设您想将一个2x2像素的图像尺寸扩大一倍,变为一个4x4像素的图像。原始像素可以直接映射到新网格中的某些位置,但介于它们之间的像素呢?
原始图像 (2x2):
P1 P2
P3 P4
新图像 (4x4):
P1 ? P2 ?
? ? ? ?
P3 ? P4 ?
? ? ? ?
问号表示我们需要确定像素值的位置。这种根据已知值估计新位置像素值的过程称为插值。插值方法会明显影响缩放图像的质量,特别是在放大时。
有几种执行插值的方式。对于初学者来说,了解这两种是很好的开始:
**最近邻插值:**这是最简单的方法。对于新图像网格中的每个位置,它会(根据位置)找到原始图像网格中最近的单个像素,并复制其值。
**双线性插值:**这种方法对于新网格中的每个点,会考虑原始图像中最近的4个邻居(一个2x2区域)。它将新像素的值计算为这四个邻居的加权平均值,其中权重取决于到每个邻居的距离。
还有更高级的方法,例如双三次插值(它考虑4x4邻域)和Lanczos插值,它们可能提供更好的质量(通常比双线性插值结果更清晰),但计算时间也会增加。对于大多数入门目的而言,当需要平滑度时,双线性插值通常是首选。
大多数计算机视觉库都提供了方便处理缩放和插值的函数。例如,在Python中使用OpenCV这样的库时,您可能会使用resize函数。您通常需要提供:
(width, height)元组)或缩放因子(fx表示宽度因子,fy表示高度因子)。INTER_NEAREST表示最近邻,INTER_LINEAR表示双线性,INTER_CUBIC表示双三次)。让我们来看一个使用OpenCV的Python示例:
import cv2
import numpy as np
# 加载图像(将'path/to/your/image.png'替换为实际路径)
# try:
# image = cv2.imread('path/to/your/image.png')
# if image is None:
# raise FileNotFoundError("Image not found or unable to load.")
# except FileNotFoundError as e:
# print(e)
# # 如果加载失败,创建一张简单的模拟图像,用于演示
# print("正在使用模拟图像。")
# image = np.zeros((100, 150, 3), dtype=np.uint8) # 高度=100,宽度=150
# cv2.putText(image, 'Original', (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 为了演示,我们直接创建一个示例图像
image = np.zeros((100, 150, 3), dtype=np.uint8) # 高度=100,宽度=150
cv2.rectangle(image, (20, 20), (70, 70), (255, 0, 0), -1) # 蓝色方块
cv2.circle(image, (110, 50), 25, (0, 255, 0), -1) # 绿色圆形
# 获取原始尺寸
height, width = image.shape[:2]
print(f"原始尺寸:宽度={width},高度={height}")
# --- 缩小(到一半尺寸)---
# 指定精确的新尺寸
new_width_down = width // 2
new_height_down = height // 2
# 缩小使用双线性插值(通常效果不错)
downscaled_image = cv2.resize(image, (new_width_down, new_height_down),
interpolation=cv2.INTER_LINEAR)
print(f"缩小后的尺寸:宽度={downscaled_image.shape[1]},高度={downscaled_image.shape[0]}")
# --- 放大(到两倍尺寸)---
# 指定缩放因子
fx_up = 2.0 # 宽度放大2倍
fy_up = 2.0 # 高度放大2倍
# 使用最近邻插值放大
upscaled_nearest = cv2.resize(image, None, fx=fx_up, fy=fy_up,
interpolation=cv2.INTER_NEAREST)
print(f"放大后(最近邻)尺寸:宽度={upscaled_nearest.shape[1]},高度={upscaled_nearest.shape[0]}")
# 使用双线性插值放大
upscaled_linear = cv2.resize(image, None, fx=fx_up, fy=fy_up,
interpolation=cv2.INTER_LINEAR)
print(f"放大后(线性)尺寸:宽度={upscaled_linear.shape[1]},高度={upscaled_linear.shape[0]}")
# 显示结果(通常会使用cv2.imshow或matplotlib)
# cv2.imshow('原始图像', image)
# cv2.imshow('缩小后(线性)', downscaled_image)
# cv2.imshow('放大后(最近邻)', upscaled_nearest)
# cv2.imshow('放大后(线性)', upscaled_linear)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 或者保存结果:
# cv2.imwrite('缩小后.png', downscaled_image)
# cv2.imwrite('放大后_最近邻.png', upscaled_nearest)
# cv2.imwrite('放大后_线性.png', upscaled_linear)
示例输出显示了原始图像、最近邻放大(块状)和双线性放大(更平滑)。请注意,最近邻插值会复制像素,而双线性插值会平均像素以创建中间值。
图像的长宽比是其宽度与高度的比值(width/height)。缩放时,您通常希望保留原始长宽比,以避免图像内容失真。
如果您知道所需的新宽度(new_width)并想计算相应的、能保持长宽比的高度(new_height):
新高度=取整(原始宽度原始高度×新宽度)
或者,如果您知道所需的新高度:
新宽度=取整(原始高度原始宽度×新高度)
大多数库函数允许仅指定一个维度或使用缩放因子(fx、fy)。如果您为fx和fy提供相同的缩放因子,长宽比将保持不变。如果您提供特定的输出尺寸(width, height),则需要负责在必要时确保它们保持所需的纵横比。
缩放是调整图像尺寸的一项基本操作。了解其工作原理,特别是最近邻和双线性等插值方法的作用,使您能够为任务选择合适的方案,平衡速度和视觉质量。请记住,缩小会丢失信息,而放大则会估计新的像素值,可能引入块状或模糊等失真。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造