单目相机,尤其是一些具有较大视场角的鱼眼相机,所拍摄的图片通常具有较大的桶形畸变。
为了获得正确的图像,即“真实世界的直线在图片中也呈现为直线”,需要对相机拍摄的图片进行校正。
校正需要相机的内参,而通过标定相机可以获得这些参数(标定的方法见我之前的博客)。一般情况下,标定之后都需要把获得的相机标定数据保存在一些文件中,通常使用“.yml”文件格式。保存在这种格式文件中的数据非常容易通过C++语言读取放入我们需要的程序当中。
此处贴上其他作者分享的“读取和写入 opencv yml 相机标定参数”的代码作为参考。该代码非常简明易懂。
写入数据到yml文件:
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char** argv)
{
FileStorage fs("test.yml", FileStorage::WRITE);
Mat cameraMatrix = (Mat_<double>(3, 3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
Mat distCoeffs = (Mat_<double>(5, 1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
fs.release();
return 0;
}
从yml文件读取数据:
#include "opencv2/opencv.hpp"
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
FileStorage fs2("C:/Users/Administrator/Desktop/test.yml", FileStorage::READ);
Mat cameraMatrix2, distCoeffs2;
fs2["cameraMatrix"] >> cameraMatrix2;
fs2["distCoeffs"] >> distCoeffs2;
cout << cameraMatrix2 << endl;
cout << distCoeffs2 << endl;
}
原文链接:https://blog.csdn.net/qq_15505637/article/details/75270615
在对以上代码进行了一定修改之后,我终于成功地使用自己标定得到的数据实现了鱼眼相机的畸变校正。代码如下:
/******************首先添加一些必要的头文件************************/
#include "opencv2/core.hpp"
#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <cctype>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
/*************************** 1. 从yml文件读取相机标定数据*******************************/
Mat cameraMatrix, distCoeffs; //相机矩阵、畸变系数矩阵
FileStorage fs2("F:\\SoftwareData\\OpenCV\\Study\\Calibration_sample\\calibration_sample\\x64\\Debug\\camera.yml", FileStorage::READ); //此条命令可以读取之前获得的标定数据
fs2["camera_matrix"] >> cameraMatrix; //将文件中名为“camera_matrix”的变量的值赋给cameraMatrix
fs2["distortion_coefficients"] >> distCoeffs; //作用类似上一句
/*************************** 2. 读取需要校正的图片***************************************/
Mat view; //声明准备装入待处理图像的Mat类变量
Mat temp; //声明用于暂存的图像变量temp
view = imread("F:\\SoftwareData\\OpenCV\\Study\\rectify_test\\rectify_test.bmp",1); //读入待处理图像到view变量
temp = view.clone(); //克隆原图像view至暂存图像变量temp
/*注意:两种方法生成的校正图片稍有区别。方法一生成的是没有黑色边缘的图。方法二生成的是有黑色边缘的图。*/
/************************** 3.1 查表法校正********************************/
/* Mat map1, map2; //声明用于匹配的映射表map1,map2
Size imageSize; //声明图像尺寸
imageSize = view.size(); //图像尺寸赋值
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), // 构建校正表格。initUndistortRectifyMap()这个函数很重要,它可以构建校正图像的查表,形成查表后,配合另一个remap()函数使用,可以提高校正图像的速度。
getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
imageSize, CV_16SC2, map1, map2);
remap(temp, view, map1, map2, INTER_LINEAR); //对view变量进行查表,查表为从map1->map2的映射关系,使用线性插值,输出图像为view图像变量。
*/
/************************** 3.2 使用校正函数校正********************************/
undistort(temp, view, cameraMatrix, distCoeffs); //校正图像,并存放在view当中
/****************************保存校正好的图片*****************************/
imwrite("F:\\SoftwareData\\OpenCV\\Study\\rectify_test\\rectifed_image.bmp",view);
//**************************显示已经校正的图像************
// imshow("Image View", view); //显示已经校正过的图像。
return 0;
}