OpenCV图像的几何变换

目标

  • 学习将不同的几何变换应用于平移、旋转、仿射变换等图像。
  • 您将看到以下功能:cv2.getPerspectiveTransform

变换

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

缩放

缩放只是调整图像的大小。OpenCV附带了一个函数cv2.resize()为了这个目的。图像的大小可以手动指定,也可以指定缩放因子。采用了不同的插值方法。较好的插值方法是cv2.INTER_AREA因为收缩和cv2.INTER_CUBIC(慢)&cv2.INTER_LINEAR放大。默认情况下,使用的插值方法是cv2.INTER_LINEAR所有调整大小的用途。您可以调整输入图像的大小,以下方法之一是:

import cv2
import numpy as np

img = cv2.imread('messi5.jpg')

res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)

#OR

height, width = img.shape[:2]
res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)

Translation

Translation 是对象位置的转移。如果你知道(x,y)方向的变化,那就让它变成(x,y)方向吧。(t_x,t_y),您可以创建转换矩阵。\textbf{M}详情如下:

M = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y  \end{bmatrix}

您可以将其转换为类型为Numpy的数组。np.float32把它传递给cv2.warpaffine()功能。关于(100,50)的转移,请参见下面的示例:

import cv2
import numpy as np

img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape

M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))

cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

警告:cv2.warpaffine()函数是输出图像的大小,应该以(宽度、高度)。记住宽度=列数和高度=行数。

见以下结果:

旋转

图像的角度旋转\theta是通过形式的变换矩阵来实现的。

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提供了一个函数,cv2.getRotationMatrix2D。检查下面的例子,它使图像相对于中心旋转了90度,没有任何缩放。

img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape

M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))

见结果:

仿射变换

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

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

img = cv2.imread('drawing.png')
rows,cols,ch = img.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])

M = cv2.getAffineTransform(pts1,pts2)

dst = cv2.warpAffine(img,M,(cols,rows))

plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

见结果:

透视变换

对于透视转换,您需要一个3x3转换矩阵。即使经过改造,直线仍将保持直线。要找到这个转换矩阵,您需要输入图像上的4个点和输出图像上相应的点。在这4点中,有3点不应是共线的。然后通过函数求出变换矩阵。cv2.getPerspectiveTransform。然后申请cv2.warpPerspective用这个3x3变换矩阵。

见以下代码:

img = cv2.imread('sudokusmall.png')
rows,cols,ch = img.shape

pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img,M,(300,300))

plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

结果:

猜你喜欢

转载自blog.csdn.net/rongpeisheng666/article/details/81607315