透视与逆透视,及opencv中的warp

解析一下 OpenCV 中的 warp(变换)操作,特别是与透视相关的 warpPerspective

在 OpenCV 的上下文中,warp 通常指的是一种图像几何变换,它根据某种数学规则将输入图像中的像素映射到输出图像中的新位置。这个过程通常涉及两个核心步骤:

  1. 坐标变换:为输出图像中的每个像素点,计算其在输入图像中的对应位置。
  2. 像素插值:由于计算出的对应位置往往是浮点数,需要通过插值算法(如最近邻、双线性等)来确定该位置的像素值。

核心函数:cv2.warpPerspective

这是实现逆透视映射 (IPM) 最直接相关的函数。

功能

对图像进行透视变换 。它可以将图像投影到一个新的视平面,非常适合实现仿射变换 无法实现的"透视效果",例如将一张图片"贴"到一个变形的四边形表面上,或者像我们讨论的,生成鸟瞰图

工作原理
  1. 输入

    • src: 源图像。
    • M: 一个 3x3 的透视变换矩阵。这个矩阵定义了变换的规则。
    • dsize: 输出图像的大小 (width, height)
    • flags: 插值方法(如 cv2.INTER_LINEAR 最常用)。
    • borderMode: 处理边界像素的模式(如 cv2.BORDER_CONSTANT)。
    • borderValue: 如果边界模式为 BORDER_CONSTANT,用于填充边界的值(通常为黑色 0)。
  2. 内部过程(逆映射)
    warpPerspective 使用的是逆映射(Inverse Mapping),这是理解其行为的关键。它的工作流程是:

    • 对于输出图像(鸟瞰图) 上的每一个目标像素点 (x_dst, y_dst)...
    • 使用变换矩阵 M逆矩阵 M⁻¹ ,计算该点在输入图像 上对应的源位置 (x_src, y_src)
      (x_src, y_src) = apply_homography(M⁻¹, (x_dst, y_dst))
    • 由于 (x_src, y_src) 通常是浮点数,使用指定的插值算法(如双线性插值)从输入图像中该位置周围像素计算出一个新的像素值。
    • 将这个新像素值赋给输出图像的 (x_dst, y_dst) 位置。

    为什么用逆映射? 因为正向映射(从原图映射到目标图)会导致目标图上出现空洞(没有像素映射到)和重叠(多个像素映射到同一点)的问题。逆映射可以保证输出图像中的每个像素都被精确地填充。

  3. 输出

    经过透视变换后的新图像。


如何获取变换矩阵 M

M 矩阵是 warpPerspective 的灵魂。获取方式主要有两种:

  1. cv2.getPerspectiveTransform(src_pts, dst_pts)

    • 作用 :根据源图像和目标图像上的 4 组对应点 ,计算变换矩阵 M

    • 原理:通过解线性方程组来求解单应性矩阵。它需要至少 4 个点,并且假设这些点都在同一个平面上(完美符合IPM的假设)。

    • 示例

      python 复制代码
      # 假设在原始透视图像上选取了一个梯形的四边形区域
      src_pts = np.float32([[580, 460], [700, 460], [1100, 720], [200, 720]])
      # 希望它在鸟瞰图中变成一个矩形
      dst_pts = np.float32([[400, 0], [900, 0], [900, 720], [400, 720]])
      
      M = cv2.getPerspectiveTransform(src_pts, dst_pts) # 计算从 src 到 dst 的变换矩阵
      bird_eye_view = cv2.warpPerspective(image, M, (image.shape[1], image.shape[0]))
  2. cv2.findHomography(src_pts, dst_pts, method)

    • 作用:功能更强大的函数,也用于计算单应性矩阵。

    • 优势

      • 可以输入多于4个的点对,求一个最优解。
      • 内置了鲁棒性算法(如 cv2.RANSAC),可以排除错误匹配点( outliers ) 的干扰。这在通过特征点匹配计算Homography时非常有用。
      • getPerspectiveTransform 的一个更通用、更鲁棒的版本。
    • 示例

      python 复制代码
      M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

其他相关的 warp 函数

  1. cv2.warpAffine

    • 功能 :进行仿射变换。仿射变换是透视变换的一个子集,它保持了图像的"平直性"(直线变换后还是直线)和"平行性"(平行线变换后依然平行)。
    • 常见应用 :平移、旋转、缩放、剪切。它不能产生透视效果(近大远小)。
    • 变换矩阵 :使用 2x3 的矩阵。
  2. cv2.remap

    • 功能:一种更底、更灵活的几何变换函数。
    • 原理 :它直接要求你提供两个映射图 map_xmap_y,来指明输出图像中每个像素 (x,y) 应该从输入图像的哪个位置 (map_x(x,y), map_y(x,y)) 取像素值。
    • 应用 :常用于复杂的自定义变换,例如镜头畸变校正 。校正鱼眼相机图像时,cv2.fisheye.undistortImage 的内部通常就是先计算好 map_xmap_y,然后调用 remap 来实现的。

总结

函数 核心作用 变换类型 关键输入
warpPerspective 执行透视变换,实现IPM、视角转换 投影变换 3x3 单应性矩阵 M
getPerspectiveTransform 计算 用于 warpPerspective 的变换矩阵 M - 4组对应点
findHomography 鲁棒地计算 变换矩阵 M(更强大) - 多组对应点 + 方法(如RANSAC)
warpAffine 执行仿射变换(旋转、缩放、剪切等) 仿射变换 2x3 矩阵
remap 执行任意自定义的几何变换 任意变换 映射图 map_x, map_y

简单来说,在逆透视映射的流程中:
getPerspectiveTransform/findHomography 负责制定规则 (计算变换矩阵 M),而 warpPerspective 负责执行规则 (根据 M 对图像进行实际的像素变换)。

相关推荐
云知谷21 小时前
【C++基本功】C++适合做什么,哪些领域适合哪些领域不适合?
c语言·开发语言·c++·人工智能·团队开发
rit84324991 天前
基于MATLAB实现基于距离的离群点检测算法
人工智能·算法·matlab
初学小刘1 天前
深度学习:从图片数据到模型训练(十分类)
人工智能·深度学习
递归不收敛1 天前
大语言模型(LLM)入门笔记:嵌入向量与位置信息
人工智能·笔记·语言模型
之墨_1 天前
【大语言模型】—— 自注意力机制及其变体(交叉注意力、因果注意力、多头注意力)的代码实现
人工智能·语言模型·自然语言处理
从孑开始1 天前
ManySpeech.MoonshineAsr 使用指南
人工智能·ai·c#·.net·私有化部署·语音识别·onnx·asr·moonshine
涛涛讲AI1 天前
一段音频多段字幕,让音频能够流畅自然对应字幕 AI生成视频,扣子生成剪映视频草稿
人工智能·音视频·语音识别
可触的未来,发芽的智生1 天前
新奇特:黑猫警长的纳米世界,忆阻器与神经网络的智慧
javascript·人工智能·python·神经网络·架构
WWZZ20251 天前
快速上手大模型:机器学习2(一元线性回归、代价函数、梯度下降法)
人工智能·算法·机器学习·计算机视觉·机器人·大模型·slam
AKAMAI1 天前
数据孤岛破局之战 :跨业务分析的难题攻坚
运维·人工智能·云计算