欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

OpenCV 从零学习 · 第 4 讲:几何变换 resize / flip / 旋转(把图"摆正、缩放、镜像")

OpenCV 从零学习 · 第 4 讲:几何变换 resize / flip / 旋转

现实里的图片总不"完美":头像太大要压缩、扫描件拍歪了要摆正、自拍想镜像、训练数据要翻转增广……这一讲把三种最常用的几何变换讲透,重点说清每个参数怎么选、不同插值/翻转方式差在哪

1. cv2.resize —— 缩放(最常用)

函数签名

dst = cv2.resize(src, dsize, fx=0, fy=0, interpolation=cv2.INTER_LINEAR)
# dsize : 目标尺寸 (宽, 高)  —— 注意是(宽,高), 和 img.shape 的(高,宽)顺序相反!
# fx,fy: 缩放比例(二选一: 给 dsize 就不给 fx/fy, 反之亦然)
# interpolation: 插值方式
新手必踩坑 ①:dsize 是 (宽, 高),不是 (高, 宽)!
img.shape 返回 (高, 宽),但 resizedsize 要填 (宽, 高)。写反了图会被拉变形。
插值方式怎么选(核心差异):缩小用 INTER_AREA(防锯齿/摩尔纹),放大用 INTER_CUBICINTER_LANCZOS4(更清晰,慢一点);想要"像素块"不模糊用 INTER_NEAREST
插值常量特点适用
INTER_NEAREST最近邻,不平滑图标/分类标签,保持硬边不糊
INTER_LINEAR双线性(默认)一般放大,速度均衡
INTER_AREA区域重采样缩小首选,避免波纹
INTER_CUBIC双三次,慢而清放大首选
INTER_LANCZOS48x8 兰索斯,最清放大且对清晰度要求高
场景案例 A:上传头像前压缩到 512×512
缩小用 INTER_AREA 最稳:
resized = cv2.resize(img, (512, 512), interpolation=cv2.INTER_AREA)
场景案例 B:把小图标按比例放大展示
放大追求清晰,用 INTER_CUBIC;这里用比例 fx/fy 更直观:
big = cv2.resize(img, None, fx=3, fy=3, interpolation=cv2.INTER_CUBIC)

2. cv2.flip —— 翻转 / 镜像

函数签名

dst = cv2.flip(src, flipCode)
# flipCode: 0 = 上下翻转(绕水平轴)
#           1 = 左右翻转(镜像)
#          -1 = 同时上下+左右翻转
flipCode效果典型场景
0上下颠倒转正扫描件/手机拍的 PDF 倒过来了,翻回来
1左右镜像自拍镜像、文字镜像校正
-1180° 旋转快速把图倒个头
场景案例 C:自拍做成镜像效果
人习惯照镜子,左右镜像更顺眼:
mirror = cv2.flip(img, 1)
场景案例 D:训练数据增强
把数据集图片左右翻转,样本量直接翻倍、模型更抗左右差异:
aug = cv2.flip(img, 1)

3. 旋转(任意角度)—— warpAffine + getRotationMatrix2D

函数签名

M = cv2.getRotationMatrix2D(center, angle, scale)
# center: 旋转中心 (宽/2, 高/2) 这样的 (x, y)
# angle : 角度, 正数=逆时针, 负数=顺时针
# scale : 缩放, 1.0 表示不缩放
dst = cv2.warpAffine(img, M, (宽, 高))   # 注意输出尺寸也是 (宽, 高)!
新手必踩坑 ②:旋转默认会"裁掉四角"
warpAffine 的输出尺寸若还用原图大小,转完图的四角会被切掉。要么把输出尺寸放大,要么用 borderValue 填边。另外 angle 正数在 OpenCV 里是逆时针,和直觉的"顺时针为正"相反。
场景案例 E:把拍歪 5° 的扫描文档摆正
以图中心为轴逆时针转 5°,并放大输出尺寸避免裁角,黑边填充:
h, w = img.shape[:2]
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, 5, 1.0)
# 输出尺寸放大一点, 旋转后不裁角; 空白填黑色(也可填 255 白边)
fixed = cv2.warpAffine(img, M, (w + 60, h + 60), borderValue=(0, 0, 0))
场景案例 F:数据增强——随机旋转 ±15°
训练模型时随机小角度旋转,提升鲁棒性:
import random
ang = random.uniform(-15, 15)
M = cv2.getRotationMatrix2D((w/2, h/2), ang, 1.0)
rot = cv2.warpAffine(img, M, (w, h))

4. 平移(把图挪个位置)—— 手写仿射矩阵

平移是更简单的仿射变换:构造一个 2×3 矩阵,指定 x/y 方向移动多少像素。

import numpy as np
M = np.float32([[1, 0, tx],     # tx: 向右移多少像素(负则向左)
                [0, 1, ty]])    # ty: 向下移多少像素(负则向上)
moved = cv2.warpAffine(img, M, (w, h))
场景案例 G:把水印从中间挪到右下角
先算出水印该去的偏移量,平移一张透明水印图再叠加即可:
tx, ty = w - 200, h - 80     # 挪到右下角附近
M = np.float32([[1, 0, tx], [0, 1, ty]])
wm_moved = cv2.warpAffine(watermark, M, (w, h))

5. 本讲要点清单

  • resizedsize(宽, 高),和 img.shape 的 (高,宽) 相反。
  • 缩小用 INTER_AREA,放大用 INTER_CUBIC/LANCZOS4,硬边不糊用 INTER_NEAREST
  • flip:0 上下、1 左右镜像、-1 都翻;自拍/数据增广常用 1。
  • 旋转用 getRotationMatrix2D + warpAffine;角度正=逆时针;注意放大输出尺寸防裁角。
  • 平移手写 2×3 矩阵 [[1,0,tx],[0,1,ty]] 再 warpAffine。
✅ 下一讲预告:图片有噪点、想变平滑怎么办?第 5 讲:图像滤波与平滑(均值/高斯/中值/双边)

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功