slam14讲 双目图像生成点云并保存pcd点云 代码

本文是在slam14讲的ch5 双目生成点云的代码基础上增加了保存功能,

代码写的一般,第一次上传代码,见谅。

 

双目点云生成并保存

#include 
#include 
#include 
#include //Eigen核心模块
#include 
#include 

using namespace std;
using namespace Eigen;
 
// 文件路径
string left_file = "../left.png";
string right_file = "../right.png";
 
//string left_file = "./left.png";
//string right_file = "./right.png";//该方法需要把两张图像放在build文件夹下面
 
 
// 在pangolin中画图,已写好,无需调整
void showPointCloud(
    const vector> &pointcloud);
 
int main(int argc, char **argv) {
 
    // 内参
    double fx = 718.856, fy = 718.856, cx = 607.1928, cy = 185.2157;
    // 基线
    double b = 0.573;
 
    // 读取图像
    cv::Mat left    = cv::imread(left_file, 0);//0表示返回一张灰度图
    cv::Mat right = cv::imread(right_file, 0);//0表示返回一张灰度图
    cv::Ptr sgbm = cv::StereoSGBM::create(
        0, 96, 9, 8 * 9 * 9, 32 * 9 * 9, 1, 63, 10, 100, 32);    //关于sgbm算法的经典参数配置
    cv::Mat disparity_sgbm, disparity;
    sgbm->compute(left, right, disparity_sgbm);
    disparity_sgbm.convertTo(disparity, CV_32F, 1.0 / 16.0f); //注意disparity才是最后的视差图
 
    // 生成点云
    vector> pointcloud;//前三维为X,Y,Z,表示位置信息,后一维表示颜色信息,在此处为灰度
 
    // 如果你的机器慢,请把后面的v++和u++改成v+=2, u+=2
    for (int v = 0; v < left.rows; v++)
        for (int u = 0; u < left.cols; u++) 
        {
            //设置一个Check,排除视差不在(10.0, 96.0)范围内的像素点
            if (disparity.at(v, u) <= 0.0 || disparity.at(v, u) >= 96.0) continue;
            Vector4d point(0, 0, 0, left.at(v, u) / 255.0); // 前三维为xyz,第四维为颜色 创建一个Vector4d类型的变量,前三维用来存储位置信息,后一维为归一化之后的灰度
 
            // 根据双目模型计算 point 的位置  根据双目模型恢复像素点的三维位置
            double x = (u - cx) / fx;
            double y = (v - cy) / fy;
            double depth = fx * b / (disparity.at(v, u));
            
            //将X,Y,Z赋值给point的前三维  
            point[0] = x * depth;
            point[1] = y * depth;
            point[2] = depth;
            pointcloud.push_back(point);
        }

    //save pointcloud
    cout<> &pointcloud) {
 
    if (pointcloud.empty()) {
        cerr << "Point cloud is empty!" << endl;
        return;
    }
    //创建一个pangolin窗口
    pangolin::CreateWindowAndBind("Point Cloud Viewer", 1024, 768);//分别表示窗口名Point Cloud Viewer、窗口宽度=1024和窗口高度=768
    glEnable(GL_DEPTH_TEST);//根据物体远近,实现遮挡效果
    glEnable(GL_BLEND); //使用颜色混合模型,让物体显示半透明效果
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//GL_SRC_ALPHA表示使用源颜色的alpha值作为权重因子,GL_ONE_MINUS_SRC_ALPHA表示使用(1-源颜色的alpha值)作为权重因子
 
    pangolin::OpenGlRenderState s_cam(
        pangolin::ProjectionMatrix(1024, 768, 500, 500, 512, 389, 0.1, 1000),
        pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0)
    );
   //ProjectionMatrix()中各参数依次为图像宽度=1024、图像高度=768、fx=500、fy=500、cx=512、cy=389、最近距离=0.1和最远距离=1000
   //ModelViewLookAt()中各参数为相机位置,被观察点位置和相机哪个轴朝上
   //比如,ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0)表示相机在(0, -0.1, -1.8)位置处观看视点(0, 0, 0),并设置相机XYZ轴正方向为(0,-1,0),即右上前
 
   //创建交互视图,显示上一帧图像内容
    pangolin::View &d_cam = pangolin::CreateDisplay()
        .SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -1024.0f / 768.0f)
        .SetHandler(new pangolin::Handler3D(s_cam));
   //SetBounds()内的前4个参数分别表示交互视图的大小,均为相对值,范围在0.0至1.0之间
   //第1个参数表示bottom,即为视图最下面在整个窗口中的位置
   //第2个参数为top,即为视图最上面在整个窗口中的位置
   //第3个参数为left,即视图最左边在整个窗口中的位置
   //第4个参数为right,即为视图最右边在整个窗口中的位置
   //第5个参数为aspect,表示横纵比
 
 
    while (pangolin::ShouldQuit() == false) //如果pangolin窗口没有关闭,则执行
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清空颜色和深度缓存,使得前后帧不会互相干扰
 
        d_cam.Activate(s_cam);//激活显示,并设置相机状态
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//设置背景颜色为白色
 
        glPointSize(2);
        glBegin(GL_POINTS); //绘制点云
        for (auto &p: pointcloud) {
            glColor3f(p[3], p[3], p[3]); //设置颜色信息
            glVertex3d(p[0], p[1], p[2]);//设置位置信息
        }
        glEnd();
        pangolin::FinishFrame();//按照上面的设置执行渲染
        usleep(5000);   // sleep 5 ms 停止执行5毫秒
    }
    return;

}

你可能感兴趣的:(opencv,计算机视觉,c++)