1477 字
7 分钟
OpenCV:几何变换

1. 概述#

​ 几何变换是将一幅图像中的坐标位置映射到另一幅图像中的新坐标位置,实质是改变像素的空间位置,估算新空间位置上的像素值。

​ 常见的几何变换包括:缩放翻转仿射变换透视等。

2. 缩放#

2.1 使用方式#

  • 调用函数cv2.resize()实现对图像的缩放
  • 函数原型dst = cv2.resize( src, dsize, fx, fy, interpolation )
  • 函数参数
    • dst :表示目标图像
    • src:表示原始图像
    • dsize:表示输出图像大小
    • fx:表示水平方向的缩放比例
    • fy:表示垂直方向的缩放比例
    • interpolation:表示插值方式
  • 插值
    • 理解:在对图像进行几何处理时,给无法直接通过映射得到值的像素点赋值。
    • 举例:将图像放大为原来的2倍,必然会多出一些无法被直接映射值的像素点,对于这些像素点,插值方式决定了如何确定它们的值。
    • 插值方式
类型说明适用场景
cv2.INTER_NEAREST最近邻插值
cv2.INTER_LINEAR双线性插值(默认)放大图像,速度较快
cv2.INTER_CUBIC三次样条插值放大图像,速度较慢
cv2.INTER_LINEAR_EXACT位精确双线性插值
cv2.INTER_AREA区域插值缩小图像
cv2.INTER_MAX差值编码掩码
  • 目标图像的大小:通过dsize或者fx、fy二者之一来指定
    • 通过dsize指定:无论是否指定fx、fy的值,都由dsize决定目标图像的大小。
      • shape属性中,第1个值对应的是行数第2个值对应的是列数
      • dsize参数中,第1个值对应的是列数第2个值对应的是行数
    • 通过fx、fy指定dsize需要设定为None,此时目标图像的大小由fx、fy来决定。
      • 目标图像大小:dsize = (round(fx * src.cols), round(fy * src.rows))

2.2 示例#

import cv2
src = cv2.imread("person.jpg")
dst = cv2.resize(src, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)
cv2.imwrite("resize.jpg", dst)
原图缩放

3. 翻转#

3.1 使用方式#

  • 调用函数cv2.flip()实现对图像的翻转
  • 函数原型dst = cv2.flip( src, flipCode )
  • 函数参数
    • dst :表示目标图像
    • src:表示原始图像
    • flipCode :表示旋转类型
参数值意义
0绕着x轴翻转:水平翻转
任意正整数绕着y轴翻转:垂直翻转
任意负整数绕着x轴、y轴同时翻转:水平翻转 + 垂直翻转

3.2 示例#

import cv2
src = cv2.imread("person.jpg")
x = cv2.flip(src, 0)
y = cv2.flip(src, 1)
x_y = cv2.flip(src, -1)
cv2.imwrite("x.jpg", x)
cv2.imwrite("y.jpg", y)
cv2.imwrite("x+y.jpg", x_y)
原图水平翻转垂直翻转水平翻转 + 垂直翻转
xyx+y

4. 仿射变换#

仿射变换 是指 图像可以通过一系列的几何变换来实现平移、旋转等多种操作 ,该变换能够保持图像的平直性和平行性。平直性和平行性是指图像经过仿射变换后,直线仍然是直线,平行线仍然是平行线。

​ 在OpenCV中,通过变换矩阵M、配合仿射变换函数cv2.warpAffine()实现仿射变换。

4.1 变换原理#

[xdstydst]=[M11M12M13M21M22M23][xsrcysrc1]\begin{bmatrix} x_{dst} \\ y_{dst} \end{bmatrix} = \begin{bmatrix} M_{11}&M_{12}&M_{13} \\ M_{21}&M_{22}&M_{23} \end{bmatrix} *\begin{bmatrix} x_{src} \\ y_{src} \\ 1 \end{bmatrix}

