后续还会更改
#include <io.h>
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void getFilesName(string& fileDirectory, string& fileType, vector<string>& filesName)
{
string buffer = fileDirectory + "/*" + fileType; // 拼接文件搜索路径,形如 "目录/*文件类型"
intptr_t hFile;
_finddata_t c_file; // 文件信息结构体
hFile = _findfirst(buffer.c_str(), &c_file); // 开始查找第一个匹配的文件
if (hFile == -1L)
cout << "No " << fileType << " files in current directory!" << endl;
else
{
string fullFilePath;
// 循环查找并处理每个匹配的文件
do
{
fullFilePath.clear();
fullFilePath = fileDirectory + "/" + c_file.name; // 拼接完整文件路径,形如 "目录/文件名"
filesName.push_back(fullFilePath); // 将完整文件路径存储到文件名向量中
} while (_findnext(hFile, &c_file) == 0);
_findclose(hFile); // 关闭文件查找句柄
}
}
void cameraCalibration(vector<string>& filesName, const Size &cornersNum, const Size &gridSize,
Mat& cameraMatrix, Mat& distCoeffs, Mat& rvecsMat, Mat& tvecsMat)
{
Detect 2D corners
cout << "*****角点检测 starts*****" << endl;
Size image_size;
vector<Point2f> image_points; // 2D corners of one image
vector<vector<Point2f>> image_points_seq; // 2D corners of all images
for (int i = 0; i < filesName.size(); ++i)
{
cout << "Image " << filesName[i] << " processing..." << endl;
Mat img = imread(filesName[i]);
if (i == 0) // get width and height only when reads the first image
{
image_size.width = img.cols;
image_size.height = img.rows;
cout <<"图片宽: "<< image_size.width << endl;
cout <<"图片高: "<< image_size.height << endl;
}
// 检测棋盘格角点
if (!findChessboardCorners(img, cornersNum, image_points))
{
cout << "Detect corners of " << filesName[i] << " failed. " << endl;
waitKey(0);
return;
}
else
{
Mat imgGray;
cvtColor(img, imgGray, COLOR_RGB2GRAY); // 将图像转换为灰度图
// subpix processing to get more accurate results 使用亚像素处理以获得更精确的角点位置
cv::cornerSubPix(imgGray, image_points, cv::Size(5, 8),
cv::Size(-1, -1),
cv::TermCriteria(TermCriteria::COUNT | TermCriteria::EPS, 20, 0.01)); //亚像素处理的迭代停止条件 使用迭代次数(COUNT)和迭代误差(EPS)的组合,最多迭代 20 次,或达到迭代误差 0.01 时停止。
image_points_seq.push_back(image_points); // 将处理后的角点添加到图像角点序列中
}
}
2D corners -> 3D corners 将检测到的2D角点映射到3D世界坐标系中,形成对象点序列。
vector<vector<Point3f>> object_points_seq;
for (int t = 0; t < filesName.size(); ++t) //遍历所有图片文件
{
vector<Point3f> object_points;
for (int i = 0; i < cornersNum.height; ++i) //遍历棋盘格的高度方向上的角点
{
for (int j = 0; j < cornersNum.width; ++j) //遍历棋盘格的宽度方向上的角点
{
Point3f realPoint;
realPoint.x = i * gridSize.width; //设置该角点在X轴上的坐标,根据棋盘格的行数和格子大小计算得出。
realPoint.y = j * gridSize.height;
realPoint.z = 0; // due to all corners in the same plane 棋盘格的所有角点在同一平面上,因此Z轴坐标都为0
object_points.push_back(realPoint); // 将当前计算得到的3D角点坐标添加到object_points向量中。
}
}
object_points_seq.push_back(object_points);
}
cout << "*****角点检测 ends*****" << endl;
Calibration
cout << "*****Calibration started*****" << endl;
calibrateCamera(object_points_seq, image_points_seq, image_size, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);
//distCoeffs 畸变系数
//rvecsMat 包含每张图像的旋转矩阵的向量。每个旋转矩阵对应一个图像
//tvecsMat 包含每张图像的旋转矩阵的向量。每个旋转矩阵对应一个图像
cout << "*****Calibration ended*****" << endl;
}
void saveResults(const string &file, const Mat &cameraMatrix, const Mat &distCoeffs, const Mat &rvecsMat, const Mat &tvecsMat) {
ofstream resultFile(file, ios::out); //创建一个输出文件流对象 resultFile,以便将相机标定结果写入文件。
if (!resultFile) {
cout << "Opening " << file << " failed." << endl;
return;
}
// 内部参数矩阵输出
cout << "Intrinsic parameters of this camera: " << endl;
cout << cameraMatrix << endl;
resultFile << "Intrinsic parameters of this camera: " << endl;
resultFile << cameraMatrix << endl;
resultFile << endl;
// 旋转矩阵输出
cout << "rvecsMat" << endl;
cout << rvecsMat << endl;
resultFile << "rvecsMat" << endl;
resultFile << rvecsMat << endl;
resultFile << endl;
// 平移矩阵输出
cout << "tvecsMat" << endl;
cout << tvecsMat << endl;
resultFile << "tvecsMat" << endl;
resultFile << tvecsMat << endl;
resultFile << endl;
// 畸变系数输出
cout << "Distortion coefficients of this camera: " << endl;
cout << distCoeffs << endl;
resultFile << "Distortion coefficients of this camera: " << endl;
resultFile << distCoeffs << endl;
resultFile.close();
cout << "results saved to " << file << endl;
}
int main() {
string resultFile; // 结果文件
string fileDirectory; // 待标定图片文件夹
string fileType; // 待标定图片类型
cout << "Please input where to save results: " << endl; // E:\\shipsee\\test\\test\\calibration_result.txt
cin >> resultFile;
cout << "Please input where are the pictures: " << endl; // E:\\shipsee\\test\\test\\images
cin >> fileDirectory;
cout << "Please input which type of pictures to processing: " << endl; // .jpg
cin >> fileType;
// 获取文件名
vector<string> filesName;
getFilesName(fileDirectory, fileType, filesName);
Size cornersNum = Size(5, 8); // 角点行列数
Size gridSize = Size2d(23, 23); // 棋盘格大小
Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); // 相机内参数矩阵
Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)); // 相机畸变系数
Mat rvecsMat = Mat(3, 3, CV_32FC1, Scalar::all(0)); // 旋转矩阵
Mat tvecsMat = Mat(3, 1, CV_32FC1, Scalar::all(0)); // 平移矩阵
cameraCalibration(filesName, cornersNum, gridSize, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);
saveResults(resultFile, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);
system("pause");
return 0;
}
[点击并拖拽以移动]