关于matlab双目标定出来的旋转矩阵和平移矩阵方向,以及matlab与opencv三角化测三维坐标

棋盘格格距为10mm   相机型号mv-CA013-20gc

现利用matlab双目标定工具箱标定出

 stereoParams.RotationOfCamera2参数

stereoParams.TranslationOfCamera2参数 

结合相机摆放位置,可以看到stereoParams.RotationOfCamera2实际上是_{2}^{1}\textrm{R},即相机2相对于相机1的旋转矩阵

stereoParams.TranslationOfCamera2为_{1}^{2}\textrm{t}即相机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运行结果

保持一致

  • 21
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要用 OpenCV 得到无人机拍摄的旋转矩阵平移向量,可以使用以下步骤: 1. 加载照片,并进行特征点检测和匹配。可以使用 SIFT、SURF、ORB 等算法进行特征点检测和匹配。OpenCV 提供了这些算法的实现。 ```python import cv2 # 加载照片 img1 = cv2.imread('img1.jpg') img2 = cv2.imread('img2.jpg') # 初始化特征检测器和描述符 detector = cv2.SIFT_create() matcher = cv2.BFMatcher() # 检测特征点 kp1, des1 = detector.detectAndCompute(img1, None) kp2, des2 = detector.detectAndCompute(img2, None) # 特征点匹配 matches = matcher.match(des1, des2) ``` 2. 对特征点进行三维重建,得到相机的内部参数矩阵三维点云。可以使用 OpenCV 中的 `cv2.triangulatePoints()` 函数进行三维重建。 ```python # 相机内部参数矩阵 K = np.array([[f, 0, cx], [0, f, cy], [0, 0, 1]]) # 对特征点进行三维重建 points1 = np.array([kp1[m.queryIdx].pt for m in matches]) points2 = np.array([kp2[m.trainIdx].pt for m in matches]) points1_norm = cv2.undistortPoints(points1.reshape(-1, 1, 2), K, None) points2_norm = cv2.undistortPoints(points2.reshape(-1, 1, 2), K, None) points4d = cv2.triangulatePoints(P1, P2, points1_norm, points2_norm) points3d = cv2.convertPointsFromHomogeneous(points4d.T) # 将三维点云转换为矩阵形式 points3d_mat = np.zeros((points3d.shape[0], 3)) for i in range(points3d.shape[0]): points3d_mat[i] = points3d[i][0] ``` 其中,`f`、`cx` 和 `cy` 分别为相机的焦距和主点坐标,`P1` 和 `P2` 分别为两张照片的投影矩阵,可以使用相机内部参数矩阵相机外部参数矩阵计算得到。 3. 对相机的位置和姿态进行优化,得到最优的相机外部参数,包括旋转矩阵平移向量。可以使用 OpenCV 中的 `cv2.solvePnP()` 函数进行优化。 ```python # 优化相机的外部参数 retval, rvec, tvec, inliers = cv2.solvePnPRansac(points3d_mat, points2, K, None) # 将旋转向量转换为旋转矩阵 R, _ = cv2.Rodrigues(rvec) ``` 其中,`points3d_mat` 和 `points2` 分别为三维点云和对应的像素坐标,`K` 和 `None` 分别为相机的内部参数矩阵和畸变参数,`rvec` 和 `tvec` 分别为相机的旋转向量和平移向量,`R` 为相机旋转矩阵。 最后得到的 `R` 和 `tvec` 分别为相机旋转矩阵平移向量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

残月独悬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值