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() 的使用方法,是进行图像校正和机器视觉开发的重要基础。

相关推荐
小李不困还能学1 小时前
PyCharm下载安装与配置教程
ide·python·pycharm
程序猿编码1 小时前
用C++从零开始造一个微型GPT,不借助任何第三方库
开发语言·c++·gpt·模型推理
博观而约取厚积而薄发1 小时前
Pytest 从入门到精通,一篇就够(超详细实战教程)
python·测试工具·单元测试·自动化·pytest
imzed1 小时前
使用 Playwright + Pytest 构建 Web UI 自动化测试框架
python·自动化·pytest
普通网友2 小时前
pytest一些常见的插件
开发语言·python·pytest
苦瓜花2 小时前
【Kotlin】初入门
android·开发语言·kotlin
时空系2 小时前
Python 高性能高压缩打包器 —— 基于 JianPy 语义分析引擎
python
cndes2 小时前
给Miniconda换源,让包下载更迅速
开发语言·python