4.2 使用方式#

  • 调用函数cv2.warpAffine()实现对图像的仿射变换
  • 函数原型dst = cv2.warpAffine( src, M, dsize, flags, borderMode, borderValue )
  • 函数参数
    • dst :表示目标图像
    • src:表示原始图像
    • M:代表一个2×3的变换矩阵。使用不同的变换矩阵,就可以实现不同的仿射变换。
    • dsize:表示输出图像大小
    • flags:表示插值方式
    • borderMode:代表边界类型,默认为BORDER_CONSTANT
    • borderValue:代表边界值,默认是0

4.3 示例:平移#

import cv2
import numpy as np
src = cv2.imread("person.jpg")
H, W, C = src.shape
M = np.float32([[1, 0, 200], [0, 1, 400]])
dst = cv2.warpAffine(src, M, (W, H))
cv2.imwrite("offset.jpg", dst)
原图平移
offset

4.4 示例:旋转#

  • 通过函数cv2.getRotationMatrix2D()获取转换矩阵
  • 函数原型retval = cv2.getRotationMatrix2D(center, angle, scale)
  • 函数参数
    • center:表示图像旋转的中心点
    • angle:表示旋转角度,正数表示逆时针旋转,负数表示顺时针旋转。
    • scale:表示缩放尺度
import cv2
import numpy as np
src = cv2.imread("person.jpg")
H, W, C = src.shape
M = cv2.getRotationMatrix2D((W/2, H/2), 45, 0.5)
dst = cv2.warpAffine(src, M, (W, H))
cv2.imwrite("rotate.jpg", dst)
原图旋转
rotate

4.5 示例:任意变换#

  • 通过函数cv2.getAffineTransform()获取转换矩阵
  • 函数原型retval = cv2.getAffineTransform(pt_src, pt_dst)
  • 函数参数
    • pt_src:表示输入图像的三个点坐标,对应平行四边形的左上角右上角左下角
    • pt_dst:表示输出图像的三个点坐标,对应平行四边形的左上角右上角左下角
import cv2
import numpy as np
src = cv2.imread("person.jpg")
H, W, C = src.shape
pt1 = np.float32([[0, 0], [W - 1, 0], [0, H - 1]])
pt2 = np.float32([[0, H * 0.15], [W * 0.8, H * 0.2], [W * 0.15, H * 0.9]])
M = cv2.getAffineTransform(pt1, pt2)
dst = cv2.warpAffine(src, M, (W, H))
cv2.imwrite("affine.jpg", dst)
原图任意变换
affine

5. 透视变换#

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

5.1 使用方式#

透视变换#

  • 调用函数cv2.warpPerspective()实现透视变换
  • 函数原型dst = cv2.warpPerspective( src, M, dsize, flags, borderMode, borderValue )
  • 函数参数
    • dst :表示目标图像
    • src:表示原始图像
    • M:代表一个3×3的变换矩阵
    • dsize:表示输出图像大小
    • flags:表示插值方式,默认为INTER_LINEAR
    • borderMode:代表边界类型,默认为BORDER_CONSTANT
    • borderValue:代表边界值,默认是0

转换矩阵#

  • 通过函数cv2.getPerspectiveTransform()获取转换矩阵
  • 函数原型retval = cv2.getPerspectiveTransform(pt_src, pt_dst)
  • 函数参数
    • pt_src:表示输入图像的四个顶点坐标
    • pt_dst:表示输出图像的四个点坐标

5.2 示例#

import cv2
import numpy as np
src = cv2.imread("person.jpg")
H, W, C = src.shape
pt1 = np.float32([[0, 0], [W - 1, 0], [0, H - 1], [W - 1, H - 1]])
pt2 = np.float32([[100, H / 4], [W - 100, H / 3], [100, H * 3 / 4], [W - 100, H * 2 / 3]])
M = cv2.getPerspectiveTransform(pt1, pt2)
dst = cv2.warpPerspective(src, M, (W, H))
cv2.imwrite("perspective.jpg", dst)
原图透视变换
perspective
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00