基于Win10+OpenCV3.4.1+PCL1.8环境,使用双目立体视差图进行三维点云的重建。

原理

使用双目视差图重建三维点云的原理其实很简单,与使用RGB-D相机进行三维点云重建的过程并没有太大区别,主要是通过双目立体视觉获取物体的深度信息( Z c Z_c Zc​),并计算 X c 、 Y c X_c、Y_c Xc​、Yc​坐标值,配合原图提供的RGB信息,即可构成三维点云(PointXYZRGB)。

  • 双目立体视觉获取视差图和深度图的原理可参考: 双目视觉测距原理深度剖析:一个被忽略的小问题
  • 三维点云重建相关流程可参考:三维重建技术概述

代码

/*
相机参数:cam0 = [4152.073 0 1288.147; 0 4152.073 973.571; 0 0 1]cam1 = [4152.073 0 1501.231; 0 4152.073 973.571; 0 0 1]doffs = 213.084    baseline = 176.252width = 2872height = 1984
相机内参数矩阵:K=[fx 0 u0; 0 fy v0; 0 0 1]doffs = |u1 - u0|
*/#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <opencv2/opencv.hpp>  using namespace cv;
using namespace std;
using namespace pcl;int user_data;
// 相机内参
const double u0 = 1288.147;
const double v0 = 973.571;
const double fx = 4152.073;
const double fy = 4152.073;
const double baseline = 176.252;
const double doffs = 213.084;  // 代表两个相机主点在x方向上的差距, doffs = |u1 - u0|void viewerOneOff(visualization::PCLVisualizer& viewer)
{viewer.setBackgroundColor(0.0, 0.0, 0.0);
}int main()
{// 读入数据Mat color = imread("im0.png"); // RGBMat depth = imread("disp0.png",IMREAD_UNCHANGED);// depthif (color.empty() || depth.empty()){cout << "The image is empty, please check it!" << endl;return -1;}// 相机坐标系下的点云PointCloud<PointXYZRGB>::Ptr cloud(new PointCloud<PointXYZRGB>);for (int row = 0; row < depth.rows; row++) {for (int col = 0; col < depth.cols; col++){ushort d = depth.ptr<ushort>(row)[col];if (d==0)continue;PointXYZRGB p;// depth         p.z = fx * baseline / (d + doffs); // Zc = baseline * f / (d + doffs)p.x = (col - u0) * p.z / fx; // Xc向右,Yc向下为正p.y = (row - v0) * p.z / fy;p.y = -p.y;  // 为便于显示,绕x轴三维旋转180°p.z = -p.z;// RGBp.b = color.ptr<uchar>(row)[col * 3];p.g = color.ptr<uchar>(row)[col * 3 + 1];p.r = color.ptr<uchar>(row)[col * 3 + 2];cloud->points.push_back(p);}}cloud->height = depth.rows;cloud->width = depth.cols;cloud->points.resize(cloud->height * cloud->width);visualization::CloudViewer viewer("Cloud Viewer");viewer.showCloud(cloud);viewer.runOnVisualizationThreadOnce(viewerOneOff);while (!viewer.wasStopped()){user_data = 9;}return 0;
}

