畸變矯正
注意:雖然能夠成功矯正但是也會損失了部分圖像!
透視變換(Perspective Transformation)
概念:
透視變換是將圖片投影到一個新的視平面(Viewing Plane),也稱作投影映射(Projective Mapping)。 我們常說的仿射變換是透視變換的一個特例。 透視變換的目的就是把現實中為直線的物體,在圖片上可能呈現為斜線,通過透視變換轉換成直線 的變換。 仿射變換(Affine Transformation或 Affine Map),又稱為仿射映射,是指在幾何中,圖像進行從 一個向量空間進行一次線性變換和一次平移,變換為到另一個向量空間的過程。
思想:
通用的變換公式為:
x,y是原始圖片坐標,對應得到變換后的圖片坐標(X’;Y’;Z’)其中:
可以看作原圖像的數據各值與變換后圖像的數據各值,對應相等。
令a33=1,展開上面公式,得到一個點的情況:
如果我們要解出上面含有8個未知量(a)的方程,我們需要8個像素點,原圖像4個,新圖像4個。
源點四個坐標分別為A:(x0,y0),(x1,y1),(x2,y2),(x3,y3) 目標點四個坐標分別為B:(X’0,Y’0),(X’1,Y’1),(X’2,Y’2),(X’3,Y’3)
手動代碼實現:
import numpy as npdef WarpPerspectiveMatrix(src, dst):assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4#assert:當src的格式等于dst的格式,并且src的格式大于等于4,程序才繼續運行nums = src.shape[0]A = np.zeros((2*nums, 8)) # A*warpMatrix=BB = np.zeros((2*nums, 1))for i in range(0, nums):A_i = src[i,:]B_i = dst[i,:]A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0,-A_i[0]*B_i[0], -A_i[1]*B_i[0]]B[2*i] = B_i[0]A[2*i+1, :] = [0, 0, 0, A_i[0], A_i[1], 1,-A_i[0]*B_i[1], -A_i[1]*B_i[1]]B[2*i+1] = B_i[1]A = np.mat(A)#用A.I求出A的逆矩陣,然后與B相乘,求出warpMatrixwarpMatrix = A.I * B #求出a_11, a_12, a_13, a_21, a_22, a_23, a_31, a_32#之后為結果的后處理warpMatrix = np.array(warpMatrix).T[0]warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0) #插入a_33 = 1warpMatrix = warpMatrix.reshape((3, 3))return warpMatrixif __name__ == '__main__':print('warpMatrix')src = [[10.0, 457.0], [395.0, 291.0], [624.0, 291.0], [1000.0, 457.0]] #編造的輸入src = np.array(src)dst = [[46.0, 920.0], [46.0, 100.0], [600.0, 100.0], [600.0, 920.0]] #編造的輸出dst = np.array(dst)warpMatrix = WarpPerspectiveMatrix(src, dst)print(warpMatrix)
這里就不展示結果了 重點是思想
opencv接口代碼實現:
import cv2
import numpy as npimg = cv2.imread('photo1.jpg')result3 = img.copy()#img = cv2.GaussianBlur(img,(3,3),0)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#轉灰度,做單通道計算比較節省時間
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#canny邊緣檢測(僅針對這次的輸入圖片)
cv2.imshow("canny", edges)'''
注意這里src和dst的輸入并不是圖像,而是圖像對應的頂點坐標。
'''
src = np.float32([[207, 151], [517, 285], [17, 601], [343, 731]])
dst = np.float32([[0, 0], [337, 0], [0, 488], [337, 488]])
# 生成透視變換矩陣;進行透視變換
m = cv2.getPerspectiveTransform(src, dst)
result = cv2.warpPerspective(result3, m, (337, 488))
# (337,488)是輸出圖像大小
cv2.imshow("src", img)
cv2.imshow("result", result)
cv2.waitKey(0)
結果展示:
分別是:輸入圖片,邊緣提取,透視變換結果
成功將其原圖片中紙片矯正~
但是注意:雖然成功矯正但是也損失了部分圖像!