Python OpenCV 透视变换(Perspective Transform)详解与实战

在机器视觉开发中,经常会遇到目标存在倾斜、旋转或拍摄角度不一致的问题。例如标签识别、二维码识别、文档扫描、车牌识别等,如果直接进行后续处理,往往会影响算法的准确率。

透视变换(Perspective Transform) 可以将任意四边形区域映射为规则矩形,实现图像校正(Rectification),是工业视觉中非常重要的一项图像处理技术。

本文将介绍透视变换的基本原理,并结合 OpenCV 提供完整的 Python 示例代码。

一、什么是透视变换?

透视变换(Perspective Transform)又称单应性变换(Homography),它能够描述同一平面在不同视角下的映射关系。

复制代码
      倾斜图像                    校正后

   ┌────────┐              ┌──────────┐
  /          /|            │          │
 /          / |    --->    │          │
└──────────┘  |            │          │
 \          \ |            │          │
  \          \|            └──────────┘

经过透视变换后:

  • 倾斜标签恢复水平
  • 文档恢复矩形
  • 方便 OCR 识别
  • 提高测量精度

二、透视变换原理

二维平面的透视变换可表示为:

x′y′w=Hxy1 \begin{bmatrix} x' \\ y' \\ w \end{bmatrix} = H \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} x′y′w =H xy1

其中:

  • (x,y)(x,y)(x,y):原图坐标
  • (x′,y′)(x',y')(x′,y′):变换后的坐标
  • HHH:3×3 单应性矩阵(Homography Matrix)

最终坐标需要进行归一化:

X=x′w,Y=y′w X = \frac{x'}{w}, \quad Y = \frac{y'}{w} X=wx′,Y=wy′

OpenCV 会自动完成这些计算,我们只需要提供四个对应点即可。

三、OpenCV 实现流程

透视变换通常分为两步:

  1. 四个对应点
  2. cv2.getPerspectiveTransform() → 得到变换矩阵 M
  3. cv2.warpPerspective() → 得到校正后的图像

四、getPerspectiveTransform()

OpenCV 提供:

python 复制代码
M = cv2.getPerspectiveTransform(src, dst)

其中:

  • src:原图四个角点
  • dst:目标图四个角点

例如:

python 复制代码
src = np.float32([
    [120,80],
    [450,60],
    [480,320],
    [90,350]
])

dst = np.float32([
    [0,0],
    [400,0],
    [400,300],
    [0,300]
])

M = cv2.getPerspectiveTransform(src, dst)

此时得到变换矩阵 M(3×3 Matrix)。

五、warpPerspective()

获得矩阵之后即可进行透视校正:

python 复制代码
result = cv2.warpPerspective(img, M, (400, 300))

参数说明:

参数 说明
img 输入图像
M 透视变换矩阵
(400, 300) 输出图像尺寸

返回值就是校正后的图像。

六、完整示例

python 复制代码
import cv2
import numpy as np

# 读取图片
img = cv2.imread("label.jpg")

# 原图四个顶点
src = np.float32([
    [120,80],
    [450,60],
    [480,320],
    [90,350]
])

# 目标矩形
dst = np.float32([
    [0,0],
    [400,0],
    [400,300],
    [0,300]
])

# 计算透视矩阵
M = cv2.getPerspectiveTransform(src, dst)

# 执行透视变换
result = cv2.warpPerspective(
    img,
    M,
    (400,300)
)

cv2.imshow("Original", img)
cv2.imshow("Perspective", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行后即可得到校正后的矩形图像。

七、自动获取四个顶点

实际项目中,四个角点通常不是手动输入,而是通过轮廓检测获得。

例如:

python 复制代码
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mask = cv2.inRange(gray, 120, 255)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(contours, key=cv2.contourArea)
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.float32(box)

此时 box 就是四个角点坐标,可以直接作为透视变换输入。这也是工业视觉最常见的方法。

八、角点排序

由于 cv2.boxPoints() 返回的四个点顺序可能不同,因此通常需要重新排序。

常见顺序为:

复制代码
左上 ---- 右上
 |          |
 |          |
左下 ---- 右下

排序后才能保证透视结果不会发生镜像或旋转。

示例代码:

python 复制代码
def order_points(pts):
    pts = np.array(pts)
    s = pts.sum(axis=1)
    diff = np.diff(pts, axis=1)
    rect = np.zeros((4, 2), dtype=np.float32)
    rect = pts[np.argmin(s)]      # 左上
    rect = pts[np.argmax(s)]      # 右下
    rect = pts[np.argmin(diff)]   # 右上
    rect = pts[np.argmax(diff)]   # 左下
    return rect

这是 OpenCV 项目中常用的排序方式。

九、工业视觉中的应用

透视变换广泛应用于:

  • 标签识别
  • OCR 文字识别
  • 条码识别
  • 二维码识别
  • 文档扫描
  • PCB 定位
  • 产品尺寸测量
  • AOI 自动光学检测
  • 工件姿态校正

例如在标签检测中,通常先通过轮廓找到标签区域,再利用透视变换将倾斜标签拉正,最后送入 OCR 引擎识别,可显著提升识别准确率。

十、透视变换与仿射变换的区别

对比项 仿射变换 透视变换
需要点数 3 个点 4 个点
保持平行线 保持 不保持
是否可处理透视畸变 不可以 可以
变换矩阵 2×3 3×3
常见函数 cv2.warpAffine() cv2.warpPerspective()

简单来说,仿射变换适用于旋转、平移、缩放等线性变换,而透视变换能够处理拍摄角度带来的透视畸变,因此适用范围更广。

十一、总结

透视变换是 OpenCV 中处理图像几何畸变的重要工具,通过四个对应点建立映射关系,可以将倾斜或变形的目标恢复为规则矩形。在工业视觉中,它常与阈值分割、轮廓检测、最小外接矩形等算法配合使用,实现标签校正、OCR 识别、二维码识别以及高精度尺寸测量等功能。

熟练掌握 cv2.getPerspectiveTransform() 与 cv2.warpPerspective() 的使用方法,是进行图像校正和机器视觉开发的重要基础。

相关推荐
怕浪猫3 小时前
RAG 面试 6 连问,从原理到优化全部覆盖
python·算法·面试
高洁013 小时前
具身智能中的世界模型训练
人工智能·python·深度学习·机器学习·transformer
无线通信科研笔记3 小时前
IEEE TVT 2026 论文精读与完整复现|相位误差如何重塑近场 RIS 的幅相响应
论文阅读·人工智能·python·算法·论文笔记
朝朝辞暮i3 小时前
VLA 系统学习第 1 课:VLA 到底在干什么?
人工智能·python·计算机视觉·vla
2601_962885724 小时前
如何用 Python 自动识别股票的支撑位与压力位?
开发语言·python
爱吃奥利奥_wen4 小时前
面向对象三板斧:封装、继承、多态,到底在“装“什么、“承“什么、“变“什么?
开发语言·经验分享·c#
北冥有鱼被烹4 小时前
VCSEL全景解析:与光模块NPO CPO的关系、市场量化分析与产业链影响
python
我可能是个假开发4 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong5 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
正在走向自律5 小时前
AI数据分析与可视化:从基础到应用实践
服务器·人工智能·python·机器学习·数据分析·pandas