1 仿射變換與透視變換
1.1 仿射變換
之前在圖像旋轉實驗中已經接觸過仿射變換,仿射變換是一個二維坐標系到另一個二維坐標系的過程,在仿射變換中符合直線的平直性和平行性。
1.2 透視變換
透視變換是把一個圖像投影到一個新的視平面的過程。在現實世界中,觀察到的物體在人類視覺中都會受到透視效果的影響:近大遠小。通俗的講,透視變換的作用是改變物體被觀察的視角。
實際開發中判斷是否是透視變換的方法非常簡單:只要是攝像頭拍攝出的畫面都是符合透視變換。
1.3?透視變換矩陣
與仿射變換相同,透視變換也有對應的透視變換矩陣,在這個過程原始圖像src中的點(x,y)通過透視變換被轉換到到dst圖像中的新坐標點(x',y')
代碼運行步驟:
圖片輸入→坐標選取→獲取透視變換矩陣→透視變換→插值方法→邊緣填充→圖片輸出
原始圖片:4.jpg
import cv2 # 導入OpenCV庫,用于計算機視覺任務
import numpy as np # 導入NumPy庫,用于數值計算和數組操作
import matplotlib.pyplot as pltif __name__ == '__main__':# 1. 圖片輸入path = '4.jpg' # 定義圖片路徑image_np = cv2.imread(path) # 讀取圖片,返回NumPy數組格式的圖像數據# 2. 坐標選取# 左上、右上、左下、右下points = [[171, 5], [271, 105], [27, 150], [127, 248]]# 轉換為np數組pts1 = np.float32(points) # src的四個角點:將點列表轉換為NumPy數組,數據類型為32位浮點數print(pts1) # 打印點坐標print(type(pts1)) # 打印數據類型# 畫紅框,標記ROI區域image_line = image_np.copy() # 創建原圖的副本,避免修改原圖# 畫四條線,標記出要校正的區域cv2.line(image_line, # 在哪個圖像上畫線points[0], # 起點points[1], # 終點(0, 0, 255), # 顏色(B,G,R格式),這里是紅色2, # 線條粗細cv2.LINE_AA # 抗鋸齒線型,使線條更平滑)# 重復畫線操作,連接其他點形成四邊形cv2.line(image_line, points[1], points[3], (0, 0, 255), 2, cv2.LINE_AA)cv2.line(image_line, points[2], points[3], (0, 0, 255), 2, cv2.LINE_AA)cv2.line(image_line, points[0], points[2], (0, 0, 255), 2, cv2.LINE_AA)# 3. 獲取透視變換矩陣# 獲得原圖分辨率,這個原圖分辨率是后面定義矯正后的圖片分辨率大小。# img_shape = image_np.shape # 獲取圖像形狀(高度, 寬度, 通道數)# print("原圖分辨率:", img_shape)img_shape = (260, 170, 3) # 可自行定義圖像形狀(高度, 寬度, 通道數)# 定義目標點:左上、右上、左下、右下 - 對應整個圖像的四個角points = [[0, 0], [img_shape[1], 0], [0, img_shape[0]], [img_shape[1], img_shape[0]]]print(points) # 打印目標點坐標# 轉換為np數組pts2 = np.float32(points) # dst的四個角點:將目標點轉換為NumPy數組# 生成透視變換矩陣M = cv2.getPerspectiveTransform(pts1, # src的四個角點: 源圖像的四個角點(要校正的區域)pts2 # dst的四個角點: 源圖像的四個角點(要校正的區域))print(M) # 打印透視變換矩陣# 4. 透視變換 + 5. 插值方法 + 6. 邊緣填充correct_image = cv2.warpPerspective(image_np, # 原圖M, # 透視變換矩陣(img_shape[1], img_shape[0]), # dst分辨率:輸出圖像尺寸(寬度, 高度)cv2.INTER_LINEAR, # 插值方法:雙線性插值,平衡速度和質量cv2.BORDER_WRAP # 邊緣填充:邊緣像素環繞)# 使用matplotlib手動去看要截取的x,y的數組參數q = plt.imread(path)plt.imshow(q)plt.axis('off') # 取消坐標軸顯示plt.show()# 7. 圖片輸出cv2.imshow('image_line', image_line) # 顯示帶有標記線的圖像cv2.imshow('correct_image', correct_image) # 顯示校正后的圖像cv2.waitKey(0) # 等待鍵盤輸入,0表示無限等待cv2.imwrite('jz.png', correct_image)
運行結果: