使用OpenCV库进行相机标定C++代码

通过分析一系列(至少三张)包含棋盘格图案的图像,来计算相机的内参数矩阵(包括焦距、主点坐标等)和畸变系数,以及每幅图像对应的外参数(旋转和平移向量)。下面是代码的详细步骤:
1、包含头文件和命名空间定义:引入必要的OpenCV库头文件和Windows API头文件,以及定义了使用的命名空间。
2、定义棋盘格角点查找函数:定义了findChessboardCornersFunc函数,该函数利用OpenCV的findChessboardCorners查找图像中的棋盘格角点,并使用cornerSubPix函数进一步精确这些角点的位置。
主函数流程:
2、初始化参数:定义了棋盘格的规格(行数、列数)、每个格子的实际宽度和高度,以及用于存储角点的世界坐标、图像坐标、图像名称和图像数据的向量。
读取图像文件名:通过Windows API遍历指定路径下的.jpg和.png格式的图像文件,将文件路径添加到imageNames向量中。
初始化世界坐标系中的棋盘格角点:根据棋盘格的规格和格子的实际尺寸,计算所有角点的三维坐标并存储在objp 向量中。
处理每个图像:遍历所有图像,读取图像并将其转换为灰度图,然后尝试在图像中查找棋盘格角点。如果找到,将角点图像坐标、对应的角点世界坐标和图像本身分别存储在imagePoints、objectPoints和images向量中。
相机标定:使用calibrateCamera函数,根据找到的所有图像角点及其对应的世界坐标,以及图像的尺寸,计算出相机的内参数矩阵、畸变系数、旋转矩阵和平移向量。
输出结果:打印出计算得到的相机内参数矩阵和畸变系数。
图像去畸变展示:选取第一张图像,使用undistort函数对其进行去畸变处理,并显示原始图像和去畸变后的图像,等待用户按键后关闭窗口。

#include <opencv2/opencv.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <windows.h>
#include <iostream>
#include <vector>
#include <filesystem>

using namespace cv;
using namespace std;

// 函数用于寻找并标记图像中的棋盘格角点
bool findChessboardCornersFunc(const Mat& image, Size patternSize, vector<Point2f>& corners)
{
	bool found = findChessboardCorners(image, patternSize, corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_FAST_CHECK + CALIB_CB_NORMALIZE_IMAGE);
	if (found)
		cornerSubPix(image, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.01));
	return found;
}

