1. 程式人生 > 其它 >Python - opencv (七) 透視變換

Python - opencv (七) 透視變換

一.作用

透視變換是將影象從一個視平面投影到另外一個視平面的過程,所以透視變換也被稱為投影對映(Projection Mapping)。我們知道在影象的仿射變換中需要變換矩陣是一個2x3的兩維平面變換矩陣,而透視變換本質上空間立體三維變換,根據其次座標方差,要把三維座標投影到另外一個視平面,就需要一個完全不同的變換矩陣M,所以這個是透視變換跟OpenCV中幾何仿射變換最大的不同。

常用的應用場景如將放在桌面的文件用OCR得到其文字,需要進行透視變換把這張紙“放正”

二.原理

參考部落格:https://blog.csdn.net/zhangjunp3/article/details/80036310

u,v是原始圖片左邊,對應得到變換後的圖片座標x,y,其中。

變換矩陣可以分作四部分來理解,表示線性變換,表示平移,產生透視,

所以可以理解成仿射等是透視變換的特殊形式。經過透視變換之後的圖片通常不是平行四邊形(除非對映視平面和原來平面平行的情況)。

重寫之前的變換公式可以得到:

所以,已知變換對應的幾個點就可以求取變換公式。反之,特定的變換公式也能新的變換後的圖片。簡單的看一個正方形到四邊形的變換:

根據變換公式得到:

定義幾個輔助變數:

都為0時變換平面與原來是平行的,可以得到:

不為0時,得到

求解出的變換矩陣就可以將一個正方形變換到四邊形。反之,四邊形變換到正方形也是一樣的。於是,我們通過兩次變換:四邊形變換到正方形+正方形變換到四邊形就可以將任意一個四邊形變換到另一個四邊形。

三.示例

原圖,要把發票放正:

程式碼:

 1 import cv2
 2 import matplotlib.pyplot as plt
 3 import numpy as np
 4 
 5 if __name__ == '__main__':
 6     img = cv2.imread('../pics/10.png', 0)
 7     img = cv2.GaussianBlur(img, (5, 5), 0)
 8 
 9     edge = cv2.Canny(img, 40, 180)
10     contours, hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
11 12 tmp = np.zeros(img.shape, np.uint8) 13 draw_cnt = [] 14 arcs = [] 15 for c in contours: 16 arc = cv2.arcLength(c, False) 17 arcs.append(arc) 18 19 draw_cnt.append(contours[arcs.index(max(arcs))]) 20 cv2.drawContours(tmp, draw_cnt, -1, (250, 255, 255), 2) 21 22 approx = cv2.approxPolyDP(draw_cnt[0], 10, True) # 近似多邊形,10為精度,調這個引數使邊數為4 23 24 approx_point1 = approx.reshape(4, 2).astype(np.float32) 25 26 plane = np.array([[0, 0], [0, 600], [400, 600], [400, 0]], dtype="float32") # 投影到400*600的面上 27 28 M = cv2.getPerspectiveTransform(approx_point1, plane) 29 out_img = cv2.warpPerspective(img, M, (400, 600)) 30 dst = cv2.perspectiveTransform(plane.reshape(1, 4, 2), M) 31 32 transformed = cv2.resize(out_img, (400, 600)) 33 34 cv2.imshow('edge', transformed) 35 36 cv2.waitKey()

效果: