1.双目相机模型
2.双目相机标定
void visionagin:: Mystersocalibrate()
{
//读取左右相机拍摄的照片文件名
ifstream iftL("C:\\Users\\86176\\Downloads\\visionimage\\totalphotosL.txt"),
iftR("C:\\Users\\86176\\Downloads\\visionimage\\totalphotosR.txt");
string temp("C:\\Users\\86176\\Downloads\\visionimage\\");
string imagenameL, imagenameR;//每幅图像的路径
vector<Mat>imagesL, imagesR;
while (getline(iftL, imagenameL)&&getline(iftR,imagenameR))
{
Mat imageL, imageR;
//读取左右图像集
imageL = imread(temp + imagenameL);
imageR = imread(temp + imagenameR);
if (imageL.empty() || imageR.empty())
{
cout << "读取失败!" << endl;
}
imagesL.push_back(imageL);
imagesR.push_back(imageR);
}
vector<vector<Point2f>>points2L, points2R;//左右相机多幅图像的角点坐标
Size bothboardsize(9, 6);
Size squaresize(10, 10);
//求取左右图像中棋盘的角点坐标
for (int i = 0; i < imagesL.size(); ++i)
{
Mat gryL, gryR;
cvtColor(imagesL[i], gryL, COLOR_BGR2GRAY);
cvtColor(imagesR[i], gryR, COLOR_BGR2GRAY);
vector<Point2f> tempL;
vector<Point2f> tempR;
findChessboardCorners(gryL, bothboardsize, tempL);
findChessboardCorners(gryR, bothboardsize, tempR);
//细化棋盘角点坐标
find4QuadCornerSubpix(gryL, tempL, Size(5, 5));
find4QuadCornerSubpix(gryR, tempR, Size(5, 5));
points2L.push_back(tempL);
points2R.push_back(tempR);
}
//生成左右棋盘角点的空间三维坐标集
vector<vector<Point3f>>points3;
for (int i = 0; i < imagesL.size(); ++i)
{
vector<Point3f> TEMP;
for (int j = 0; j < bothboardsize.height; ++j)
{
for (int k = 0; k < bothboardsize.width; ++k)
{
Point3f temp;
temp.x = j * squaresize.width;
temp.y = k * squaresize.height;
temp.z = 0;
TEMP.push_back(temp);
}
}
points3.push_back(TEMP);
}
Mat cameraML = Mat(3, 3, CV_32FC1,Scalar::all(0));
Mat cameraMR = Mat(3, 3, CV_32FC1, Scalar::all(0));
Mat distcoeffL= Mat(1, 5, CV_32FC1, Scalar::all(0));
Mat distcoeffR = Mat(1, 5, CV_32FC1, Scalar::all(0));
Mat rvecs, tvecs;
//先单独标定左右相机参数
calibrateCamera(points3, points2L, imagesL[0].size(), cameraML, distcoeffL, rvecs, tvecs);
calibrateCamera(points3, points2R, imagesR[0].size(), cameraMR, distcoeffR, rvecs, tvecs);
Mat R, T, E, F;//旋转短阵、平移向量、 本征矩阵、基本矩阵
stereoCalibrate(points3, points2L, points2R, cameraML, distcoeffL, cameraMR, distcoeffR, imagesL[0].size(), R, T, E, F,CALIB_USE_INTRINSIC_GUESS);
cout << "两个相机坐标系的旋转矩阵:" << R << endl;
cout << "两个相机坐标系的平移向量" << T<< endl;
}
3.双目相机校正
void visionagin:: Mysterorectofy()
{
//使用之前双目相机标定得到的内参 畸变系数 旋转矩阵和平移向量
Mat R= (Mat_<double >(3, 3) << 0.9999912307195959, 0.003090276899205375, 0.002826423994037764,
-0.003077528700595732, 0.9999851228861411, -0.004503645577366223,
-0.002840299456896107, 0.004494907682673629, 0.9999858641520486);
//平移向量三行一列
Mat T=(Mat_<double >(3,1)<< -33.22516725994758,
0.4373643000560988,
0.523302125269594);
Mat cameraML = (Mat_<float >(3, 3) << 532.0162975827582, 0, 332.1725192389595,
0, 531.5651587897565, 233.3880748229786,
0, 0, 1);
Mat distcoeffL = (Mat_<float >(1, 5) << -0.2851884066280067, 0.0800972142572013, 0.001274031468563325, -0.002415106464876228, 0.1065791099058786);
Mat cameraMR = (Mat_<float >(3, 3) << 535.3824650855895, 0, 321.0856312892987,
0, 535.4791599963741, 248.6968617265358,
0, 0, 1);
Mat distcoeffR = (Mat_<float>(1, 5) << -0.3191637777394278, 0.2726553907347779, -0.001018543210768334, -0.001877630188078218, -0.2524120140824795);
//读取图片
ifstream iftL("C:\\Users\\86176\\Downloads\\visionimage\\totalphotosL.txt"),
iftR("C:\\Users\\86176\\Downloads\\visionimage\\totalphotosR.txt");
string temp("C:\\Users\\86176\\Downloads\\visionimage\\");
string imagenameL, imagenameR;//每幅图像的路径
vector<Mat>imagesL, imagesR;
while (getline(iftL, imagenameL) && getline(iftR, imagenameR))
{
Mat imageL, imageR;
//读取左右图像集
imageL = imread(temp + imagenameL);
imageR = imread(temp + imagenameR);
if (imageL.empty() || imageR.empty())
{
cout << "读取失败!" << endl;
}
imagesL.push_back(imageL);
imagesR.push_back(imageR);
}
//计算校正变换矩阵
Mat R1, R2, P1, P2, Q;//把第一个相机校正前点的坐标转换到校正后点的坐标所需的旋转矩阵:R1; 第一个相机校正后坐标系的投影矩阵P1; 深度差异映射矩阵 Q
stereoRectify(cameraML, distcoeffL, cameraMR, distcoeffR, imagesL[0].size(), R, T, R1, R2, P1, P2, Q);
//计算校正映射矩阵
Mat remapx1, remapx2, remapy1, remapy2;
initUndistortRectifyMap(cameraML, distcoeffL, R1, P1, imagesL[0].size(), CV_32FC1, remapx1, remapy1);
initUndistortRectifyMap(cameraMR, distcoeffR, R2, P2, imagesL[0].size(), CV_32FC1, remapx2, remapy2);
for (int i = 0; i < imagesL.size(); ++i)
{
imshow("原图L" + to_string(i + 1), imagesL[i]);
imshow("原图R" + to_string(i + 1), imagesR[i]);
//进行校正
Mat tempL, tempR;
remap(imagesL[i], tempL, remapx1, remapy1, INTER_LINEAR);
remap(imagesR[i], tempR, remapx2, remapy2, INTER_LINEAR);
//图像拼接
Mat result;
hconcat(tempL, tempR, result);
imshow("校正后结果"+to_string(i+1), result);
}
}