1. 程式人生 > 其它 >Python-幾何變換

Python-幾何變換

OpenCV提供了兩個變換函式,cv2.warpAffine和cv2.warpPerspective, 使用這兩個函式你可以實現所有型別的變換。cv2.warpAffine 接收的引數是 2×3 的變換矩陣,而 cv2.warpPerspective 接收的引數是 3×3 的變換矩 陣。

擴充套件縮放

擴充套件縮放只是改變影象的尺寸大小。OpenCV提供的函式cv2.resize()可以實現這個功能。影象的尺寸可以自己手動設定,你也可以指定縮放因子。我們可以選擇使用不同的插值方法。在縮放時我們推薦使用cv2.INTER_AREA,在擴充套件時我們推薦使用cv2.INTER_CUBIC(慢)和 cv2.INTER_LINEAR。預設情況下所有改變影象尺寸大小的操作使用的插值方法都是cv2.INTER_LINEAR。 你可以使用下面任意一種方法改變影象的尺寸:

import cv2
import numpy as np

from PIL import Image

img = cv2.imread("1.jpg")
# 下面的None本應該是輸出影象的尺寸,但是因為後邊我們設定了縮放因子
# 因此這裡為None
res=cv2.resize(img,None,fx=0.5,fy=0.5,interpolation=cv2.INTER_CUBIC)

#這裡呢,我們直接設定輸出影象的尺寸,所以不用設定縮放因子
height,width=img.shape[:2]
res1=cv2.resize(img,(int(0.5*width),int(0.5*height)),interpolation=cv2.INTER_CUBIC)

cv2.imshow('res',res)
cv2.imshow('res1',res1)
cv2.waitKey(0)
cv2.destroyAllWindows()

平移

平移就是將物件換一個位置。如果你要沿(x,y)方向移動,移動的距離 是(tx,ty),你可以以下面的方式構建移動矩陣:

你可以使用 Numpy 陣列構建這個矩陣(資料型別是 np.float32),然 後把它傳給函式 cv2.warpAffine()。看看下面這個例子吧,它被移動了 (100,50)個畫素。

import cv2
import numpy as np

from PIL import Image

img = cv2.imread("1.jpg")

height,width=img.shape[:2]
mat_translation=np.float32([[1,0,20],[0,1,50]])#變換矩陣
#表示平移變換 20代表水平方向上的平移距離 50代表豎直方向上的平移距離
res=cv2.warpAffine(img,mat_translation,(width+20,height+50))

cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

旋轉

對一個影象旋轉角度 θ, 需要使用到下面形式的旋轉矩陣

但是 OpenCV 允許你在任意地方進行旋轉,但是旋轉矩陣的形式應該修改為

其中:

為了構建這個旋轉矩陣,OpenCV提供了一個函式:cv2.getRotationMatrix2D。

import cv2
import numpy as np

from PIL import Image

img = cv2.imread("1.jpg")

rows,cols=img.shape[:2]

#這裡的第一個引數為旋轉中心,第二個為旋轉角度,第三個為旋轉後的縮放因子

#可以通過設定旋轉中心,縮放因子,以及視窗大小來防止旋轉後超出邊界的問題

M=cv2.getRotationMatrix2D((cols/2,rows/2),90,0.5)

#第三個引數是輸出影象的尺寸中心

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

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

仿射變換

在仿射變換中,原圖中所有的平行線在結果影象中同樣平行。為了建立這個矩陣我們需要從原影象中找到三個點以及他們在輸出影象中的位置。然後 cv2.getAffineTransform 會建立一個 2x3 的矩陣,最後這個矩陣會被傳給 函式 cv2.warpAffine。

來看看下面的例子,以及我選擇的點(被標記為綠色的點)

import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image

img = cv2.imread("1.jpg")
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))

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

透視變換

對於視角變換,我們需要一個 3x3 變換矩陣。在變換前後直線還是直線。 要構建這個變換矩陣,你需要在輸入影象上找 4 個點,以及他們在輸出圖 像上對應的位置。這四個點中的任意三個都不能共線。這個變換矩陣可以有 函式 cv2.getPerspectiveTransform() 構建。然後把這個矩陣傳給函式 cv2.warpPerspective。

import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image

img = cv2.imread("1.jpg")
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))

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