Python----OpenCV(几何变换--图像平移、图像旋转、放射变换、图像缩放、透视变换)

一、图像平移

"平移操作是通过一个平移矩阵来实现的。这个矩阵是一个2x3的矩阵,表示图像坐标的变 换。

其中,Tx 和 Ty 分别表示图像在 x 轴和 y 轴方向上平移的距离。

举个例子:

如果我们想将图像平移 100 个像素到右,50 个像素到下,Tx 就是 100,Ty 就是 50。

python 复制代码
warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
参数名 类型 说明
src 输入图像 需要进行仿射变换的原始图像,通常为NumPy数组(如灰度或BGR格式)。
M 2x3变换矩阵 用于指定旋转、平移、缩放等仿射变换的矩阵(浮点型)。
dsize 元组 (宽, 高) 输出图像的尺寸,格式为 (width, height)
dst 输出图像 可选参数,存储变换后的图像,类型和大小与 src 相同。
flags 插值方法 可选参数,默认 cv2.INTER_LINEAR,其他选项如 INTER_NEARESTINTER_CUBIC
borderMode 边界模式 可选参数,处理边界像素的方式(如 cv2.BORDER_CONSTANTBORDER_REPLICATE)。
borderValue 标量值 可选参数,当 borderMode=cv2.BORDER_CONSTANT 时使用的填充值(默认为0)。
python 复制代码
# 导入OpenCV和NumPy库
import cv2
import numpy as np

# 读取图像文件,路径为'./images/nezha.png'
img = cv2.imread('./images/nezha.png')

# 获取图像的高度(h)和宽度(w),img.shape返回的是(高度, 宽度, 通道数)
h, w = img.shape[:2]

# 定义2x3的仿射变换矩阵M,这里是一个平移变换:
# [[1, 0, tx], [0, 1, ty]],其中tx=100(水平向右平移100像素),ty=50(垂直向下平移50像素)
M = np.float32([[1, 0, 100], [0, 1, 50]])

# 应用仿射变换,参数说明:
# img: 输入图像
# M: 变换矩阵
# (w, h): 输出图像的尺寸(保持和原图相同大小)
res = cv2.warpAffine(img, M, (w, h))

# 显示原始图像,窗口名称为'img'
cv2.imshow('img', img)

# 显示变换后的图像,窗口名称为'res'
cv2.imshow('res', res)

# 等待用户按键,0表示无限等待
cv2.waitKey(0)

# 关闭所有OpenCV创建的窗口
cv2.destroyAllWindows()

二、图像旋转

2.1、出现裁剪的旋

图像的旋转变换时图像的位置变换,旋转后图像的大小一般会改变。

python 复制代码
getRotationMatrix2D(center, angle, scale) →  retval

| 参数名 | 说明 |
| center | 表示旋转的中心点 |
| angle | 表示旋转的角度(正数逆时针) |

scale 表示图像缩放因子

旋转矩阵


重点:

scale 是缩放比例(比如 1.0 表示不缩放)

t_x 和 t_y 是平移的偏移量,OpenCV 会根据你设定的旋转中心,自动帮你算好。

python 复制代码
# 导入OpenCV和NumPy库
import cv2
import numpy as np

# 读取图像文件,路径为'./images/nezha.png'
img = cv2.imread('./images/nezha.png')

# 获取图像的高度(h)和宽度(w),img.shape返回的是(高度, 宽度, 通道数)
h, w = img.shape[:2]