int main()
{
	// 标定板的规格
	Size patternSize(11, 8); // 棋盘格内角点
	float squareSizeWidth = 30.0f; // 棋盘格格子大小
	float squareSizeHeight = 30.0f; // 棋盘格格子大小
	vector<vector<Point3f>> objectPoints;
	vector<vector<Point2f>> imagePoints;
	vector<String> imageNames;
	vector<Mat> images;

	// 读取所有图像文件名
	string path = "E:\\vsifle\\image\\image\\camera_L"; // 替换为你的图像文件夹路径
	WIN32_FIND_DATAA ffd;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	hFind = FindFirstFileA((path + "\\*.jpg").c_str(), &ffd);
	if (hFind == INVALID_HANDLE_VALUE)
	{
		hFind = FindFirstFileA((path + "\\*.png").c_str(), &ffd);
		if (hFind == INVALID_HANDLE_VALUE)
		{
			printf("No JPG or PNG files found.\n");
			return EXIT_FAILURE;
		}
	}
	do
	{
		imageNames.push_back(path + "\\" + ffd.cFileName);
	} while (FindNextFileA(hFind, &ffd) != 0);
	FindClose(hFind);

	// 初始化世界坐标系中的棋盘格角点
	vector<Point3f> objp;
	// 初始化世界坐标系中的棋盘格角点,考虑实际尺寸
	for (int i = 0; i < patternSize.height; i++)
		for (int j = 0; j < patternSize.width; j++)
			objp.push_back(Point3f(j*squareSizeWidth, i*squareSizeHeight, 0.0f));

	// 对每个图像进行处理
	for (const String& name : imageNames)
	{
		Mat img = imread(name, IMREAD_GRAYSCALE);
		if (img.empty())
		{
			cout << "Can't read image " << name << endl;
			continue;
		}
		//提取图像中的角点
		vector<Point2f> corners;
		if (findChessboardCornersFunc(img, patternSize, corners))
		{
			imagePoints.push_back(corners);
			objectPoints.push_back(objp);
			images.push_back(img);
		}
		else
		{
			cout << "Chessboard not found in " << name << endl;
		}
	}

	//根据标定板的世界坐标和图像角点坐标完成相机标定
	Mat cameraMatrix, distCoeffs, rvecs, tvecs;
	vector<vector<Point2f>> allImagePoints = imagePoints;
	vector<vector<Point3f>> allObjectPoints = objectPoints;

	calibrateCamera(allObjectPoints, allImagePoints, images[0].size(), cameraMatrix, distCoeffs, rvecs, tvecs);

	// 输出结果
	cout << "Camera matrix:" << endl << cameraMatrix << endl;
	cout << "Distortion coefficients:" << endl << distCoeffs << endl;

	// 可选:使用得到的参数对一张图片进行去畸变演示
	Mat undistorted;
	undistort(images[0], undistorted, cameraMatrix, distCoeffs);  //相机去畸变
	imshow("Original Image", images[0]);
	imshow("Undistorted Image", undistorted);
	waitKey(0);

	return 0;
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是使用OpenCV进行六路相机标定C++代码示例: ```c++ #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { // 设定棋盘格尺寸,这里假设棋盘格为 20mm x 20mm const float square_size = 20.0f; // 设定棋盘格内角点数量 const int board_width = 9; const int board_height = 6; const int board_size = board_width * board_height; // 读入图像 vector<vector<Mat>> images; for (int i = 0; i < 6; i++) { vector<Mat> img_vec; for (int j = 0; j < 10; j++) { stringstream ss; ss << "./data/" << i << "_" << j << ".jpg"; Mat img = imread(ss.str(), 0); if (img.empty()) { cerr << "Image not found: " << ss.str() << endl; return -1; } img_vec.push_back(img); } images.push_back(img_vec); } // 计算内角点坐标 vector<Point3f> object_points; for (int i = 0; i < board_height; i++) { for (int j = 0; j < board_width; j++) { object_points.push_back(Point3f(j * square_size, i * square_size, 0)); } } // 搜寻内角点 vector<vector<Point2f>> image_points; for (int i = 0; i < 6; i++) { vector<Point2f> img_pts; for (int j = 0; j < 10; j++) { Mat img = images[i][j]; vector<Point2f> corners; bool found = findChessboardCorners(img, Size(board_width, board_height), corners); if (found) { // 提高角点精度 cornerSubPix(img, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1)); img_pts.insert(img_pts.end(), corners.begin(), corners.end()); } } image_points.push_back(img_pts); } // 执行标定 vector<Mat> rvecs, tvecs; Mat K, D; vector<vector<Point3f>> object_points_vec(6, object_points); calibrateCamera(object_points_vec, image_points, images[0][0].size(), K, D, rvecs, tvecs, CV_CALIB_ZERO_TANGENT_DIST | CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5); // 输出标定结果 cout << "K: \n" << K << endl; cout << "D: \n" << D << endl; for (int i = 0; i < 6; i++) { cout << "rvec" << i << ": \n" << rvecs[i] << endl; cout << "tvec" << i << ": \n" << tvecs[i] << endl; } return 0; } ``` 这段代码假设读入了六个相机的十张棋盘格图像,图像文件名为 `./data/i_j.jpg`,其中 `i` 表示相机编号,`j` 表示图像编号。标定结果将输出相机的内参矩阵 `K`、畸变系数 `D`,以及每个相机的旋转向量 `rvec` 和平移向量 `tvec`。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值