有一点需要注意的是,在计算 ( X c , Y c ) (X_c,Y_c) (Xc​,Yc​)时,如果按照如下公式计算:
{ X c = ( u − u 0 ) ∗ Z c / f x Y c = ( v − v 0 ) ∗ Z c / f y \begin{cases} X_c=(u - u_0) * Z_c / f_x \\ Y_c=(v - v_0) * Z_c / f_y \\ \end{cases} {Xc​=(u−u0​)∗Zc​/fx​Yc​=(v−v0​)∗Zc​/fy​​

则所得坐标以: x x x轴向右、 y y y轴向下为正方向,如下图。

图像坐标系与相机坐标系的关系

因此,为了正常显示,需要将结果绕 x x x轴旋转180°(三维旋转)。而绕 x x x轴进行三维旋转的变换矩阵如下所示:

取 Θ = 180 ° \Theta=180° Θ=180°,可知绕 x x x轴旋转180°,即相当于:
{ y ′ = − y z ′ = − z \begin{cases} y^\prime=-y \\ z^\prime=-z \\ \end{cases} {y′=−yz′=−z​

结果如图:

素材及处理

博主使用的RGB和depth图取自:vision middlebury_Adirondack,大家可自行下载。

  • 问题
    因为middlebury提供的groundtruth是.pfm格式的文件,而OpenCV是不支持.pfm格式文件操作的,因此就需要自己造“轮子”或者转成OpenCV支持的格式。
  • 解决方法
    这里使用的是图片格式在线转换工具,将.pfm格式图片转成.png格式:多种格式在线互转网站,亲测好用。
    当然,github上大神也提供了开源的“轮子”,可直接读入.pfm文件并转成Mat格式:点击此处链接,操作十分简单,如下是作者给出的例子。
/*** Example of how to read and save PFM files.*/#include <iostream>
#include <string>#include "PFMReadWrite.h"using namespace std;
using namespace cv;int main(void)
{//Example that loads an image and stores it under another nameMat image = loadPFM(string("image.pfm"));//Display the imageimshow("Image", image);waitKey(0);savePFM(image, "image_saved.pfm");return 0;
}

备注:

  • 上述代码同样支持其他图片,只要修改对应的相机内参即可。
  • 所有相关文件下载【CSDN】:双目立体视差图进行三维点云重建【OpenCV3.4.1+PCL1.8】
  • 参考:用VS+Opencv3.1从双目立体视差图中重建三维点云

由双目立体视差图重建三维点云【Win10+OpenCV3.4.1+PCL1.8】相关推荐

  1. 基于语义图的三维点云场景识别

    标题:Semantic Graph Based Place Recognition for 3D Point Clouds 作者:Xin Kong, Xuemeng Yang , Guangyao Z ...

  2. 从单张图重建三维人体模型综述(四)

    <Temporal Consistency Loss for High Resolution Textured and Clothed 3D Human Reconstruction from ...

  3. 从单张图重建三维人体模型综述(三)

    <Multi-View Consistency Loss for Improved Single-Image 3D Reconstruction of Clothed People> 我们 ...

  4. 摄像机模型和双目建模三维点云的理解

    1.世界坐标系一点P(Xw,Yw,Zw)转换到摄像机坐标系为(Xc,Yc,Zc) 其中R表示旋转矩阵,T表示平移矩阵 2.摄像机坐标系点(Xc,Yc,Zc)映射到图像坐标系的p(x,y)转换关系用到了 ...

  5. SfM多视图三维点云重建--【VS2015+OpenCV3.4+PCL1.8】

    难点 在完成两视图三维重建之后,接下来就是进行多视图重建.多视图重建的难点在于如何确定第 i i i( i i i>2)个相机到世界坐标系的位姿变换矩阵. 两视图重建时,是将第一个相机所在的坐标 ...

  6. SfM三维点云重建:BA优化--【VS2015+OpenCV3.4+PCL1.8】

    前言 在SfM多视图三维点云重建–[VS2015+OpenCV3.4+PCL1.8]中实现的增量式SfM三维点云重建,会随着图片数量的增加而导致误差逐渐累积,最后可能无法完成重建.在三维重建中常使用B ...

  7. VTK修炼之道56:图形基本操作进阶_表面重建技术(三维点云曲面重建)

    1.点云重建 虽然Delaunay三角剖分算法可以实现网格曲面重建,但是其应用主要在二维剖分,在三维空间网格生成中遇到了问题.因为在三维点云曲面重建中,Delaunay条件不在满足,不仅基于最大最小角 ...

  8. 【CC精品教程】任务三:CC刺像控点,提交空三,新建重建项目(三维格网、三维点云、DOM和DSM)

    <无人机航空摄影测量精品教程>合集目录(Pix4d.CC.EPS.PhotoScan.Inpho) [CC精品教程]任务一:CC新建工程.添加照片.相机参数设置.选择坐标系统 [CC精品教 ...

  9. VTK 三维 重建 切割 三维点云

    VTK 三维 重建 切割 三维点云 采用QT/C++/VTK QQ:1670386358 欢迎交流 加载dicom 支持CT,MR,PT,DX,CR,XA,US多种dicom浏览,支持Jpeg和Jpe ...

最新文章

  1. 3168串口java_电子称串口读取数据(转)
  2. 数据备份_「Cassandra实战」Cassandra数据备份
  3. CMake 指定安装目录
  4. Java程序员必看!2021Java大厂面试知识分享
  5. 实验三编程、编译、连接、跟踪
  6. CCF-百度松果基金闭门研讨会成功举办,百度飞桨提供基金平台支持
  7. C语言使用递归算法实现Sudoku Solver算法(附完整源码)
  8. 【C语言】控制台窗口图形界面编程(一)句柄和文本属性
  9. 将jar文件转换成exe可执行文件[转]
  10. 进程handle获取线程_获取进程中的线程列表
  11. DBDesigner 4 与 MySql 5 不能连接主要是驱动的原因
  12. CSS揭秘(二)背景与边框
  13. 今天的考核题目: 你知道React和Vue的区别吗? skr,skr
  14. java主流微服务框架_Spring Boot作为当下最流行的微服务开发框架,一名合格的Java开发者一定有所了解,...
  15. centos-install-kong-cassandra
  16. android CheckBox的运用
  17. Idea导出项目jar包
  18. 计算机端口错误678,Win8宽带连接出现错误678的解决方法
  19. FPGA 主流芯片选型指导和命名规则(一)
  20. 单片机移频防啸叫_JDS M-9108全自动高速移频反馈抑制器 会议鹅颈话筒麦克风防啸叫...

热门文章

  1. JS-实现类似于高考倒计时的倒计时时差
  2. Django计算机毕业设计网上商城比价系统python(源码程序+lw+远程部署)
  3. scrapy-cluster : socket.error: [Errno 98] Address already in use解决方法
  4. 安卓适配 全面屏的适配(小米MIX2 的适配)
  5. 弘辽科技:淘宝开店进货一般进多少款?开店要多少钱?
  6. c语言求一元方程的根
  7. php模板生成器,phpcms 模板标签生成器下载
  8. JS jQuery显示隐藏div的几种方法
  9. C++ multimap
  10. 研究生毕业1年论文被抽检不合格,网友喊话:翟天临,你睡了吗?