opencv-python 4.2图像的几何变化

发布时间 2023-03-28 14:47:02作者: 一枚码农

转换

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

缩放

缩放只是调整图像大小,OpenCV有一个函数cv.resize(),可以手动指定图像的大小以及缩放系数,可以使用不同的插值方法,常用的插值方法是用于缩小的cv.INTER_AREA和用于缩放的cv.INTER_CUBIC(慢)和cv.INTER_LINEAR。默认情况下,使用的插值方法是cv.INTER_LINEAR,它用于所有调整大小的操作。你可以使用以下方法之一调整输入图像的大小:

import cv2 as cv

img = cv.imread(r'C:\\Users\\yuyalong\\Pictures\\Camera Roll\\15.jpg')
cv.imshow('img', img)

# 图像缩放一半
res = cv.resize(img, None, fx=0.5, fy=0.5, interpolation=cv.INTER_CUBIC)
cv.imshow('res', res)

# 图像扩大两倍 这种方法与上边的一样,但是这种方法宽高的系数必须是整数
height, width = img.shape[:2]
res1 = cv.resize(img, (2 * width, 2 * height), interpolation=cv.INTER_CUBIC)
cv.imshow('res1', res1)

cv.waitKey(0)
cv.destroyAllWindows()

平移

平移是对象位置的移动。如果你知道像素点(x,y)要位移的距离,让它为变为($$ t_x $$,$$ t_y $$),你可以创建变换矩阵M,如下所示:

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

可以将其设置为np.float32类型的Numpy数组,并将其传递给cv.warpAffine()函数。下面的示例演示图像像素点整体进行(200,100)位移:

import cv2 as cv
import numpy as np

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\dog.jpg', 0)
rows, cols = img.shape

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

cv.imshow('img', img)
cv.imshow('dst', dst)

cv.waitKey(0)
cv.destroyAllWindows()

注意:cv.warpAffine()函数的第三个参数是输出图像的大小,它应该是(宽,高)的形式, width=列数,height=行数。

image

旋转

通过改变图像矩阵实现图像旋转角度θ
$$ M=\begin{bmatrix} cos\Theta &-sin\Theta\ sin\Theta & cos\Theta \end{bmatrix} $$

OpenCV提供了可调旋转中心的缩放旋转,这样你可以在你喜欢的任何位置进行旋转。修正的变换矩阵由下式给出:
$$ \begin{bmatrix} \alpha & \beta & \left ( 1-\alpha \right )\cdot center.x-\beta \cdot center.y \ -\beta & \alpha & \beta \cdot center.x\left ( 1-\alpha \right )\cdot center.y \end{bmatrix} $$

其中:
$$ \alpha = scale\cdot cos\Theta $$
$$ \beta = scale\cdot sin\Theta $$
为了找到这个转换矩阵,OpenCV提供了一个函数cv.getRotationMatrix2D。

以下示例将图像相对于中心旋转90度并缩放0.5倍。

import cv2 as cv
import numpy as np

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\dog.jpg', 0)
rows, cols = img.shape

M = cv.getRotationMatrix2D((cols / 2, rows / 2), 90, 0.5)
dst = cv.warpAffine(img, M, (cols, rows))

cv.imshow('img', img)
cv.imshow('dst', dst)

cv.waitKey(0)
cv.destroyAllWindows()

image

仿射变换

http://math.itdiffer.com/affine.html
在仿射变换中,原始图像中的所有平行线在输出图像中依旧平行。为了找到变换矩阵,我们需要从输入图像中得到三个点,以及它们在输出图像中的对应位置。然后cv.getAffineTransform将创建一个2x3矩阵,最后该矩阵将传递给cv.warpAffine。

import cv2 as cv
import numpy as np

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\drawing.jpg', 0)
rows, cols = img.shape

pts1 = np.float32([[50, 50], [200, 50], [100, 150]])
pts2 = np.float32([[10, 100], [200, 50], [100, 150]])
pts3 = np.float32([[50, 50], [40, 100], [100, 150]])
pts4 = np.float32([[50, 50], [200, 50], [20, 250]])

M = cv.getAffineTransform(pts1, pts2)
M1 = cv.getAffineTransform(pts1, pts3)
M2 = cv.getAffineTransform(pts1, pts4)

dst = cv.warpAffine(img, M, (cols, rows))
dst1 = cv.warpAffine(img, M1, (cols, rows))
dst2 = cv.warpAffine(img, M2, (cols, rows))

cv.imshow('img', img)
cv.imshow('dst', dst)
cv.imshow('dst1', dst1)
cv.imshow('dst2', dst2)

cv.waitKey(0)
cv.destroyAllWindows()

image

透视变换

https://blog.csdn.net/sinat_29957455/article/details/104281693
对于透视变换,需要一个3x3变换矩阵。即使在转换之后,直线仍是直线。要找到此变换矩阵,需要在输入图像上找4个点,以及它们在输出图像中的对应位置。在这4个点中,其中任意3个不共线。然后可以通过函数cv.getPerspectiveTransform找到变换矩阵,将cv.warpPerspective应用于此3x3变换矩阵。

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

img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\drawing.jpg')
rows, cols, ch = img.shape

pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[50, 50], [100, 150], [200, 50], [250, 200]])
#
M = cv.getPerspectiveTransform(pts1, pts2)

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

cv.imshow('img', img)
cv.imshow('dst', dst)

cv.waitKey(0)
cv.destroyAllWindows()

image