contribute上次修改:2026-09-29

2.2 缩放、裁剪与拼接

总目录:1.1 OpenCV介绍与学习路线 | 第二章:基础图像处理 | 编号:2.2

← 上一节:2.1 颜色空间与通道 | 下一节:2.3 绘制图形与文字 →


2.2 缩放、裁剪与拼接

这三件事看起来都是“摆弄图片大小”,底层却不一样:缩放会重新计算像素,裁剪只是取出一块区域,拼接则把多个数组接起来。

一、resize:真正修改图像尺寸

resized = cv2.resize(image, (640, 480))

第二个参数是 (宽, 高),又和 shape 的 (高, 宽) 反过来了😢

按比例缩放更不容易写错:

resized = cv2.resize(
    image,
    dsize=None,
    fx=0.5,
    fy=0.5,
    interpolation=cv2.INTER_AREA,
)

保持长宽比,把宽度改为 800:

h, w = image.shape[:2]
new_w = 800
new_h = round(h * new_w / w)
resized = cv2.resize(image, (new_w, new_h))

二、插值方法怎样选

缩放后出现的新像素从哪里来?这就是插值。

插值 常见用途 特点
INTER_NEAREST 二值标签、像素风图 最快,不创造中间值,锯齿明显
INTER_LINEAR 日常缩放 默认,速度和效果平衡
INTER_AREA 缩小图像 常用且抗混叠较好
INTER_CUBIC 放大图像 较平滑,但更慢

二值蒙版若使用线性插值,边缘可能出现 0 和 255 之外的灰度值。此时优先 INTER_NEAREST,或缩放后重新阈值化。

三、裁剪其实是 NumPy 切片

cropped = image[y1:y2, x1:x2]

例如:

cropped = image[0:200, 200:500]

表示取 y 从 0 到 199、x 从 200 到 499 的区域;切片右端不包含在结果里。

2.2-image-002

坐标来自检测结果时要先限制范围:

h, w = image.shape[:2]
x1 = max(0, x1)
y1 = max(0, y1)
x2 = min(w, x2)
y2 = min(h, y2)
roi = image[y1:y2, x1:x2].copy()

四、横向与纵向拼接

NumPy 写法:

horizontal = np.hstack((image_a, image_b))
vertical = np.vstack((image_a, image_b))

OpenCV 也提供:

horizontal = cv2.hconcat([image_a, image_b])
vertical = cv2.vconcat([image_a, image_b])

拼接很适合一次显示原图、灰度、蒙版和结果图。不过灰度图是 (H, W),彩色图是 (H, W, 3),不能直接混着拼。

gray_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
preview = cv2.hconcat([image, gray_bgr])

五、拼接为什么经常报尺寸错误

横向拼接要求高度一致;纵向拼接要求宽度一致;通道数和数据类型也应一致。

hconcat → 高度、通道、dtype 一致
vconcat → 宽度、通道、dtype 一致

一个简单的统一尺寸函数:

def to_preview(image, size=(480, 320)):
    if image.ndim == 2:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
    return cv2.resize(image, size, interpolation=cv2.INTER_AREA)

preview = cv2.hconcat([
    to_preview(original),
    to_preview(mask),
    to_preview(result),
])

← 上一节:2.1 颜色空间与通道 | 下一节:2.3 绘制图形与文字 →

留言区

不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。