下面是一個完整的 使用 OpenCV 進行相機內參標定(Camera Calibration) 的示例,包括 C++ 和 Python 兩個版本,基于棋盤格圖案標定。
一、目標:相機標定
通過拍攝多張帶有棋盤格圖案的圖像,估計相機的內參:
- 相機矩陣(內參)
K
- 畸變系數
distCoeffs
- 可選外參(R, T)
- 標定精度指標(如重投影誤差)
二、棋盤格參數設置(根據自己的棋盤格設置):
- 棋盤格角點數:
9 x 6
(內角點,9列×6行); - 每個格子實際尺寸為:
25.0 mm
(自定義); - 圖像列表已存為多張 JPG /或者其他格式圖片。
三、Python 示例(
import cv2
import numpy as np
import glob# 設置棋盤格參數
chessboard_size = (9, 6)
square_size = 25.0 # mm# 生成世界坐標系下的 3D 點
objp = np.zeros((np.prod(chessboard_size), 3), np.float32)
objp[:, :2] = np.indices(chessboard_size).T.reshape(-1, 2)
objp *= square_size# 儲存所有圖像的角點
objpoints = [] # 3D points
imgpoints = [] # 2D points# 讀取圖片
images = glob.glob("calib_images/*.jpg")for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 檢測角點ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)if ret:objpoints.append(objp)corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1),criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))imgpoints.append(corners2)# 可視化角點cv2.drawChessboardCorners(img, chessboard_size, corners2, ret)cv2.imshow('img', img)cv2.waitKey(100)cv2.destroyAllWindows()# 標定相機
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)print("相機內參矩陣 K:\n", K)
print("畸變系數 dist:\n", dist)
print("重投影誤差:", ret)
四、C++ 示例
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
#include <filesystem>using namespace cv;
using namespace std;int main() {Size boardSize(9, 6);float squareSize = 25.0f;vector<vector<Point3f>> objectPoints;vector<vector<Point2f>> imagePoints;vector<Point3f> objp;for (int i = 0; i < boardSize.height; ++i)for (int j = 0; j < boardSize.width; ++j)objp.emplace_back(j * squareSize, i * squareSize, 0);vector<String> imageFiles;glob("calib_images/*.jpg", imageFiles);for (const auto& fname : imageFiles) {Mat img = imread(fname);Mat gray;cvtColor(img, gray, COLOR_BGR2GRAY);vector<Point2f> corners;bool found = findChessboardCorners(gray, boardSize, corners);if (found) {cornerSubPix(gray, corners, Size(11,11), Size(-1,-1),TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.001));imagePoints.push_back(corners);objectPoints.push_back(objp);drawChessboardCorners(img, boardSize, corners, found);imshow("Corners", img);waitKey(100);}}destroyAllWindows();Mat K, distCoeffs;vector<Mat> rvecs, tvecs;calibrateCamera(objectPoints, imagePoints, Size(640, 480),K, distCoeffs, rvecs, tvecs);cout << "Camera Matrix K:\n" << K << endl;cout << "Distortion Coefficients:\n" << distCoeffs << endl;
}
五、輸出參數解釋
參數 | 含義 |
---|---|
K / cameraMatrix | 相機內參矩陣 (fx, fy, cx, cy) |
distCoeffs | 畸變參數 [k1, k2, p1, p2, k3] |
rvecs | 每張圖像的旋轉向量 |
tvecs | 每張圖像的平移向量 |
ret | 平均重投影誤差(數值越小越好) |
六、應用建議
- 拍攝圖像時應盡量覆蓋各個角度、不同距離;
- 建議圖像 >10 張以上;
- 標定結果可用于
cv::undistort
、cv::initUndistortRectifyMap
做圖像矯正; - 也可以用 fisheye 模型標定 (
cv::fisheye::calibrate
),適用于廣角相機。