c++学习【6】三角化获得三维点坐标,并可视化

    Mat T1 = (Mat_<float>(3, 4) <<
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0);
    Mat T2 = (Mat_<float>(3, 4) <<
        R.at<double>(0, 0), R.at<double>(0, 1), R.at<double>(0, 2), t.at<double>(0, 0),
        R.at<double>(1, 0), R.at<double>(1, 1), R.at<double>(1, 2), t.at<double>(1, 0),
        R.at<double>(2, 0), R.at<double>(2, 1), R.at<double>(2, 2), t.at<double>(2, 0)
        );

表示相机的投影矩阵。投影矩阵是一个3x4的矩阵,其中前三列代表相机的旋转和缩放变换(R),第四列代表相机的平移变换(t)。

通过Mat_<>模板类的构造函数,可以直接对Mat对象进行初始化,并使用“<<”运算符来填充矩阵元素。这里创建一个3行4列的单精度浮点型矩阵,<<运算符用于依次填充矩阵的每个元素。

因为已经求得旋转平移了,也就是相机位姿知道。就是R、t是已知的旋转矩阵和平移向量,at函数用于获取矩阵R和t中指定位置的元素值。

// 将像素坐标转换至相机坐标 

    //
    vector<Point2f> pts_1, pts_2;

通过对像素坐标进行归一化,即减去光心的横纵坐标,然后除以焦距,就可以得到相机坐标系下的坐标。最后,函数返回一个Point2f类型的相机坐标。这里假设物体在相机坐标系下的z坐标值为1。

p是输入的待转换的像素坐标,K是相机的内参矩阵。 

Point2f pixel2cam(const Point2d& p, const Mat& K)
{
    return Point2f
    (
        (p.x - K.at<double>(0, 2)) / K.at<double>(0, 0),
        (p.y - K.at<double>(1, 2)) / K.at<double>(1, 1)
    );
}

    for (DMatch m : matches)
    {
        // 将像素坐标转换至相机坐标
        pts_1.push_back(pixel2cam(keypoints_1[m.queryIdx].pt, K));
        pts_2.push_back(pixel2cam(keypoints_2[m.trainIdx].pt, K));
    }

Triangulated points shape: [500 x 4] 

    //
    Mat pts_4d;
    cv::triangulatePoints(T1, T2, pts_1, pts_2, pts_4d);

两个相机的投影矩阵,分别是3x4的矩阵,
对应两个相机图像上的像素点坐标,每个点坐标都是2x1的矩阵
存储三角化后的三维点坐标,每个点坐标都是4x1的齐次坐标,

在函数的执行过程中,triangulatePoints会先将projPoints1projPoints2转换为齐次坐标形式,然后利用两个相机的投影矩阵进行三角化,得到对应的三维点坐标。最终输出的points4D是一个4xN的矩阵,每一列代表一个三维点的齐次坐标。

需要注意的是,triangulatePoints函数输出的三维点坐标是在相机坐标系下表示的归一化坐标。如果需要得到实际的三维坐标,还需要进行后续的坐标变换操作。

  定义了一个存储3D点的向量容器。其中Point3d是一个自定义的类,用于表示三维空间中的点,包括x、y、z三个坐标值。 

    //-- 三D坐标
    vector<Point3d> points;
    // 转换成非齐次坐标
    for (int i = 0; i < pts_4d.cols; i++)
    {
        Mat x = pts_4d.col(i);
        x /= x.at<float>(3, 0); // 归一化
        Point3d p(
            x.at<float>(0, 0),
            x.at<float>(1, 0),
            x.at<float>(2, 0)
        );
        points.push_back(p);
    }

保存成bin文件 

    #include <fstream>

    std::ofstream outfile("points.bin", std::ios::out | std::ios::binary);
    outfile.write((char*)&points[0], points.size() * sizeof(cv::Point3d));
    outfile.close();

