文章目錄
QQ:3020889729 小蔡
實現原理
毫無疑問,一個個圖像——本質就是一個個多維數組,它包含像素點的排布,以及像素點的信息。
既然多維數組,我們將圖像中前兩維度——對應行列,當作一個矩陣進行處理。
第一維——也就是對應着行;第二維——也就是對應着列。
舉例:將一個多維數組當作矩陣
[[1, 2, 3]
[4, 5, 6]
[7, 8, 9]]
這裏應該能明白:第一維的每一個元素是一個list,且等大,每一個list作爲一個行,list裏邊的元素——就一一對應着屬於列。
實現函數
opencv提供的矩陣(圖像)轉換函數有兩個:
cv.warpAffine()——對應23的矩陣轉換——可以實現平移和翻轉(反轉還需要一個cv.getRotationMatrix2D來獲取旋轉後的移動座標),以及仿射變換——getAffineTransform
cv.warpPerspective()——對應33的矩陣轉換——可以應用透射變換
以及一個圖像大小按比例修改的函數:cv.resize()
warpAffine——參數
- 參數一:輸入圖像
- 參數二:平移矩陣——list類型
- 參數三:輸出圖像大小(採用元組(寬值,高值))
- 參數四:bordermode——邊界值處理——控制輸出圖像與原圖像異常值是否處理,如何處理的參數
- 參數五:bordervalue邊界值——一般默認爲0不處理
- 說明——參數四五,在簡單應用中不涉及,這裏就不細講了,後邊會慢慢整理進階的。
平移時——你應該知道移動的x,y值,並滿足以上矩陣:(也就是把x,y值放在這個位置——創建這樣的矩陣採用numpy實現)——採用numpy.float32創建
getRotationMatrix2D——參數
opencv使用該函數實現了任一點旋轉的方法——並且返回一個warpAffine的平移參數矩陣(2*3)
- 參數一:旋轉中心位置座標(採用二元元組傳入)
- 參數二:旋轉角度——正值爲逆時針旋轉角度
- 參數三:縮放比例——一般不變傳入1即可
cv.getAffineTransform——參數
opencv使用該函數實現了通過取圖像三點以及變化後的對應位置,來實現變換的方法——並且返回一個warpAffine的平移參數矩陣(2*3)——實現仿射變換
- 參數一:變化前的三個點的矩陣——list類型採用numpy.float32創建
- 參數二:變化後的三個點的矩陣——list類型
warpPerspective——參數
cv.warpPerspective實現透射變換——所以需要對空間有一個座標——也就是對應着23到33矩陣變化的需要——當然實現透射變換還需要一個函數的幫助,來獲取這樣的移動參數矩陣
- 參數一:輸入圖像
- 參數二:移動(變換)參數
- 參數三:輸出圖像大小
- 參數四:插值方式
- 參數五六與warpAffine一樣,都是對變換的邊界進行處理的參數設置
cv.getPerspectiveTransform——參數
該函數爲透色變換提供移動參數——一個3*3的移動參數矩陣。
而這樣的參數,來源於原圖像中的4個點座標,以及設置的改變後對應的座標
- 參數一:原圖像四個座標——list類型採用numpy.float32創建
- 參數二:變換後的座標——list類型
resize——參數
- 參數一:輸入圖像
- 參數二:輸出大小——設置輸出大小(二元元組)
- 參數三:x伸展比例——參數二有具體大小,不爲None時,x,y伸展不用填寫,是無效的
- 參數四:y伸展比例——也就是說,選擇一種伸縮方式即可
- 參數五:插值
- 常見插值爲:
- cv.INTER_AREA——用於縮小
- cv.INTER_LINEAR——用於縮放(放大/縮小都可以)
- cv.INTER_CUBIC——用於低分辨率
代碼實例
縮放
這裏不要設置窗體可調——不然會顯示不出來伸縮變換的。
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/open_class.png')
# cv.namedWindow('imag', cv.WINDOW_NORMAL)
img_size_h, img_size_w = img.shape[:2] # 獲取形狀大小——即第一位爲行數,第二位爲列數
res = cv.resize(img, (img_size_w*1, img_size_h*3), interpolation=cv.INTER_CUBIC)
# 高度變爲3倍
# 除了這樣的操作外,還可以如此
# res = cv.resize(img, None, fx=1, fy=3, interpolation=cv.INTER_CUBIC)
cv.imshow('imag', res)
cv.waitKey(0)
cv.destroyAllWindows()
效果:伸縮變換前
伸縮變換後
平移
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/open_class.png')
img_size_h, img_size_w = img.shape[:2] # 獲取形狀大小——即第一位爲行數,第二位爲列數
move_value = np.float32([[1, 0, 66], [0, 1, 66]]) # 前面的公式可知:這裏是移動x = 66, y = 66
res = cv.warpAffine(img, move_value, (img_size_w, img_size_h))
cv.imshow('imag', res)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
翻轉(或者說叫做2D平移旋轉)
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/open_class.png')
# cv.namedWindow('imag', cv.WINDOW_NORMAL)
img_size_h, img_size_w = img.shape[:2] # 獲取形狀大小——即第一位爲行數,第二位爲列數
move_value = cv.getRotationMatrix2D((img_size_w/2.0, img_size_h/2.0), 90, 1) # 獲取旋轉後的移動座標矩陣
res = cv.warpAffine(img, move_value, (img_size_w, img_size_h)) # 實現平移旋轉
cv.imshow('imag', res)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
仿射變換
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/open_class.png')
img_size_h, img_size_w = img.shape[:2] # 獲取形狀大小——即第一位爲行數,第二位爲列數
pst1 = np.float32([[20, 30], [50, 100], [100, 100]]) # 原圖像的點座標
pst2 = np.float32([[40, 30], [50, 100], [80, 120]]) # 原點一一對應的變換點座標
move_value = cv.getAffineTransform(pst1, pst2) # 獲取仿射變換的平移座標
res = cv.warpAffine(img, move_value, (img_size_w, img_size_h)) # 實現平移——得到仿射變換的圖形
cv.imshow('res_imag', res) # 顯示變化後的圖形
cv.imshow('imag', img) # 顯示原圖形
cv.waitKey(0)
cv.destroyAllWindows()
效果:
投射變換(可以用來解決拍攝的圖形不平整進行平整變化的轉換)
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/open_class.png')
img_size_h, img_size_w = img.shape[:2] # 獲取形狀大小——即第一位爲行數,第二位爲列數
pst1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]]) # 需要四個點座標_要求三個點不共線,# 將四點間內容作爲顯示內容
pst2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]]) # 四點的座標變化
move_value = cv.getPerspectiveTransform(pst1, pst2) # 獲取投射變換的平移座標
res = cv.warpPerspective(img, move_value, (300, 300)) # 獲取投射變換的圖形——大小盡量與變化後的四點座標等大寬度
cv.imshow('res_imag', res)
cv.imshow('imag', img)
cv.waitKey(0)
cv.destroyAllWindows()
效果:操作前後——如果圖形是2d平整的,可能就會編程內凹或者其它的一些畸變。
以下圖形實現通過透視變換,得到更平整的圖像
視角變淺
**我的效果:**確實有透視的視角變深等變化