Python影象處理丨帶你掌握影象幾何變換
摘要:本篇文章主要講解影象仿射變換和影象透視變換,通過Python呼叫OpenCV函式實。
本文分享自華為雲社群《[Python影象處理] 十二.影象幾何變換之影象仿射變換、影象透視變換和影象校正》,作者: eastmount 。
一.影象仿射變換
影象仿射變換又稱為影象仿射對映,是指在幾何中,一個向量空間進行一次線性變換並接上一個平移,變換為另一個向量空間。通常影象的旋轉加上拉昇就是影象仿射變換,仿射變換需要一個M矩陣實現,但是由於仿射變換比較複雜,很難找到這個M矩陣.
OpenCV提供了根據變換前後三個點的對應關係來自動求解M的函式——cv2.getAffineTransform(pos1,pos2),其中pos1和pos2表示變換前後的對應位置關係,輸出的結果為仿射矩陣M,接著使用函式cv2.warpAffine()實現影象仿射變換。圖5-14是仿射變換的前後效果圖。
影象仿射變換的函式原型如下:
M = cv2.getAffineTransform(pos1,pos2)
- pos1表示變換前的位置
- pos2表示變換後的位置
cv2.warpAffine(src, M, (cols, rows))
- src表示原始影象
- M表示仿射變換矩陣
- (rows,cols)表示變換後的影象大小,rows表示行數,cols表示列數
實現程式碼如下所示:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取圖片
src = cv2.imread('test.bmp')
#獲取影象大小
rows, cols = src.shape[:2]
#設定影象仿射變換矩陣
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)
#影象仿射變換
result = cv2.warpAffine(src, M, (cols, rows))
#顯示影象
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()
輸出效果圖如下所示:
二.影象透視變換
影象透視變換(Perspective Transformation)的本質是將影象投影到一個新的視平面,同理OpenCV通過函式cv2.getPerspectiveTransform(pos1,pos2)構造矩陣M,其中pos1和pos2分別表示變換前後的4個點對應位置。得到M後在通過函式cv2.warpPerspective(src,M,(cols,rows))進行透視變換。
影象透視變換的函式原型如下:
M = cv2.getPerspectiveTransform(pos1, pos2)
- pos1表示透視變換前的4個點對應位置
- pos2表示透視變換後的4個點對應位置
cv2.warpPerspective(src,M,(cols,rows))
- src表示原始影象
- M表示透視變換矩陣
- (rows,cols)表示變換後的影象大小,rows表示行數,cols表示列數
程式碼如下:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取圖片
src = cv2.imread('test01.jpg')
#獲取影象大小
rows, cols = src.shape[:2]
#設定影象透視變換矩陣
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#影象透視變換
result = cv2.warpPerspective(src, M, (190, 272))
#顯示影象
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()
輸出結果如下圖所示:
三.基於影象透視變換的影象校正
下面參考 t6_17大神 的文章,通過影象透視變換實現影象校正功能。
假設現在存在一張A4紙影象,現在需要通過呼叫影象透視變換校正影象。
程式碼如下所示:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取圖片
src = cv2.imread('test01.jpg')
#獲取影象大小
rows, cols = src.shape[:2]
#將源影象高斯模糊
img = cv2.GaussianBlur(src, (3,3), 0)
#進行灰度化處理
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#邊緣檢測(檢測出影象的邊緣資訊)
edges = cv2.Canny(gray,50,250,apertureSize = 3)
cv2.imwrite("canny.jpg", edges)
#通過霍夫變換得到A4紙邊緣
lines = cv2.HoughLinesP(edges,1,np.pi/180,50,minLineLength=90,maxLineGap=10)
#下面輸出的四個點分別為四個頂點
for x1,y1,x2,y2 in lines[0]:
print(x1,y1),(x2,y2)
for x1,y1,x2,y2 in lines[1]:
print(x1,y1),(x2,y2)
#繪製邊緣
for x1,y1,x2,y2 in lines[0]:
cv2.line(gray, (x1,y1), (x2,y2), (0,0,255), 1)
#根據四個頂點設定影象透視變換矩陣
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#影象透視變換
result = cv2.warpPerspective(src, M, (190, 272))
#顯示影象
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()
執行結果如下圖所示:
四.影象幾何變換總結
最後補充影象幾何程式碼所有變換,希望讀者能體會下相關的程式碼,並動手實踐下。輸出結果以女神為例:
完整程式碼如下:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取圖片
img = cv2.imread('test3.jpg')
image = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#影象平移矩陣
M = np.float32([[1, 0, 80], [0, 1, 30]])
rows, cols = image.shape[:2]
img1 = cv2.warpAffine(image, M, (cols, rows))
#影象縮小
img2 = cv2.resize(image, (200,100))
#影象放大
img3 = cv2.resize(image, None, fx=1.1, fy=1.1)
#繞影象的中心旋轉
#源影象的高、寬 以及通道數
rows, cols, channel = image.shape
#函式引數:旋轉中心 旋轉度數 scale
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
#函式引數:原始影象 旋轉引數 元素影象寬高
img4 = cv2.warpAffine(image, M, (cols, rows))
#影象翻轉
img5 = cv2.flip(image, 0) #引數=0以X軸為對稱軸翻轉
img6 = cv2.flip(image, 1) #引數>0以Y軸為對稱軸翻轉
#影象的仿射
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
img7 = cv2.warpAffine(image, M, (rows,cols))
#影象的透射
pts1 = np.float32([[56,65],[238,52],[28,237],[239,240]])
pts2 = np.float32([[0,0],[200,0],[0,200],[200,200]])
M = cv2.getPerspectiveTransform(pts1,pts2)
img8 = cv2.warpPerspective(image,M,(200,200))
#迴圈顯示圖形
titles = [ 'source', 'shift', 'reduction', 'enlarge', 'rotation', 'flipX', 'flipY', 'affine', 'transmission']
images = [image, img1, img2, img3, img4, img5, img6, img7, img8]
for i in xrange(9):
plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
- Serverless遇到 FinOps: Economical Serverless
- 各行各業都在關注的“密評”到底是啥?一文帶你讀懂!
- VS Code摸魚神器,讓你快速開發AI模型
- 分散式系統中如何實現臨界資源的互斥訪問?
- 帶你瞭解CANN的目標檢測與識別一站式方案
- 一文了解迴圈神經網路
- 跟我學Python影象處理丨關於影象金字塔的影象向下取樣和向上取樣
- 帶你掌握如何使用CANN 運算元ST測試工具msopst
- 編譯器優化:何為別名分析
- 一招教你如何高效批量匯入與更新資料
- 【火熱招募】一文看懂華為雲IoT Edge邊緣計算開發者大賽技術亮點
- 天天寫SQL,這些神奇的特性你知道嗎?
- 一文了解 Java 中的構造器
- 基於 PyTorch 和神經網路給 GirlFriend 製作漫畫風頭像
- Python影象處理丨帶你認識影象量化處理及區域性馬賽克特效
- 基於 PyTorch 和神經網路給 GirlFriend 製作漫畫風頭像
- 詳解KubeEdge邊緣網路專案EdgeMesh
- VLDB'22 HiEngine極致RTO論文解讀
- 推理網路精度不達標,5個方法輕鬆搞定
- 強擴充套件、強一致、高可用…GaussDB成為遊戲行業的心頭愛