500个点

    int num_points = points.size();
    std::cout << "Number of points: " << num_points << std::endl;
    // 将点云数据保存为文本文件
    ofstream file("points.txt");
    for (int i = 0; i < points.size(); i++) {
        Point3d p = points[i];
        file << p.x << " " << p.y << " " << p.z << endl;
    }
    file.close();

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1篇 系统开发基础   包括第1章三维图形世界、第2章OpenGL概述和第3章Oracle与 OCI技术及编程基础。   第1章 介绍了计算三维图形技术的发展、科学计算可视化技术、三维可视化工程设计的基本概念和发展现状。   第2章 主要对OpenGL的基本概念、OpenGL编程基础和在Visual C++环境下OpenGL基本程序框架的建立进行了讲解,并给出了一个简单的旋转立方体程序示例。通过这一章,使读者对OpenGL有初步的概念和了解,对于纹理、显示列表等更深入的编程,我们将通过后续章节进行更详细的讲解和学习。   第3章 主要对Oracle数据库及其特进行简要的介绍和说明。以Oracle 9i为例,介绍了Oracle数据库的安装步骤和Oracle支持的数据类型。在此基础上,介绍了ADO、Pro*C/C++和OCI三个主要Oracle编程接口,对它们的各自功能和特进行了详细说明,从功能方面、性能方面、开发难度方面进行了详细分析和比较。重介绍OCI编程基础、OCI的数据结构、OCI程序的基本结构、OCI执行的步骤,最后给出了在Visual C++6.0环境下开发OCI应用程序的示例。   第2篇 大规模地形三维可视化系统设计与实现   包括第4章地形三维可视化系统框架与OCI类模块设计、第5章地形三维可视化系统的地形渲染实现和第6章地形三维可视化系统项目管理与辅助功能设计。   第4章 在第2章的基础上,完成了基于OpenGL的地形三维可视化系统程序框架的建立,为后续的功能模块开发提供了基础平台;在第3章的基础上,设计了OCI公共类,将所有与OCI有关的数据库操作、数据读取等功能函数实现全部封装在该类中,并定义了公共类的全局变量myOci。   第5章 本章对地形三维可视化进行了基本概述,介绍了目前地形三维可视化的主要算法。主要介绍了海量地形与影像纹理数据的常用获取方法,给出了海量地形自分块与影像纹理分块原则和程序实现,以及地形与影像子块调度的程序实现,在此基础上实现了地形的三维可视化;还介绍了真三维立体的实现算法和数学模型,在此基础上给出了基于OpenGL的真三维立体的程序实现。   第6章 主要讲解了新建项目、打开项目、背景天空的绘制、绘图模式控制的实现方法和程序设计。介绍了基于OpenGL深度缓存的二维屏幕坐标三维空间坐标的转换算法,实现了对三维空间坐标和空间距离查询,以及查询标识设置的程序设计;最后讲解了基于键盘和鼠标联合控制的三维场景照相机程序模块的实现,实现三维场景的前、后、左、右移动和任意方向的旋转。   第3篇 线路三维可视化系统设计与实现   包括第7章三维交互技术与三维线路数据结构、第8章三维线路设计实现、第9章道路整体三维建模和第10章三维漫游的实现。   第7章 主要对三维交互环境进行了介绍,详细讲解了正射投影模式的实现、正射投影模式下场景控制方法和程序设计,以及透视投影模式的实现方法;还讲解了正射投影模式和透视投影模式下三维地面坐标的获取原理、方法,在此基础上,设计了边坡数据结构、桥梁数据结构、隧道数据结构、水沟数据结构及线路数据结构,为实现三维线路设计做好了前期准备。   第8章 主要对线路方案的主要参数设计方法和程序实现、设计交信息输入实现、线路中心线定位方法、设计方案的保存、平面方案的自动生成和程序设计、纵断面设计模块的实现、边坡模型的生成算法、线路路基三维建模方法和实现、隧道三维建模和参数控制、桥梁三维建模和参数控制的程序设计进行了详细讲解。   第9章 主要讲解了道路整体三维模型实现,对其中的线路封闭区域确定与分割算法、地形块综合数据计算、分块TIN模型的构网实现、封闭区域内数据的剔除、整体构网的程序实现都进行了详细说明;在纹理管理部分,详细讲解了边坡纹理、路肩纹理、桥梁护坡面纹理、隧道内墙纹理、隧道洞门纹理的程序设计和实现。   第10章 从多个方面对三维漫游的基本概念、程序实现、参数调整和控制进行了讲解,帮助读者学会在三维可视化系统中三维漫游模块的程序设计方法;对飞行路径的基本概念、设置方法、插值算法、保存和打开的程序设计,沿飞行路径实现三维漫游的程序设计,沿线路方案漫游的固定高度和相对高度两种模式的程序设计,三维漫游控制和调整的程序设计,以及三维漫游的相关计算都进行了详细的讲解,每一部分都给出了完整的程序代码。   第4篇 线路三维可视化系统辅助功能实现   包括第11章显示模式控制及实现、第12章3D模型载入与应用、第13章系统输出接口与动画录制实现和第14章系统简介与运行实例。   第11章 本章主要对双目立体方式、正射投影方式和透视投影方式的显示模型模式控制和实现、时钟指北针的程序设计和实现、缩略图的实现方法和程序设计进行

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值