单应性变换之图像矫正

在日常生活中经常会遇到因为拍摄时拍的不好,导致拍出来的图片歪歪扭扭的,为此需要用到图像矫正技术。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import cv2 as cv 
import imutils
import numpy as np

def find_fourpoints(grayImage):
# 寻找轮廓
gaussImage = cv.GaussianBlur(grayImage, (5, 5), 0)
edgedImage = cv.Canny(gaussImage, 75, 200)
cnts, hierarchy = cv.findContours(edgedImage.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
# 找最符合的轮廓
cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:5]
for c in cnts:
peri = cv.arcLength(c, True) # 计算轮廓周长
approx = cv.approxPolyDP(c, 0.02 * peri, True) # 多边形拟合

if len(approx) == 4:
screenCnt = approx.reshape(4, 2)
break

# 顶点重排序
rect = np.zeros((4,2), dtype = "float32")
s = np.sum(screenCnt, axis = 1)
rect[0] = screenCnt[np.argmin(s)]
rect[2] = screenCnt[np.argmax(s)]
diff = np.diff(screenCnt, axis = 1)
rect[1] = screenCnt[np.argmin(diff)]
rect[3] = screenCnt[np.argmax(diff)]

return rect

def warp(image, rect):
(tl, tr, br, bl) = rect

widthA = np.sqrt((tr[0] - tl[0]) ** 2 + (tr[1] - tl[1]) ** 2)
widthB = np.sqrt((br[0] - bl[0]) ** 2 + (br[1] - bl[1]) ** 2)
maxWidth = max(int(widthA), int(widthB))

heightA = np.sqrt((tr[0] - br[0]) ** 2 + (tr[1] - br[1]) ** 2)
heightB = np.sqrt((tl[0] - bl[0]) ** 2 + (tl[1] - bl[1]) ** 2)
maxHeight = max(int(heightA), int(heightB))

dst = np.array([[0,0],
[maxWidth - 1, 0],
[maxWidth -1, maxHeight -1],
[0, maxHeight -1]], dtype = "float32")

# H = cv.getPerspectiveTransform(rect, dst)
H, mask = cv.findHomography(rect, dst, cv.RANSAC, 5.0)
warped = cv.warpPerspective(image, H, (maxWidth, maxHeight))

return warped

if __name__ == "__main__":
# 导入资源
image = cv.imread("book.jpg")
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)

# 寻找四顶点
fourpoints = find_fourpoints(gray)
# 校正后的图像
warpedImage = warp(image, fourpoints)

cv.imshow("org", imutils.resize(image, height=500))
cv.imshow("warped", imutils.resize(warpedImage, height=500))
cv.waitKey(0)
cv.destroyAllWindows()

1.png

2.png

0%