opencv摄像头标定程序实现
摄像头标定是计算机视觉中的一个重要步骤,用于确定摄像头的内参(如焦距、主点、畸变系数等)和外参(如旋转矩阵和平移向量)。OpenCV 提供了方便的工具来进行摄像头标定。下面分别给出 C++ 和 Python 的实现。
1. C++ 实现
1.1 准备工作
- 准备一个棋盘格(如 9x6 的棋盘格)。
- 拍摄多张棋盘格图片(至少 10-15 张),确保棋盘格在不同位置和角度。
1.2 代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main() {
// 棋盘格的尺寸
Size boardSize(9, 6);
float squareSize = 1.0f; // 棋盘格方块的物理尺寸(单位:米)
// 存储棋盘格角点的三维坐标
vector<vector<Point3f>> objectPoints;
// 存储棋盘格角点的二维图像坐标
vector<vector<Point2f>> imagePoints;
// 生成棋盘格的三维坐标
vector<Point3f> obj;
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
obj.push_back(Point3f(j * squareSize, i * squareSize, 0));
}
}
// 读取图像
vector<String> imagePaths;
glob("path/to/calibration_images/*.jpg", imagePaths);
for (size_t i = 0; i < imagePaths.size(); i++) {
Mat image = imread(imagePaths[i]);
Mat gray;
cvtColor(image, 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(obj);
// 绘制并显示角点
drawChessboardCorners(image, boardSize, Mat(corners), found);
imshow("Corners", image);
waitKey(500);
}
}
// 标定摄像头
Mat cameraMatrix, distCoeffs;
vector<Mat> rvecs, tvecs;
double rms = calibrateCamera(objectPoints, imagePoints, gray.size(), cameraMatrix, distCoeffs, rvecs, tvecs);
cout << "RMS error: " << rms << endl;
cout << "Camera matrix: " << cameraMatrix << endl;
cout << "Distortion coefficients: " << distCoeffs << endl;
// 保存标定结果
FileStorage fs("camera_calibration.yml", FileStorage::WRITE);
fs << "camera_matrix" << cameraMatrix;
fs << "distortion_coefficients" << distCoeffs;
fs.release();
return 0;
}
1.3 运行说明
- 将棋盘格图片放在
path/to/calibration_images/
目录下。 - 运行程序后,标定结果将保存在
camera_calibration.yml
文件中。
2. Python 实现
2.1 准备工作
- 准备一个棋盘格(如 9x6 的棋盘格)。
- 拍摄多张棋盘格图片(至少 10-15 张),确保棋盘格在不同位置和角度。
2.2 代码实现
import cv2
import numpy as np
import glob
# 棋盘格的尺寸
board_size = (9, 6)
square_size = 1.0 # 棋盘格方块的物理尺寸(单位:米)
# 存储棋盘格角点的三维坐标
object_points = []
# 存储棋盘格角点的二维图像坐标
image_points = []
# 生成棋盘格的三维坐标
objp = np.zeros((board_size[0] * board_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:board_size[0], 0:board_size[1]].T.reshape(-1, 2)
objp *= square_size
# 读取图像
images = glob.glob('path/to/calibration_images/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 查找棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, board_size, None)
if ret:
# 亚像素精确化
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1),
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
image_points.append(corners2)
object_points.append(objp)
# 绘制并显示角点
cv2.drawChessboardCorners(img, board_size, corners2, ret)
cv2.imshow('Corners', img)
cv2.waitKey(500)
# 标定摄像头
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
print("RMS error:", ret)
print("Camera matrix:\n", camera_matrix)
print("Distortion coefficients:\n", dist_coeffs)
# 保存标定结果
np.savez('camera_calibration.npz', camera_matrix=camera_matrix, dist_coeffs=dist_coeffs)
cv2.destroyAllWindows()
2.3 运行说明
- 将棋盘格图片放在
path/to/calibration_images/
目录下。 - 运行程序后,标定结果将保存在
camera_calibration.npz
文件中。
3. 总结
- C++ 和 Python 的实现步骤基本相同,主要包括:准备棋盘格、查找角点、亚像素精确化、标定摄像头、保存标定结果。
- 标定结果可以用于后续的图像校正、三维重建等任务。