OpenCV實現相機校正
本文實例為大傢分享瞭OpenCV實現相機校正的具體代碼,供大傢參考,具體內容如下
1. 相機標定
根據張正友校正算法,利用棋盤格數據校正對車載相機進行校正,計算其內參矩陣,外參矩陣和畸變系數。
標定的流程是:
- 準備棋盤格數據,即用於標定的圖片
- 對每一張圖片提取角點信息
- 在棋盤上繪制提取到的角點(非必須,隻是為瞭顯示結果)
- 利用提取的角點對相機進行標定
- 獲取相機的參數信息
2.關於相機校正用到的幾個API:
1、尋找棋盤圖中的棋盤角點
rect, corners = cv2.findChessboardCorners(image, pattern_size, flags)
參數:
- Image: 輸入的棋盤圖,必須是8位的灰度或者彩色圖像
- Pattern_size:棋盤圖中每行每列的角點個數(內角點)。
- flags: 用來定義額外的濾波步驟以有助於尋找棋盤角點。所有的變量都可以單獨或者以邏輯或的方式組合使用。取值主要有:
CV_CALIB_CB_ADAPTIVE_THRESH :使用自適應閾值(通過平均圖像亮度計算得到)將圖像轉換為黑白圖,而不是一個固定的閾值。
CV_CALIB_CB_NORMALIZE_IMAGE :在利用固定閾值或者自適應的閾值進行二值化之前,先使用cvNormalizeHist來均衡化圖像亮度。
CV_CALIB_CB_FILTER_QUADS :使用其他的準則(如輪廓面積,周長,方形形狀)來去除在輪廓檢測階段檢測到的錯誤方塊。
返回:
- Corners:檢測到的角點
- rect: 輸出是否找到角點,找到角點返回1,否則返回0
2、檢測完角點之後可以將測到的角點繪制在圖像上,使用的API是:
cv2.drawChessboardCorners(img, pattern_size, corners, rect)
參數:
- Img: 預繪制檢測角點的圖像
- pattern_size : 預繪制的角點的形狀
- corners: 角點矩陣
- rect: 表示是否所有的棋盤角點被找到,可以設置為findChessboardCorners的返回值
註意:如果發現瞭所有的角點,那麼角點將用不同顏色繪制(每行使用單獨的顏色繪制),並且把角點以一定順序用線連接起來。
3、利用定標的結果計算內外參數
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, image_size, None, None)
參數:
- Object_points:世界坐標系中的點,在使用棋盤的場合,令z的坐標值為0,而x,y坐標用裡面來度量,選用英寸單位,那麼所有參數計算的結果也是用英寸表示。最簡單的方式是定義棋盤的每一個方塊為一個單位。
- image_points:在圖像中尋找到的角點的坐標,包含object_points所提供的所有點
- image_size: 圖像的大小,以像素為衡量單位
返回:
- ret: 返回值
- mtx: 相機的內參矩陣,大小為3*3的矩陣
- dist: 畸變系數,為5*1大小的矢量
- rvecs: 旋轉變量
- tvecs: 平移變量
2.1 圖像去畸變
上一步中得到相機的內參及畸變系數,利用其進行圖像的去畸變,最直接的方法就是調用opencv中的函數得到去畸變的圖像:
def img_undistort(img, mtx, dist): dst = cv2.undistort(img, mtx, dist, None, mtx) return dst
求畸變的API:
dst = cv2.undistort(img, mtx, dist, None, mtx)
參數:
- Img: 要進行校正的圖像
- mtx: 相機的內參
- dist: 相機的畸變系數
返回:
- dst: 圖像校正後的結果
3. 相機校正
import cv2 import numpy as np import matplotlib.pyplot as plt import matplotlib.image as mpimg import glob def plot_contrast_imgs(origin_img, converted_img, origin_img_title="origin_img", converted_img_title="converted_img", converted_img_gray=False): """ 用於對比顯示兩幅圖像 """ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 20)) ax1.set_title(origin_img_title) ax1.imshow(origin_img) ax2.set_title(converted_img_title) if converted_img_gray==True: ax2.imshow(converted_img, cmap="gray") else: ax2.imshow(converted_img) plt.show() # 1. 參數設定:定義棋盤橫向和縱向的角點個數並指定校正圖像的位置 nx = 9 ny = 6 file_paths = glob.glob("./camera_cal/calibration*.jpg") # 2. 計算相機的內外參數及畸變系數 def cal_calibrate_params(file_paths): object_points = [] # 三維空間中的點:3D image_points = [] # 圖像空間中的點:2d # 2.1 生成真實的交點坐標:類似(0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)的三維點 objp = np.zeros((nx * ny, 3), np.float32) objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2) # 2.2 檢測每幅圖像角點坐標 for file_path in file_paths: img = cv2.imread(file_path) # 將圖像轉換為灰度圖 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自動檢測棋盤格內4個棋盤格的角點(2白2黑的交點) rect, corners = cv2.findChessboardCorners(gray, (nx, ny), None) # 若檢測到角點,則將其存儲到object_points和image_points if rect == True: object_points.append(objp) image_points.append(corners) # 2.3 獲取相機參數 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None) return ret, mtx, dist, rvecs, tvecs def img_undistort(img, mtx, dist): """ 圖像去畸變 """ return cv2.undistort(img, mtx, dist, None, mtx) # 測試去畸變函數的效果 file_paths = glob.glob("./camera_cal/calibration*.jpg") ret, mtx, dist, rvecs, tvecs = cal_calibrate_params(file_paths) if mtx.any() != None: # a.any() or a.all() img = mpimg.imread("./camera_cal/calibration1.jpg") undistort_img = img_undistort(img, mtx, dist) plot_contrast_imgs(img, undistort_img) print("done!") else: print("failed")
執行代碼:
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 基於python opencv單目相機標定的示例代碼
- 如何基於python實現單目三維重建詳解
- OpenCV特征提取與檢測之Shi-Tomasi角點檢測器
- OpenCV通過透視變換實現矯正圖像詳解
- python圖像處理基本操作總結(PIL庫、Matplotlib及Numpy)