主要参考https://blog.csdn.net/billbliss/article/details/52527182一文进行的学习
在1的基础上,将代码写成函数调用形式,利用.yml文件存储摄像头标定数据。
camera data.yml
%YAML:1.0
image_Width: 960
image_Height: 576
fx: 635.6616
fy: 493.5513
cx: 502.5203
cy: 272.9890
kc1: -0.3917
kc2: 0.1388
kc3: 0
kc4: 0
camera data中存储了相机标定数据(源自maltab工具箱),可以利用以下matlab程序生成上述yml文件
fp=fopen('D:\camera data.txt','a');
fprintf(fp,'%s\r\n','%YAML:1.0');
fprintf(fp,'%s','image_Width: ');
fprintf(fp,'%d\r\n',cameraParams.ImageSize(2));
fprintf(fp,'%s','image_Height: ');
fprintf(fp,'%d\r\n',cameraParams.ImageSize(1));
fprintf(fp,'%s','fx: ');
fprintf(fp,'%f\r\n',cameraParams.FocalLength(1));
fprintf(fp,'%s','fy: ');
fprintf(fp,'%f\r\n',cameraParams.FocalLength(2));
fprintf(fp,'%s','cx: ');
fprintf(fp,'%f\r\n',cameraParams.PrincipalPoint(1));
fprintf(fp,'%s','cy: ');
fprintf(fp,'%f\r\n',cameraParams.PrincipalPoint(2));
fprintf(fp,'%s','kc1: ');
fprintf(fp,'%f\r\n',cameraParams.RadialDistortion(1));
fprintf(fp,'%s','kc2: ');
fprintf(fp,'%f\r\n',cameraParams.RadialDistortion(2));
fprintf(fp,'%s','kc3: ');
fprintf(fp,'%f\r\n',cameraParams.TangentialDistortion(1));
fprintf(fp,'%s','kc4: ');
fprintf(fp,'%f\r\n',cameraParams.TangentialDistortion(2));
fclose(fp);%关闭文件。
movefile('D:\camera data.txt', 'D:\camera data.yml');
模仿了前人的编写方法,将读取参数作为一个函数,将图片重映射参数获取作为一个参数,同时因为后续处理会用到处理后的图片,把remap放在main里面
#include <iostream>
#include"opencv.hpp"
using namespace cv;
using namespace std;
void Get_Camera_Params(Mat &intrinsic_matrix, Mat &distortion_coeffs, Size &imageSize, char *image_path)
{
FileStorage get_camera_inf;
double fx, fy, cx, cy, kc1, kc2, kc3, kc4;
int image_Width, image_Height;
if (get_camera_inf.open(image_path, FileStorage::READ) != 0)
{
get_camera_inf["fx"] >> fx;
get_camera_inf["fy"] >> fy;
get_camera_inf["cx"] >> cx;
get_camera_inf["cy"] >> cy;
get_camera_inf["kc1"] >> kc1;
get_camera_inf["kc2"] >> kc2;
get_camera_inf["kc3"] >> kc3;
get_camera_inf["kc4"] >> kc4;
get_camera_inf["image_Width"] >> image_Width;
get_camera_inf["image_Height"] >> image_Height;
}
else
cout << "Cannot open this file" << endl;
get_camera_inf.release();
intrinsic_matrix = (Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);//内参矩阵
distortion_coeffs = (Mat_<double>(1, 4) << kc1, kc2, kc3, kc4);//畸变系数
imageSize = Size(image_Width, image_Height);
cout << "intrinsic_matrix " << intrinsic_matrix << endl
<< "distortion_coeffs " << distortion_coeffs << endl
<< "imageSize " << imageSize << endl;
}
void Image_Correction(Mat &Img, char *image_path,Mat &map1, Mat &map2)
{
Mat intrinsic_matrix, distortion_coeffs;//定义内参矩阵和畸变参数矩阵
Size imageSize;//照片尺寸
Get_Camera_Params(intrinsic_matrix, distortion_coeffs, imageSize, image_path);
//undistort(Img, ImgRemap, intrinsic_matrix, distortion_coeffs); //矫正 300ms
initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, Mat(),
getOptimalNewCameraMatrix(intrinsic_matrix, distortion_coeffs,imageSize,1, imageSize, 0),
imageSize,CV_16SC2,map1,map2);//获得map1,map2映射表,用以提升速度,多张图片只需要运行一次
}
void main()
{
Mat Img1 = imread("C:\\Users\\sunmingzhe\\Desktop\\test\\1.jpg");//读取待处理图片
char *image_path1 = "D:\\项目代码\\相机标定\\camera calibration\\camera calibration\\camera data.yml";
string filePath = "Correction1.jpg";//处理后图像名
Mat ImgRemap1= imread(filePath);
Mat map1_x, map1_y;
Image_Correction(Img1, image_path1, map1_x, map1_y);//获取映射矩阵map1_x, map1_y
remap(Img1, ImgRemap1, map1_x, map1_y, INTER_LINEAR);//校准图像 70ms
imshow("Correction Image", ImgRemap1);//显示图像
imwrite(filePath, ImgRemap1);//保存图像
waitKey(0);
}
Get_Camera_Params的作用是读取yaml文件中的参数(ps:yaml中":"一定是英文符号。。否则会报错。。中文英文很接近。。。mdzz)
map1,map2放在外面试因为处理多张图片时,这些图片的map1,map2是一样的,只需要执行一次Image_Correction函数
之前考虑把remap也放在Image_Correction函数中,然后把map1,map2定义为全局变量,考虑到remap就一行,就放弃了。。