# 创建旋转矩阵M:
# 参数说明:
# (w//2, h//2) - 旋转中心点(图像中心)
# 45 - 旋转角度(逆时针45度)
# 1 - 缩放比例(1表示保持原大小)
M = cv2.getRotationMatrix2D((w//2, h//2), 45, 1)

# 应用仿射变换进行图像旋转:
# img: 输入图像
# M: 旋转矩阵
# (w, h): 输出图像的尺寸(保持和原图相同大小)
res = cv2.warpAffine(img, M, (w, h))

# 显示原始图像,窗口名称为'img'
cv2.imshow('img', img)

# 显示旋转后的图像,窗口名称为'res'
cv2.imshow('res', res)

# 等待用户按键,0表示无限等待
cv2.waitKey(0)

# 关闭所有OpenCV创建的窗口
cv2.destroyAllWindows()

2.2、不出现裁剪的旋转

python 复制代码
# 导入OpenCV和NumPy库
import cv2
import numpy as np

# 读取图像文件
img = cv2.imread('./images/nezha.png')

# 获取原始图像的高度和宽度
h, w = img.shape[:2]

# 创建旋转矩阵:
# 参数说明:
# (w//2, h//2) - 以图像中心为旋转中心
# 45 - 旋转角度(逆时针45度)
# 1 - 缩放比例(1表示保持原大小)
M = cv2.getRotationMatrix2D((w//2, h//2), 45, 1)

# 计算旋转矩阵中的cos和sin绝对值
cos = np.abs(M[0, 0])  # 旋转矩阵中的cosθ分量
sin = np.abs(M[0, 1])  # 旋转矩阵中的sinθ分量

# 计算旋转后图像的新尺寸(避免裁剪)
# 新宽度 = 原高度*sinθ + 原宽度*cosθ
nW = int((h * sin) + (w * cos))  
# 新高度 = 原高度*cosθ + 原宽度*sinθ
nH = int((h * cos) + (w * sin))  

# 调整旋转矩阵的平移分量,使旋转后的图像居中显示
# 水平方向偏移:新宽度/2 - 原宽度/2
M[0, 2] += (nW / 2) - (w / 2)
# 垂直方向偏移:新高度/2 - 原高度/2
M[1, 2] += (nH / 2) - (h / 2)

# 应用仿射变换,使用调整后的参数:
# img - 输入图像
# M - 调整后的旋转矩阵
# (nW, nH) - 新的图像尺寸(确保完整显示旋转后的图像)
res = cv2.warpAffine(img, M, (nW, nH))

# 显示原始图像
cv2.imshow('img', img)
# 显示旋转后的图像
cv2.imshow('res', res)
# 等待按键
cv2.waitKey(0)
# 关闭所有窗口
cv2.destroyAllWindows()

三、放射变换

放射变换是一种二维坐标空间中的线性变换+平移,它可以实现图像的:平移(Translation) 缩放(Scaling) 旋转(Rotation) 翻转(Reflection) 错切(Shear)

应用场景

图像校准

图像配准(如航拍图拼接)

仿射数据增强(如训练图像预处理)

python 复制代码
warpAffine(src,M,dsize[,dest[,flags[,boederModel[,borderValue]]]])→dest
参数名 类型 说明 默认值
src numpy.ndarray 输入图像矩阵(BGR或灰度图) 无(必须参数)
dst numpy.ndarray 输出图像矩阵,尺寸由dsize指定,类型与src一致 None(自动创建)
M np.float32 (2×3) 仿射变换矩阵 格式:[[a11, a12, b1], [a21, a22, b2]] 无(必须参数)
dsize tuple (width,height) 输出图像尺寸(注意:宽度在前!) 无(必须参数)
flags int 插值方法: INTER_NEAREST(最近邻) INTER_LINEAR(双线性,默认) INTER_CUBIC(三次样条) INTER_LINEAR
borderMode int 边缘填充方式: BORDER_CONSTANT(常量填充,默认) BORDER_REPLICATE(复制边缘) BORDER_REFLECT(镜像) BORDER_CONSTANT
borderValue scalar/tuple borderMode=CONSTANT时的填充值: - 灰度图:单值(如0) - BGR图:三元组(如(0,255,0) 0(黑色)
python 复制代码
# 导入OpenCV和NumPy库
import cv2
import numpy as np

# 读取图片
img = cv2.imread('./images/nezha.png')

# 获取图片的宽高和通道数
# rows: 图像高度(行数)
# cols: 图像宽度(列数) 
# channels: 图像通道数(如3表示BGR彩色图)
rows, cols, channels = img.shape

# 定义原图上三个点的坐标(左上、右上、左下)
# 这些点将用于定义变换前的三角形区域
p1 = np.float32([
    [0, 0],          # 左上角
    [cols-1, 0],     # 右上角
    [0, rows-1]      # 左下角
])

# 定义变换后三个点的目标坐标
# 这里将左下角点移动到右下角位置,实现类似"推斜"效果
p2 = np.float32([
    [0, 0],          # 左上角(保持不变)
    [cols-1, 0],     # 右上角(保持不变)
    [cols-1, rows-1] # 原左下角移动到右下角
])

# 计算仿射变换矩阵
# 根据三组对应点计算2x3变换矩阵
M = cv2.getAffineTransform(p1, p2)

# 应用仿射变换
# img: 输入图像
# M: 变换矩阵
# (cols, rows): 输出图像尺寸(保持原图大小)
dst = cv2.warpAffine(img, M, (cols, rows))

# 显示原始图像
cv2.imshow("img", img)
# 显示变换后的图像
cv2.imshow("dst", dst)
# 等待按键
cv2.waitKey(0)
# 关闭所有窗口
cv2.destroyAllWindows()

四、图像缩放

图像比例缩放是指将给定的图像在x轴方向按比例缩放x倍,在y轴方向按比例缩放y倍,从 而获得一幅新图像。

python 复制代码
resize(src,dsize[,dst[fx[,interpolation]]]]→dst
参数名 类型 说明 注意事项
src numpy.ndarray 输入图像矩阵(BGR或灰度图) 必须参数
dsize tuple (width, height) 目标图像尺寸 与(fx,fy)不能同时为零
fx float x轴方向缩放因子 当dsize=(0,0)时生效
fy float y轴方向缩放因子 当dsize=(0,0)时生效
interpolation int 插值方法: - INTER_NEAREST(最近邻) - INTER_LINEAR(双线性,默认) - INTER_CUBIC(三次样条) - INTER_AREA(区域重采样) 缩小推荐INTER_AREA 放大推荐INTER_LINEAR

使用规则:

  1. 尺寸优先级dsize 参数优先于 fx/fy

  2. 互斥规则

    • 当指定 dsize 时,fxfy 被忽略

    • dsize=(0,0) 时,通过 fxfy 计算尺寸

插值方法选择建议:

场景 推荐方法 特点
图像缩小 INTER_AREA 避免摩尔纹
常规放大 INTER_LINEAR 平衡速度质量
高质量放大 INTER_CUBIC 速度慢但更平滑
边缘保留 INTER_LANCZOS4 8x8像素邻域

插值(Interpolation)

最近邻插值(Nearest Neighbor Interpolation)

立方插值(Cubic Interpolation)

Lanczos 插值(Lanczos Interpolation)
实际应用场景

图像预处理:将所有输入图像统一为相同尺寸

目标检测:在不同尺度上检测目标(图像金字塔)

图像增强:放大图像以便观察细节

图像压缩:缩小图像以节省存储空间

python 复制代码
# 导入OpenCV和NumPy库
import cv2
import numpy as np

# 读取图片
img = cv2.imread('./images/nezha.png')

# 方式1:直接指定目标尺寸进行缩放
# 将图像调整为800×600像素大小
# 使用双线性插值(INTER_LINEAR)保证缩放质量
resized_image_800_600 = cv2.resize(
    img,                   # 原始图像
    (800, 600),            # 目标尺寸(宽度,高度)
    interpolation=cv2.INTER_LINEAR  # 插值方法
)

# 方式2:使用缩放因子进行等比缩放
# 将图像宽高都缩小为原来的一半
# None表示不直接指定尺寸,通过fx/fy计算
resized_image_05_05 = cv2.resize(
    img,                   # 原始图像
    None,                  # 不直接指定尺寸
    fx=0.5,                # 宽度缩放因子(0.5倍)
    fy=0.5,                # 高度缩放因子(0.5倍)
    interpolation=cv2.INTER_LINEAR  # 插值方法
)

# 显示原始图像
cv2.imshow("img", img)
# 显示800×600缩放结果
cv2.imshow("resized_image_800_600", resized_image_800_600)
# 显示0.5倍缩放结果
cv2.imshow("resized_image_05_05", resized_image_05_05)

# 等待按键操作(0表示无限等待)
cv2.waitKey(0)
# 销毁所有OpenCV窗口
cv2.destroyAllWindows()

五、透视变换

透视变换是一种图像处理技术,用于将二维平面上的图像或物体映射到三维空间中。它通 过改变图像的视角和投影来创建一个具有透视效果的图像。

透视变换是一种射影变换(Projective Transformation),它会保持直线的性质,即变换 前的直线在变换后依然是直线。透视变换的核心原理是找到两个图像平面上4个点之间的映 射关系。

cv2.getPerspectiveTransform() 函数用于计算一个透视变换矩阵。透视变换是图像处理中的一种几何 变换,能够将图像中的一个矩形区域转换为另一个矩形区域,通常用于图像的校正、透视投 影等应用。

参数名 类型 说明 注意事项
srcPoints np.float32 (4,2) 源图像中四边形的4个顶点坐标,顺序必须为: 左上 → 右上 → 右下 → 左下 必须严格按顺序排列,否则会导致扭曲错误
dstPoints np.float32 (4,2) 目标图像中对应的4个顶点坐标,顺序与 srcPoints 一致 若希望输出为矩形,目标点应定义为矩形坐标

**cv2.warpPerspective()**将透视变换矩阵应用到源图像,生成透视变换后的图像。

参数名 类型 说明 默认值/注意事项
src numpy.ndarray 输入图像(BGR或灰度图) 必须为OpenCV图像格式(如 cv2.imread() 读取)
M np.float32 (3,3) 透视变换矩阵(来自 cv2.getPerspectiveTransform() 必须是3×3矩阵
dsize tuple (width, height) 输出图像尺寸 若小于输入尺寸,会裁剪图像
flags int 插值方法: INTER_LINEAR(默认) INTER_NEAREST INTER_CUBIC 放大图像推荐 INTER_CUBIC
borderMode int 边界填充方式: BORDER_CONSTANT(默认) BORDER_REPLICATE 填充黑色区域时可指定 borderValue
borderValue scalar/tuple 边界填充值(如 (0, 255, 0) 表示绿色) 默认 0(黑色)

基本步骤

选择源点和目标点: 透视变换的关键是源图像中的四个点和目标图像中的四个点。你需要选择四个对应点(源图像和目标图像的四个 点),这些点通常是矩形的四个角。

计算透视变换矩阵: 使用 cv2.getPerspectiveTransform() 函数来计算变换矩阵,输入源图像四个点和目标图像四个点。

应用透视变换: 使用 cv2.warpPerspective() 函数将透视变换矩阵应用到源图像。
透视变换的应用场景

文档校正:对手机拍摄的书页、名片、票据等图像进行校正,使其恢复为标准矩形,便于后续 OCR(光学字符识别)处理。

车道检测:在自动驾驶系统中,将摄像头拍摄的道路图像透视变换为鸟瞰图,有助于车道线检测和车辆定位。

增强现实(AR):通过透视变换将虚拟图像投影到真实物体表面,实现虚实结合的效果。

图像拼接:在全景图制作过程中,对多个重叠图像进行透视变换,便于图像之间的无缝拼接。

python 复制代码
# 导入必要的库
import cv2
import numpy as np

# 读取图像文件
image = cv2.imread('./images/piao.png')

# 全局变量,用于存储鼠标点击的坐标点
points = []

# 鼠标回调函数
def mouse_callback(event, x, y, flags, param):
    global points
    # 检测鼠标左键点击事件
    if event == cv2.EVENT_LBUTTONDOWN:
        # 将坐标点添加到列表中
        points.append((x, y))
        # 在图像上绘制绿色实心圆标记点击位置(半径5像素)
        cv2.circle(image, (x, y), 5, (0, 255, 0), -1)
        # 更新显示图像
        cv2.imshow("Original", image)

        # 当收集到4个点后
        if len(points) == 4:
            # 将点转换为numpy数组(float32类型)
            pts1 = np.float32(points)
            print(pts1)  # 打印坐标点
            cv2.destroyAllWindows()  # 关闭所有窗口

# 显示原始图像
cv2.imshow("Original", image)   

# 设置鼠标回调函数,关联到"Original"窗口
cv2.setMouseCallback("Original", mouse_callback)

# 等待用户操作(0表示无限等待)
cv2.waitKey(0)

# 将收集到的点转换为numpy数组(float32类型)
pts1 = np.float32([list(i) for i in points])

# 定义目标点坐标(300x300的正方形)
pts2 = np.float32([[0, 0], [300, 0], [300, 300], [0, 300]])

# 计算透视变换矩阵(3x3矩阵)
M = cv2.getPerspectiveTransform(pts1, pts2)

# 应用透视变换,输出300x300的图像
dst = cv2.warpPerspective(image, M, (300, 300))

# 获取变换后图像的尺寸
rows, cols = dst.shape[:2]

# 创建旋转矩阵(以图像中心旋转90度)
M2 = cv2.getRotationMatrix2D((cols/2, rows/2), 90, 1)

# 应用旋转变换
res = cv2.warpAffine(dst, M2, (cols, rows))

# 显示最终结果
cv2.imshow("res", res)
cv2.waitKey(0)
cv2.destroyAllWindows()

相关推荐
测试老哥10 分钟前
软件测试之单元测试
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
张较瘦_12 分钟前
[论文阅读] 人工智能 + 软件工程 | LLM辅助软件开发:需求如何转化为代码?
论文阅读·人工智能·软件工程
whabc10027 分钟前
和鲸社区深度学习基础训练营2025年关卡3_Q1(1)
人工智能·深度学习
勤奋的知更鸟32 分钟前
标准化模型格式ONNX介绍:打通AI模型从训练到部署的环节
人工智能·语言模型
ydm_ymz37 分钟前
C语言初阶4-数组
c语言·开发语言
金山几座39 分钟前
OpenCV探索之旅:形态学魔法
opencv·计算机视觉
presenttttt1 小时前
用Python和OpenCV从零搭建一个完整的双目视觉系统(六 最终篇)
开发语言·python·opencv·计算机视觉
逐花归海.1 小时前
『 C++ 入门到放弃 』- 多态
开发语言·c++·笔记·程序人生
盼小辉丶1 小时前
Transoformer实战——Transformer模型性能评估
人工智能·深度学习·transformer
极限实验室1 小时前
Coco AI 实战(二):摄入MongoDB 数据
人工智能·mongodb