Python - opencv (七) 透视变换

一.作用

透视变换是将图像从一个视平面投影到另外一个视平面的过程,所以透视变换也被称为投影映射(Projection Mapping)。我们知道在图像的仿射变换中需要变换矩阵是一个2x3的两维平面变换矩阵,而透视变换本质上空间立体三维变换,根据其次坐标方差,要把三维坐标投影到另外一个视平面,就需要一个完全不同的变换矩阵M,所以这个是透视变换跟OpenCV中几何仿射变换最大的不同。 

常用的应用场景如将放在桌面的文档用OCR得到其文字,需要进行透视变换把这张纸“放正”

二.原理

参考博客:https://blog.csdn.net/zhangjunp3/article/details/80036310

Python - opencv (七) 透视变换

u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中Python - opencv (七) 透视变换

变换矩阵Python - opencv (七) 透视变换产生透视,

所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

重写之前的变换公式可以得到:

 Python - opencv (七) 透视变换

所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:Python - opencv (七) 透视变换

根据变换公式得到:

Python - opencv (七) 透视变换 

定义几个辅助变量:

Python - opencv (七) 透视变换

都为0时变换平面与原来是平行的,可以得到:

 Python - opencv (七) 透视变换

不为0时,得到

 Python - opencv (七) 透视变换

求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。

Python - opencv (七) 透视变换

 

三.示例

原图,要把发票放正: 

Python - opencv (七) 透视变换

代码:

 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()

效果: 

Python - opencv (七) 透视变换

 

上一篇:day7.11


下一篇:数据分析数据探索