在这里插入图片描述

仿射变换可以将矩形图片映射为平行四边形,
透视变换可以将矩形图片映射为任意四边形。


前言

opencv提供了两个变换函数,cv2.warpAffine和cv2.warpPerspective,
使用这两个函数可以实现所有类型的变换。

cv2.warpAffine 接收的参数2x3的变换矩阵;

cv2.warpPerspective 接收的3x3的变换矩阵。


一、仿射变换 cv2.warpAffine()

1.1 函数说明

img_out = cv.warpAffine(img, mat, size)

@desc:
img_out -- 输出图像
img -- 原始图像
mat -- 2×3的变换矩阵
size -- 变换后图像尺寸
  1. 仿射变换(Affine Transformation) 包括平移(transform)、旋转(rotate)、缩放(scale)、剪切(shear)。
  2. 本质上是另外两种简单变换的叠加:一个是线性变换,一个是平移变换
  3. 该变换能保证图像的平直性和平行性,原来的直线仿射变换后还是直线,原来的平行线经过仿射变换之后还是平行线。
  4. 进行哪种形式的仿射变换完全取决于变换矩阵mat。

1.2 仿射变换实例

变换矩阵mat不同,变换类型不同

仿射变换矩阵mat的三种设定方式:

  1. 人为给定
  2. 使用函数 cv2.getRotationMatrix2D()
  3. 使用函数 cv2.getAffineTransform(src, dst)

1.2.1 平移变换

平移矩阵 mat_shift 为人为给定。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# ----------------------------------------------------#
#           读取图像
# ----------------------------------------------------#
image_original = cv.imread("LenaRGB.bmp")
H, W, _ = image_original.shape
cv.imshow("image_original", image_original)
cv.waitKey(delay=0)

# ----------------------------------------------------#
#           平移变换
# mat = [[1,0,dx],
#        [0,1,dy]]
# ----------------------------------------------------#
dx = 50
dy = 100
mat_shift = np.float32([[1, 0, dx],
                        [0, 1, dy]])  # 构造平移矩阵
image_shift = cv.warpAffine(image_original, mat_shift, (W, H))
cv.imshow("image_shift", image_shift)
cv.waitKey(delay=0)
cv.destroyAllWindows()

Lena图

1.2.2 旋转变换

旋转矩阵 mat_rotate 使用函数 cv2.getRotationMatrix2D() 获得。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# ----------------------------------------------------#
#           读取图像
# ----------------------------------------------------#
image_original = cv.imread("LenaRGB.bmp")
H, W, _ = image_original.shape
cv.imshow("image_original", image_original)
cv.waitKey(delay=0)

# ----------------------------------------------------#
#           旋转变换
# 对于图像的变换,OpenCV 提供了 getRotationMatrix2D() 函数来得到旋转矩阵
# 该函数包含三个参数,第一个参数是旋转中心,第二个参数是旋转角度,第三个参数是缩放比例
# mat = cv2.getRotationMatrix2D(center, angle, scale)
# ----------------------------------------------------#
center = (256, 256)
angle = 45
scale = 1
mat_rotate = cv.getRotationMatrix2D(center, angle, scale)
image_rotate = cv.warpAffine(image_original, mat_rotate, (W, H))
cv.imshow("image_rotate", image_rotate)
cv.waitKey(delay=0)
cv.destroyAllWindows()
opencv
OpenCV: 开源计算机视觉库

Lena图

1.2.3 一般仿射变换

仿射矩阵 mat_affine 使用函数cv2.getAffineTransform() 获得。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# ----------------------------------------------------#
#           读取图像
# ----------------------------------------------------#
image_original = cv.imread("LenaRGB.bmp")
H, W, _ = image_original.shape
cv.imshow("image_original", image_original)
cv.waitKey(delay=0)

# ----------------------------------------------------#
#           仿射变换
# 变换矩阵mat可通过cv.getAffineTransfrom(points1, points2)函数获得
# 变换矩阵的获取需要至少三组变换前后对应的点坐标,设取原图上的三个点组成矩阵points1,变换后的三个点组成的矩阵points2
# mat_affine = cv.getAffineTransform(points1, points2)
# image_affine = cv.warpAffine(image_original, mat_affine, (image_original.shape[1], image_original.shape[0]))
# ----------------------------------------------------#
points1 = np.float32([[30, 30], [100, 40], [40, 100]])
points2 = np.float32([[60, 60], [200, 80], [80, 200]])
mat_affine = cv.getAffineTransform(points1, points2)
image_affine = cv.warpAffine(image_original, mat_affine, (W, H))
cv.imshow("image_affine", image_affine)
cv.waitKey(delay=0)
cv.destroyAllWindows()

在这里插入图片描述

1.3 仿射变换总结

  1. 在仿射变换中,原图中所有的平行线,在结果图像中仍然保持平行。
    为了得到仿射变换矩阵,需要从原图像中找到三个点以及在输出图像中的对应点。然后cv2.getAffineTransform()函数会创建一个2x3的矩阵,即为仿射变换矩阵。
    最后将矩阵传入函数cv2.warpAffine()对图像进行仿射变换。
  2. 仿射变换是一种二维坐标到二维坐标之间的线性变换,它保持了二维图形的平直性(直线经过变换之后依然是直线)和平行性(二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。
  3. 任意的仿射变换都能表示为乘一个矩阵(线性变换),再加上一个向量(平移)的形式。

二、透视变换 cv2.warpPerspective()

2.1 函数说明

img_out = cv.warpPerspective(img, mat, size)

@desc:
img_out -- 输出图像
img -- 原始图像
mat -- 3×3的变换矩阵
size -- 变换后图像尺寸
  1. 透视变换(Perspective Transformation) 也叫视角转换,是将图片投影到一个新的视平面,也称作投影映射。顾名思义,将图片从一个视角转换到另一个视角
  2. 该变换能保证图像的平直性,不保证平行性,透视变换可保持直线不变形,但是平行线可能不再平行。

2.2 透视变换实例

透视变换矩阵 mat_perspective 使用函数 cv.getPerspectiveTransform() 获得。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# ----------------------------------------------------#
#           读取图像
# ----------------------------------------------------#
image_original = cv.imread("LenaRGB.bmp")
H, W, _ = image_original.shape
cv.imshow("image_original", image_original)
cv.waitKey(delay=0)

# ----------------------------------------------------#
#           透视变换
# 变换矩阵mat可通过cv.getPerspectiveTransform()函数获得,原理和cv.getAffineTransform()相同
# 透视变换至少需要四组变换前后对应的点坐标
# 设取原图上的四个点组成矩阵points1,变换后的四个点组成的矩阵points2
# mat_perspective = cv.getPerspectiveTransform(points1, points2)
# image_perspective = cv.warpPerspective(image_original, mat_perspective, (image_original.shape[1], image_original.shape[0]))
# ----------------------------------------------------#
points1 = np.float32([[30, 30], [10, 40], [40, 10], [5, 15]])
points2 = np.float32([[0, 0], [400, 0], [0, 400], [400, 400]])

mat_perspective = cv.getPerspectiveTransform(points1, points2)
image_perspective = cv.warpPerspective(image_original, mat_perspective,
                                       (image_original.shape[1], image_original.shape[0]))

cv.imshow("image_perspective", image_perspective)
cv.waitKey(delay=0)
cv.destroyAllWindows()

在这里插入图片描述

2.3 透视变换总结

  1. 对于视角变换,需要一个3x3的变换矩阵。
    为了得到视角变换(透视变换)矩阵,需要在输入图像上找四个点,以及在输出图像上对应的位置。这四个点中的任意三个都不能共线。
    然后函数cv2.getPerspectiveTransform()创建一个3x3的矩阵,即为视角变换矩阵。
    最后将矩阵传入函数cv2.warpPerspective对图像进行透视变换。
  2. 视角变换是二维到三维,再到另一个二维视平面的映射。
  3. 相对于仿射变换,视角变换灵活性更高,将一个四边形矩形区域映射到另一个四边形区域(不一定是平行四边形),不只是线性变换,但也是通过矩阵乘法实现的,使用的是3x3的矩阵,矩阵前两行和仿射矩阵相同,也实现了线性变换和平移,第三行用于实现透视变换。

三、单应性变换cv2.findHomography()

参考单应性cv.findHomography 相关的:
OpenCV中的「透视变换 / 投影变换 / 单应性」—cv.warpPerspective、cv.findHomography
单应性矩阵可以当作透视变换中的透视变换矩阵mat 。

四、总结

  1. 仿射变换可以将矩形图片映射为平行四边形,
    透视变换可以将矩形图片映射为任意四边形。

  2. 仿射变换是透视变换的一种特殊形式,它是把二维转到三维,变换后在映射回之前的二维空间,而不是另一个二维空间。
  3. 仿射变换至少需要三个对应的点坐标,透视变换至少需要四个。

参考链接:
cv2.warpAffine、cv2.warpPerspective
cv2.getPerspectiveTransform()与cv2.warpPerspective()详解
python之详细图像仿射变换讲解(图像平移、旋转、缩放、翻转)
透视变换(Perspective Transformation)

阅读全文
AI总结
GitHub 加速计划 / opencv31 / opencv
192
14
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:7 个月前 )
767dd838 Fix configuring with CMake version 4 1 小时前
6ffc515b Parallel_for in box Filter and support for 32f box filter in Fastcv hal #27182 Added parallel_for in box filter hal and support for 32f box filter ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 2 小时前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