OpenCV基于Python图像的几何变换

目标

  • 学习将不同的几何变换应用到图像上,如平移、旋转、仿射变换等。
  • 你会使用到函数: cv.getPerspectiveTransform

变换

OpenCV提供了两个转换函数cv.warpAffinecv.warpPerspective,您可以使用它们进行各
种转换。cv.warpAffine采用2x3转换矩阵,而cv.warpPerspective采用3x3转换矩阵作为输
入。

缩放

缩放只是调整图像的大小。为此,OpenCV带有一个函数cv.resize()。图像的大小可以手动指
定,也可以指定缩放比例。也可使用不同的插值方法。首选的插值方法是cv.INTER_AREA
于缩小,cv.INTER_CUBIC(慢)和cv.INTER_LINEAR
用于缩放。默认情况下,出于所有调
整大小的目的,使用的插值方法为cv.INTER_LINEAR。您可以使用以下方法调整输入图像的大
小:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC) #或者
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

平移

平移是物体位置的移动。如果您知道在(x,y)方向上的位移,则将其设为(t_x,t_y),你可以创建转换
矩阵\mathbf{M},如下所示:
M = \begin{bmatrix} 1 & 0 & t_x \ 0 & 1 & t_y \end{bmatrix}
您可以将其放入np.float32类型的Numpy数组中,并将其传递给cv.warpAffine函数。参见下
面偏移为(100, 50)的示例:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst1 = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

警告

cv.warpAffine函数的第三个参数是输出图像的大小,其形式应为 (width,height) 。记住
width =列数, height =行数。

你将看到下面的结果:
gray
pingyi

旋转

图像旋转角度为θ是通过以下形式的变换矩阵实现的:
M = \begin{bmatrix} cos\theta & -sin\theta \ sin\theta & cos\theta \end{bmatrix}
但是OpenCV提供了可缩放的旋转以及可调整的旋转中心,因此您可以在自己喜欢的任何位置旋
转。修改后的变换矩阵为
\begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot center.x - \beta \cdot center.y \ - \beta &
\alpha & \beta \cdot center.x + (1- \alpha ) \cdot center.y \end{bmatrix}

其中:
\begin{array}{l} \alpha = scale \cdot \cos \theta , \ \beta = scale \cdot \sin \theta \end{array}
为了找到此转换矩阵,OpenCV提供了一个函数cv.getRotationMatrix2D。请检查以下示例,该
示例将图像相对于中心旋转90度而没有任何缩放比例。

img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 和 rows-1 是坐标限制
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst2 = cv.warpAffine(img,M,(cols,rows))

查看结果:
rotation

仿射变换

在仿射变换中,原始图像中的所有平行线在输出图像中仍将平行。为了找到变换矩阵,我们需要
输入图像中的三个点及其在输出图像中的对应位置。然后cv.getAffineTransform将创建一个2x3
矩阵,该矩阵将传递给cv.warpAffine

查看以下示例,并查看我选择的点(以绿色标记):

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

img = cv.imread('./data/drawing_green.png') #请设置图片的位置路径
# img = cv.imread('./data/drawing_red.png')
rows, cols, ch = img.shape
pts1 = np.float32([[100, 90], [180, 90], [100, 160]])
pts2 = np.float32([[90, 100], [180, 90], [150, 180]])
M = cv.getAffineTransform(pts1, pts2)
dst = cv.warpAffine(img, M, (cols, rows))
# cv.imshow('img', img)
plt.imshow(img) # 显示查看一下原始图像
plt.show()
# cv.waitKey(0)
# cv.destroyAllWindows()
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()

原始图像(绿色标记点)

原始图像(绿色标记点)

warpAffine

仿射变换后的结果

注意:
OpenCV加载的彩色图像处于BGR模式。但是Matplotlib以RGB模式显示。因此,如果使用OpenCV读取彩色图像,则Matplotlib中将无法正确显示彩色图像。例如:

  • 当原始图像为绿色标记的点时,经过仿射变换后,绿色标记点的结果图像仍为绿色,因为BGR↔RGB。
  • 当原始图像为红色标记的点时,经过仿射变换后,红色标记点的结果图像变为蓝色,因为BGR↔RGB

原始图像(红色标记点

原始图像(红色标记点)

warpAffine

仿射变换后的结果

透视变换

对于透视变换,您需要3x3变换矩阵。即使在转换后,直线也将保持直线。要找到此变换矩阵,您
需要在输入图像上有4个点,在输出图像上需要相应的点。在这四个点中,其中三个不应共线。然
后可以通过函数cv.getPerspectiveTransform找到变换矩阵。然后将cv.warpPerspective
用于此3x3转换矩阵。

请参见下面的代码:

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

img = cv.imread('./data/sudoku_hong.png') # 请设置图片所在路径
rows, cols, ch = img.shape
pts1 = np.float32([[74, 84], [487, 67], [35, 510], [516, 516]])
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
M = cv.getPerspectiveTransform(pts1, pts2)
dst = cv.warpPerspective(img, M, (300, 300))
plt.imshow(img) # 显示查看一下原始图像
plt.show()
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()

原始图像(红色标记)

原始图像
结果:

warpPerspective

透视变换后的结果

投射变换过程中,同样存在Matplotlib中将无法正确显示彩色图像现象,红色标记点的结果图像变为蓝色,因为BGR↔RGB

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值