变换

opencv提供了两个转换函数cv.warpAffine和cv.warpPersective,可以使用它们进行各种转换。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('./images/lena.jpeg')
# 缩小
img_small1=cv.resize(img,None,fx=0.5,fy=0.5,interpolation=cv.INTER_AREA)
height,width=img.shape[:2]
img_small2=cv.resize(img,(int(0.5*width),int(0.5*height)),interpolation=cv.INTER_AREA)
# 放大
img_big1=cv.resize(img,None,fx=2,fy=2,interpolation=cv.INTER_CUBIC)
img_big2=cv.resize(img,(2*width,2*height),interpolation=cv.INTER_CUBIC)
print(img.shape) # (256, 256, 3)
print(img_small1.shape) # (128, 128, 3)
print(img_small2.shape) # (128, 128, 3)
print(img_big1.shape) # (512, 512, 3)
print(img_big2.shape) # (512, 512, 3)

cv.imshow('img',img)
cv.imshow('img_small1',img_small1)
cv.imshow('img_small2',img_small2)
cv.imshow('img_big1',img_big1)
cv.imshow('img_big2',img_big2)

cv.waitKey(0)
cv.destroyAllWindows()

平移

如果想要沿(x,y)方向移动,移动的距离为(tx,ty),可以以下面方式构建移动矩阵。

 可以使用Numpy数组构建矩阵,数据类型为np.float32,然后传给函数cv.warpAffine(),函数的第三个参数是输出图像的大小,它的格式应该是图像的(宽,高)。应该记住的是图像的宽对应的是列数,高对应的是行数。

import numpy as np
import cv2 as cv

img=cv.imread('./images/lena.jpeg')
rows,cols=img.shape[:2]
# 设置移动矩阵
M=np.array([[1,0,100],[0,1,50]],dtype=np.float32)
dst=cv.warpAffine(img,M,(cols,rows))
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

旋转

图像旋转角度为θ是通过以下的变换矩阵实现的:

 但opencv允许在任意地方进行旋转,所以矩阵为:

 其中α = scale · cos θ,β=scale·sin θ

为了找到此转换矩阵,opencv提供了一个函数cv.getRotationMatrix2D。

import cv2 as cv

img=cv.imread('./images/lena.jpeg')
rows,cols=img.shape[:2]
# 第一个参数为旋转中心,第二个参数为旋转角度,第三个为旋转后的缩放因子
# 可以通过设置旋转中心,缩放因子以及窗口大小来防止旋转后超出边界的问题
M=cv.getRotationMatrix2D((cols/2,rows/2),45,0.6)
dst=cv.warpAffine(img,M,(cols,rows))
while(1):
    cv.imshow('img',dst)
    if cv.waitKey(1)&0XFF==27:
        break
cv.destroyAllWindows()

仿射变换

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

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

img=cv.imread('./images/lena.jpeg')
img=img[:,:,[2,1,0]]
rows,cols,ch=img.shape
pts1=np.float32([[50,50],[200,50],[50,200]])
pts2=np.float32([[10,100],[200,50],[100,250]])
M=cv.getAffineTransform(pts1,pts2)
dst=cv.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个点,在输出图像上需要相应的点。在这四个点中,其中三个不应共线。然后可以通过函数cv.getPerspectiveTransform找到变换矩阵。然后将cv.warpPerspective应用于3x3转换矩阵。

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

img=cv.imread('./images/lena.jpeg')
print(img.shape)
img=img[:,:,[2,1,0]]
rows,cols,ch=img.shape
pts1=np.float32([[56,65],[26,52],[28,86],[239,130]])
pts2=np.float32([[0,0],[200,0],[0,230],[230,780]])
M=cv.getPerspectiveTransform(pts1,pts2)
dst=cv.warpPerspective(img,M,(cols,rows))
plt.subplot(121)
plt.imshow(img)
plt.title('input')
plt.subplot(122)
plt.imshow(dst)
plt.title('output')
plt.show()

 

 posted on 2024-05-02 20:06  会飞的金鱼  阅读(22)  评论(0)    收藏  举报