棋盘格格距为10mm 相机型号mv-CA013-20gc
现利用matlab双目标定工具箱标定出
stereoParams.RotationOfCamera2参数
stereoParams.TranslationOfCamera2参数
结合相机摆放位置,可以看到stereoParams.RotationOfCamera2实际上是,即相机2相对于相机1的旋转矩阵
stereoParams.TranslationOfCamera2为即相机1相对相机2的平移
matlab三角化算出棋盘格三维点坐标
% 提取左相机和右相机的匹配点像素坐标
imagePoints1 = [534.000977, 669.012024; 555.036255,668.459778]; % 替换为实际的左相机匹配点
imagePoints2 = [742.877014, 534.354797; 764.536194, 535.095947]; % 替换为实际的右相机匹配点
% 使用 triangulate 函数计算三维坐标
points3D = triangulate(imagePoints1, imagePoints2, stereoParams);
% 显示结果
scatter3(points3D(:,1), points3D(:,2), points3D(:,3), '.');
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Reconstructed 3D Points');
运行norm(points3D(1,:)-points3D(2,:)),算出棋盘格格距10.1964mm与实际一致
opencv三角化算出棋盘格三维点坐标
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <iostream>
using namespace std;
using namespace cv;
cv::Point2d pixel2cam(const cv::Point2f& p, const cv::Mat& K) {
return cv::Point2d(
(p.x - K.at<double>(0, 2)) / K.at<double>(0, 0),
(p.y - K.at<double>(1, 2)) / K.at<double>(1, 1)
);
}
int main() {
// 定义左右相机的相机矩阵
cv::Mat T1 = (cv::Mat_<float>(3, 4) <<
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0);
/*cv::Mat T2 = (cv::Mat_<float>(3, 4) <<
0.953637062614699, 0.00658496811859602, -0.300887007035011, 4.458319257471509e+02,
-0.00250704140519836, 0.999899730598709, 0.0139371263904078, 11.501725596171031,
0.300948612807905, -0.0125366240873153, 0.953557950785106, 65.623152047724048);*/
//cv::triangulatePoints(T2, T1, pts1, pts2, points4D);//for 2
//cv::triangulatePoints(T1, T2, pts2, pts1, points4D);//for 2
//cv::triangulatePoints(T2, T1, pts2, pts1, points4D);//啥也不是
//cv::triangulatePoints(T1, T2, pts1, pts2, points4D);//啥也不是
cv::Mat T2 = (cv::Mat_<float>(3, 4) <<
0.953637062614699, -0.00250704140519836, 0.300948612807905, -444.882209363911,
0.00658496811859602, 0.999899730598709, -0.0125366240873153, -13.6136685536819,
-0.300887007035011, 0.0139371263904078, 0.953557950785106, 71.4092543846866);
cv::Mat K1 = (cv::Mat_<double>(3, 3) <<
3638.91841273777, 0, 605.061877450677,
0, 3646.16879065885, 528.394303538593,
0, 0, 1);
cv::Mat K2 = (cv::Mat_<double>(3, 3) <<
3624.20398341909, 0, 667.453224169270,
0, 3626.03671391354, 469.395650206574,
0, 0, 1);
// 读取图像
cv::Mat image1 = cv::imread("E:/BaiduNetdiskDownload/毕设/test/l/Image_2429.bmp");
cv::Mat image2 = cv::imread("E:/BaiduNetdiskDownload/毕设/test/r/Image_2692.bmp");
// 检查图像是否成功加载
if (image1.empty()|| image2.empty()) {
std::cerr << "无法加载图像文件!" << std::endl;
return -1;
}
// 定义棋盘格内角点的行数和列数
int chessboardRows = 8; // 棋盘格行数
int chessboardCols = 11; // 棋盘格列数
// 用于存储检测到的角点
std::vector<cv::Point2f> corners1, corners2;
std::vector<cv::Point2d> pts1, pts2;
// 尝试在图像中检测棋盘格角点
bool patternFound1 = cv::findChessboardCorners(image1, cv::Size(chessboardCols, chessboardRows), corners1);
bool patternFound2 = cv::findChessboardCorners(image2, cv::Size(chessboardCols, chessboardRows), corners2);
for (int i = 0; i < corners1.size(); i++)
{
// 调用函数将像素坐标系下的点转换为相机坐标系下的点
pts1.push_back(pixel2cam(corners1[i], K1));
pts2.push_back(pixel2cam(corners2[i], K2));
}
//-- 计算基础矩阵
Mat fundamental_matrix;
fundamental_matrix = findFundamentalMat(corners1, corners2, FM_RANSAC);
// 如果找到棋盘格角点
if (patternFound1&& patternFound2) {
// 在图像中绘制检测到的角点
cv::drawChessboardCorners(image1, cv::Size(chessboardCols, chessboardRows), corners1, patternFound1);
cv::drawChessboardCorners(image2, cv::Size(chessboardCols, chessboardRows), corners2, patternFound2);
/*
std::vector<cv::Point2f> p1;
p1.push_back(pixel2cam(corners1[1], K1));
std::vector<cv::Point2f> p2;
p2.push_back(pixel2cam(corners2[1], K2));
*/
// 通过三角测量计算三维点坐标
cv::Mat points4D1;
cv::triangulatePoints(T1, T2, pts1, pts2, points4D1);//T2 == T21 服了
//cv::triangulatePoints(T2, T1, pts1, pts2, points4D);//for 2
// 将齐次坐标转换为非齐次坐标
cv::Mat points3D1;
cv::convertPointsFromHomogeneous(points4D1.t(), points3D1);
// 显示带有角点的图像
cv::imshow("Detected Corners1", image1);
cv::imshow("Detected Corners2", image2);
cv::waitKey(0);
}
else {
std::cerr << "未能检测到棋盘格角点!" << std::endl;
}
return 0;
}
matlab运行结果
opencv运行结果
保持一致