#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
ifstream inImgPath("calibdata.txt"); //标定所用图像文件的路径
vector imgList;
vector::iterator p;
string temp;
if (!inImgPath.is_open())
{
cout << "没有找到文件" << endl;
}
//读取文件中保存的图片文件路径,并存放在数组中
while (getline(inImgPath, temp))
{
imgList.push_back(temp);
}
ofstream fout("caliberation_result.txt"); //保存标定结果的文件
cout << "开始提取角点......" << endl;
cv::Size image_size;//保存图片大小
cv::Size pattern_size = cv::Size(9, 10);//标定板上每行、每列的角点数;测试图片中的标定板上内角点数为8*6
vector corner_points_buf;//建一个数组缓存检测到的角点,通常采用Point2f形式,以图像的左上角为原点,而不是以棋盘的左上角为原点
vector::iterator corner_points_buf_ptr;
vector> corner_points_of_all_imgs; //所有图片的角点信息
int image_num = 0;
string filename;
while(image_num < imgList.size())
{
filename = imgList[image_num++];
cout << "image_num = " << image_num << endl;
cout << filename << endl;
cv::Mat imageInput = cv::imread(filename);
if (image_num == 1)
{
image_size.width = imageInput.cols;
image_size.height = imageInput.rows;
cout << "image_size.width = " << image_size.width << endl;
cout << "image_size.height = " << image_size.height << endl;
}
if (findChessboardCorners(imageInput, pattern_size, corner_points_buf) == 0)
{
cout << "can not find all chessboard corners!\n"; //找不到角点
exit(1);
}
else
{
cv::Mat gray;
cv::cvtColor(imageInput, gray, COLOR_RGB2GRAY); //将原来的图片转换为灰度图片
cv::find4QuadCornerSubpix(gray, corner_points_buf, cv::Size(5, 5)); //提取亚像素角点,Size(5, 5),角点搜索窗口的大小。
corner_points_of_all_imgs.push_back(corner_points_buf);
cv::drawChessboardCorners(gray, pattern_size, corner_points_buf, true);
cv::imshow("camera calibration", gray);
cv::waitKey(100);
}
}
int total = corner_points_of_all_imgs.size();
cout << "total=" << total << endl;
int cornerNum = pattern_size.width * pattern_size.height;//每张图片上的总的角点数
// cout< 第" << i + 1 << "幅图片的数据 -->:" << endl;
for (int j = 0;j < cornerNum;j++)
{
cout << "-->" << corner_points_of_all_imgs[i][j].x;
cout << "-->" << corner_points_of_all_imgs[i][j].y;
if ((j + 1) % 3 == 0)
{
cout << endl;
}
else
{
cout.width(10);
}
}
cout << endl;
}
cout << endl << "角点提取完成" << endl;
//摄像机标定
cout << "开始标定………………" << endl;
cv::Mat cameraMatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));//内外参矩阵,H——单应性矩阵
cv::Mat distCoefficients = cv::Mat(1, 5, CV_32FC1, cv::Scalar::all(0));//摄像机的5个畸变系数:k1,k2,p1,p2,k3
vector tvecsMat;//每幅图像的平移向量,t,若干张图片的,不是一张图像的
vector rvecsMat;//每幅图像的旋转向量(罗德里格旋转向量,若干张图片的,不是一张图像的
vector> objectPoints;//保存所有图片的角点的三维坐标,所有图片的
//初始化每一张图片中标定板上角点的三维坐标 //世界坐标系,以棋盘格的左上角为坐标原点
int i, j, k;
for (k = 0;k < image_num;k++)//遍历每一张图片
{
vector tempCornerPoints;//每一幅图片对应的角点数组
//遍历所有的角点
for (i = 0;i < pattern_size.height;i++)
{
for (j = 0;j < pattern_size.width;j++)
{
cv::Point3f singleRealPoint;//一个角点的坐标,初始化三维坐标
singleRealPoint.x = i * 10; //10是长/宽,根据黑白格子的长和宽,计算出世界坐标系(x,y,z)
singleRealPoint.y = j * 10;
singleRealPoint.z = 0;//假设z=0
tempCornerPoints.push_back(singleRealPoint);
}
}
objectPoints.push_back(tempCornerPoints);
}
cv::calibrateCamera(objectPoints, corner_points_of_all_imgs, image_size, cameraMatrix, distCoefficients, rvecsMat, tvecsMat, 0);
cout << "标定完成" << endl;
//开始保存标定结果
cout << "开始保存标定结果" << endl;
cout << endl << "相机相关参数:" << endl;
fout << "相机相关参数:" << endl;
cout << "1.内外参数矩阵:" << endl;
fout << "1.内外参数矩阵:" << endl;
cout << "大小:" << cameraMatrix.size() << endl;
fout << "大小:" << cameraMatrix.size() << endl;
//cout< image_points_calculated;//存放新计算出的投影点的坐标
vector tempPointSet = objectPoints[i];
cv::projectPoints(tempPointSet, rvecsMat[i], tvecsMat[i], cameraMatrix, distCoefficients, image_points_calculated); //计算根据内外参等重投影出来的新的二维坐标,输出到image_points_calculated
//计算新的投影点与旧的投影点之间的误差
vector image_points_old = corner_points_of_all_imgs[i]; //向量
//将两组数据换成Mat格式
cv::Mat image_points_calculated_mat = cv::Mat(1, image_points_calculated.size(), CV_32FC2); //将mat矩阵转成1维的向量
cv::Mat image_points_old_mat = cv::Mat(1, image_points_old.size(), CV_32FC2);
for (j = 0;j < tempPointSet.size();j++)
{
image_points_calculated_mat.at(0, j) = cv::Vec2f(image_points_calculated[j].x, image_points_calculated[j].y); //vec2f->一个二维的向量
image_points_old_mat.at(0, j) = cv::Vec2f(image_points_old[j].x, image_points_old[j].y); //直接调用函数,不用定义对象
}
err = cv::norm(image_points_calculated_mat, image_points_old_mat, cv::NORM_L2); //输入的是矩阵
err /= corner_points_counts; //每个角点的误差
total_err += err;
cout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;
fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;
}
cout << "总体平均误差:" << total_err / image_num << "像素" << endl;
fout << "总体平均误差:" << total_err / image_num << "像素" << endl;
cout << "评价完成" << endl;
//下面就是矫正图像的代码
cv::Mat mapx = cv::Mat(image_size, CV_32FC1); //对应坐标的重映射参数
cv::Mat mapy = cv::Mat(image_size, CV_32FC1);
cv::Mat R = cv::Mat::eye(3, 3, CV_32F); //定义的对角线为1的对角矩阵
cout << "保存矫正图像" << endl;
string imageFileName;
std::stringstream StrStm;
for (int i = 0;i < image_num;i++)
{
cout << "Frame #" << i + 1 << endl;
cv::initUndistortRectifyMap(cameraMatrix, distCoefficients, R, cameraMatrix, image_size, CV_32FC1, mapx, mapy); //输入内参,纠正后的内参,外参等,计算输出矫正的重映射参数(相片尺寸 width*height),每个像素点都需要转换
cv::Mat src_image = cv::imread(imgList[i], 1);
cv::Mat new_image = src_image.clone();
cv::remap(src_image, new_image, mapx, mapy, cv::INTER_LINEAR);
imshow("原始图像", src_image);
imshow("矫正后图像", new_image);
StrStm.clear();
imageFileName.clear();
StrStm << i + 1;
StrStm >> imageFileName;
imageFileName += "_d.jpg";
cv::imwrite(imageFileName, new_image);
cv::waitKey(200);
}
cout << "保存结束" << endl;
fout.close(); //
cv::waitKey(0);
return 0;
}
相关文章:三维重建学习(4):张正友相机标定程序实现(OpenCV)_hongbin_xu的博客-CSDN博客_标定程序