SLAM学习笔记

2023-05-16

编译环境ubuntu20.04,vs code

先cmake文件

cmake_minimum_required(VERSION 2.8)
project(image)

set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++17")
find_package(OpenCV REQUIRED)
find_package( Pangolin REQUIRED)
find_package( Sophus REQUIRED)

include_directories("/usr/include/eigen3")
include_directories(${Pangolin_INCLUDE_DIRS})

add_executable(img image.cpp)
add_executable(distort undistort.cpp)
add_executable(stereo stereoVision.cpp)
add_executable(joint jointMap.cpp)



target_link_libraries(img ${OpenCV_LIBS})

target_link_libraries(distort ${OpenCV_LIBS})

target_link_libraries(stereo ${OpenCV_LIBS} ${Pangolin_LIBRARIES})

target_link_libraries(joint ${OpenCV_LIBS} ${Pangolin_LIBRARIES})
target_link_libraries(joint Sophus::Sophus)

然后是双目视觉

#include <opencv2/opencv.hpp>
#include <Eigen/Core>
#include <iostream>
#include <pangolin/pangolin.h>
#include <unistd.h>
using namespace std;
using namespace Eigen;

string left_file = "/home/martin/桌面/code/image/left.png";
string right_file = "/home/martin/桌面/code/image/right.png";
void showPointCloud(const vector<Vector4d, Eigen::aligned_allocator<Vector4d>> &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);                                     //读图
    cv::Mat right = cv::imread(right_file, 0);
    cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create(                        
        0,96,9,8*9*9,32*9*9,1,63,10,100,2);
    /*双目立体匹配算法
    参数含义解释(按顺序):
    int minDisparity 最小差异值,通常是0,在个别情况需要进行改动,比如整流算法将图像改变
    int numDisparities 最大差异减去最小差异。首先这个数字得大于零,其次还得能被16整除
    int blockSize 匹配的块大小。必须是大于等于1的奇数,通常取值在3~11内
    int P1 控制视差平滑度的第一个参数
    int P2 控制视差平滑度的第二个参数。这两个值越大,差异越平滑。P1是相邻像素之间的视差变化正负1的惩罚
           P2是相邻像素之间视差超过1的惩罚。算法要求P2>P1。
    int disp12MaxDiff 左右视差检查中允许的最大差异。设为非正值即禁用该功能
    int preFilterCap 预滤波图像像素的截断值。
                     该算法先计算每个像素的导数,用[-preFilterCap,perFilterCap]间断剪切,
                     最后将结果传递给Birchfield-Tomas像素成本函数。(取值1~63)
    int uniquenessRatio 视差唯一性百分比,视差窗口范围内最低代价是次低代价的(1+uniquenessRatio/100)倍时,
                        最低代价对应的视差值才是该像素点的视差,否则视差置0(一般5~15)
    int speckleWindowSize 平滑视差区域的最大尺寸,0的话是禁用斑点过滤,一般50~200
    int speckleRange 每个连接组件内的最大视差变化。(会被隐式乘以16)一般1或2 ||所以我不太理解高博的32是什么意思
    int mode 设置为StereoSGBM::MODE_HH以运行全尺寸双通道动态编程算法。默认false(这里直接没写)
    */                                      
    cv::Mat disparity_sgbm,disparity;
    sgbm->compute(left,right,disparity_sgbm);                                     //计算、转换图像类型和画幅
    disparity_sgbm.convertTo(disparity, CV_32F, 1.0/16.0f);

    vector<Vector4d, Eigen::aligned_allocator<Vector4d>> pointcloud;

    for (size_t i = 0; i < left.rows; i++)                                        //生成深度点云
    {
        for (size_t j = 0; j < left.cols; j++)
        {
            if(disparity.at<float>(i,j) <= 0.0 || disparity.at<float>(i,j) >= 96.0)//在宽高范围内获取像素值
            continue;

            Vector4d point (0,0,0, left.at<uchar>(i,j) / 255.0);                  //三维坐标带个颜色

            double x = (j-cx)/fx;                                                 //书上的双目模型
            double y = (i-cy)/fy;
            double depth = fx * b /(disparity.at<float>(i,j));
            point[0] = x*depth;
            point[1] = y*depth;
            point[2] = depth;

            pointcloud.push_back(point);
        }
        
    }
    
    cv::imshow("disparity",disparity / 96.0);
    cv::waitKey(0);

    showPointCloud(pointcloud);
    return 0;

}
//pangolin正常调用生成点云图像----------------------------------------------------------------------
void showPointCloud(const vector<Vector4d, Eigen::aligned_allocator<Vector4d>> &pointcloud)
{
    if (pointcloud.empty()) 
    {
        cerr << "Point cloud is empty!" << endl;
        return;
    }

    pangolin::CreateWindowAndBind("Point Cloud Viewer", 1024, 768);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_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)
    );

    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));

    while (pangolin::ShouldQuit() == false)
    {
        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);   
    }
    return;    
}

最后是点云地图

#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <boost/format.hpp>
#include <pangolin/pangolin.h>
#include "sophus/se3.hpp"
using namespace std;
using namespace Eigen;

//声明同前两次一致
typedef Eigen::Matrix<double,6,1> Vector6d;
typedef vector<Sophus::SE3d,Eigen::aligned_allocator<Sophus::SE3d>> TrajectoryType;
//显示点云的函数
void showPointCloud(const vector<Vector6d, Eigen::aligned_allocator<Vector6d>> &pointcloud);

int main (int argc,char** argv)
{
    vector<cv::Mat> colorImgs, depthImgs;                       //创建两个放置彩色图和深度图的容器
    TrajectoryType poses;                                       //相机姿态

    ifstream fin("/home/martin/桌面/code/image/pose.txt");       //我改成了pose的绝对路径
    if(!fin)
    {
        cerr<<"路径错误"<<endl;
        return 1;
    }

    for (int i = 0; i < 5; i++)                                 //书中的fmt读取文件的方式我改成了绝对路径还是不行
    {
        string img_file = "color.png";                          //我选择用字符串插值(本人c++还是太菜了)
        string dpt_file = "depth.pgm";
        string q = to_string(i+1);
        img_file.insert(5,q);
        dpt_file.insert(5,q);
        cout<<img_file<<endl;
        colorImgs.push_back(cv::imread(img_file));              //逐个读取并尾插进容器
        depthImgs.push_back(cv::imread(dpt_file,-1));

        double data[7] = {0};                                   //姿态读取3456旋转012平移
        for(auto &d:data) fin>>d;                               //c++11新的for遍历,还挺好用的
        Sophus::SE3d pose (Eigen::Quaterniond(data[6],data[3],data[4],data[5]),
                           Eigen::Vector3d(data[0],data[1],data[2]));
        poses.push_back(pose);
        
    }

    double cx = 325.5, cy = 253.5, fx = 518.0, fy = 519.0;      //相机内参
    double depthScale = 1000.0;                           
    vector<Vector6d, Eigen::aligned_allocator<Vector6d>> pointcloud;
    pointcloud.reserve(10000000);

    for (size_t i = 0; i < 5; i++)
    {
        cout<<"图象转换中: "<<i+1<<endl;
        cv::Mat color = colorImgs[i];                           //取出图像容器中的图像
        cv::Mat depth = depthImgs[i];
        Sophus::SE3d T = poses[i];
        
        for (size_t j = 0; j < color.rows; j++)                 //遍历图像
        {
            for (size_t k = 0; k < color.cols; k++)
            {
                unsigned int d = depth.ptr<unsigned short>(j)[k];//读取深度
                if(d==0) continue;                              //深度为零就是没有测到
                Eigen::Vector3d point;
                point[2] = double(d) / depthScale;
                point[0] = (k-cx)*point[2]/fx;
                point[1] = (j-cy)*point[2]/fy;
                Eigen::Vector3d pointworld = T * point;

                Vector6d p;
                p.head<3>() = pointworld;
                p[5] = color.data[j * color.step + k * color.channels()];      //blue
                p[4] = color.data[j * color.step + k * color.channels()+1];    //green
                p[3] = color.data[j * color.step + k * color.channels()+2];    //red
                pointcloud.push_back(p);                                       //拼接
                
            }
            
        }
        
    }

    cout<<"点云共有"<<pointcloud.size()<<"个点"<<endl;
    showPointCloud(pointcloud);
    return 0;
    
}

//和先前的非常像,改动只有两处-------------------------------------------------------------------------
void showPointCloud(const vector<Vector6d, Eigen::aligned_allocator<Vector6d>> &pointcloud)
{
    if (pointcloud.empty()) 
    {
        cerr << "Point cloud is empty!" << endl;
        return;
    }

    pangolin::CreateWindowAndBind("Point Cloud Viewer", 1024, 768);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_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)
    );

    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));

    while (pangolin::ShouldQuit() == false)
    {
        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]/255.0, p[4]/255.0, p[5]/255.0);   //这里两句
            glVertex3d(p[0], p[1], p[2]);
        }
        glEnd();
        pangolin::FinishFrame();
        usleep(5000);   
    }
    return;    
}


c++东西确实多,还得继续学。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SLAM学习笔记 的相关文章

  • GSV2008

    GSV2008 是HDMI2 0 四进二出矩阵 xff0c 自持HDCP2 2 xff0c 支持DOWN SCALER 四个HDMI输入 xff0c 2个HDMI输出 xff0c 自动EQ 应用 xff1a 1 xff0c 功放 ARC C
  • 漏洞挖掘-从任意文件读取漏洞到获取账户利用

    开篇 大家好 xff0c 我是承影战队的v1ct0ry xff0c 这次我为大家分享一次比较有趣的漏洞挖掘经历 这次挖掘过程是以灰盒挖掘为主要思想进行展开 xff0c 不熟悉的读者可以阅读上篇文章熟悉一下 一 任意文件读取 开局我们通过扫描
  • curl命令行工具

    转载 curl 命令行工具的使用及命令参数说明 curl的使用 1 1 URL访问 1 2 表单提交 1 3 其它HTTP请求方法 1 4 文件上传 1 5 HTTPS支持 1 6 添加请求头 1 7 Cookie支持curl语法及选项cu
  • Ubuntu20.4安装ROS系统教程(自用)

    1 Ubuntu各个版本系统对应的ROS版本 1 2Ubuntu16 04与ROS kinetic的安装 1 2 1Ubuntu16 04配置 1 2 2安装ROS kinetic版 1 3Ubuntu18 04和ROS melodic的安
  • UART 空闲中断+DMA接收流程

    在项目中利用UART空闲中断接收外部信号 xff0c 利用DMA接收 xff0c 实现外部到内存的传输 通过分析其它文章的代码 xff0c 大概如下 xff1a span class token comment 配置 DMA Stream
  • 5分钟带你从数据类型了解Java相比C/C++有什么优势

    数据类型是一门语言的血肉 xff0c 通过这5分钟的浏览 xff0c 只学过C C 43 43 的小伙伴会初步了解Java的一些特性 xff0c 学过一点Java的朋友在读完这篇文章后也一定会对Java的语法规范有更深刻的了解 Java数据
  • 备赛电赛学习硬件篇(一):电机部分

    目录 一 电机选型 二 电机的正反转 xff0c 刹车 一 电机选型 1 电机类型 无刷电机较贵 xff0c 但是静音且损耗小 xff0c 由于霍尔元件的特殊性 xff08 不带霍尔需要转速高的时候才可以利用反电动势准确确定转子的位置 xf
  • 【总线】一文看懂RS232和RS485通信总线

    目录 RS232概述 RS232特性 RS485 概述 RS485 特性 RS232 和 RS485 的区别 区别总结 RS232概述 RS 232接口符合电子工业联盟 xff08 EIA xff09 建立的串行数据通信接口标准 原始编号是
  • 【C++学习笔记】vector构造函数

    文章目录 1 vector构造函数说明 xff1a 2 实战 xff1a 2 1 vector构造函数代码示例2 2 输出 3 参考资料 1 vector构造函数说明 xff1a span class token keyword templ
  • 请求报文/相应报文

    一 请求报文分为4个部分 请求行 请求头 请求空行 请求体 1 1 请求行 主要是3个部分 GET 请求方式 1 2 请求地址 所带的参数 demo demo php userName 61 E6 9D 8E E5 9B 9B amp us
  • python+requests——高级用法——auth认证

  • C语言char指针的使用

    在c语言中 xff0c char指针不仅能指向char变量 xff0c 还能指向常量字符串 xff0c 同时也能指向一个char数组的 想要访问单个字符 xff0c 就要通过 来进行解引用 xff0c 若是要访问整个数组或字符串的话 xff
  • HTTP协议的请求格式解析

    HTTP协议是一个使用较多的应用层协议 xff0c 它是一个请求 响应式的一个协议 xff0c 就是我客户端给你发一个请求 xff0c 你客户端需要返回给我一样响应 首先我们来看一下HTTP协议的请求格式 HTTP请求格式 xff1a HT
  • 运行Gazebo+moveit+Rviz,报错,提示无控制器

    在rviz里规划成功后 xff0c 执行显示failed rviz里能规划 xff0c 但是Gazebo里动不了 moveit报错如下 xff1a WARN 1679466487 132361192 26 763000000 Waiting
  • 基于UDP协议搭建的简单客户端与服务器(UDP协议)

    UDP协议 UDP协议的介绍1 UDP的缺点 基于UDP实现的回显服务器基于UDP实现的客户端 UDP协议的介绍 UDP协议特点 xff1a 1 无连接 2 面向数据报 3 不可靠传输 4 全双工 16位源端口号 目的端口号 xff1a 表
  • C++之AStar寻路算法

    仅以记录 有一种算法 名为AStar 它的作用是求图中两点之间的最短路径 沉迷 该算法的我 自己编写了一个版本 注释虽少 但求传神 代码虽 恶心 但求理解 include lt iostream gt include lt vector g
  • 使用livox_viewer2对激光雷达livox_mid360进行调试

    准备 系统 windows10 硬件 xff1a livox mid360 软件 xff1a livox viewer2 测试 连接号激光雷达设备 xff0c 电脑ip相关设置和livox avia一样 livox系列激光雷达ip设置都是一
  • 听说你还不会制作“GIF动图”,手把手包教会,这不就来了吗

    近期 xff0c 看了好多写的博客 xff0c xff08 不管是前端HTML的还是后端Java的 xff0c 前端制作的3D部分的效果图需要展示动图 xff09 发现有点还存在想使用动图 xff0c 但是不会制作 xff0c 又或者是制作
  • HTML+js实现贪吃蛇小游戏(内含完整代码)

    案例分析 看图拆解游戏 首先我们根据图片上的内容把这个游戏拆解成几个部分去单独看 xff1a 最外面的大盒子包裹着内容加边框限制蛇的活动范围 xff0c 整个范围可以看成由许多小方格排列构成的 xff0c 例如这样子的 xff1a xff1
  • 【华为Hilink SDK Linux系统开发】第三章:华为hilink SDK Linux系统网关适配

    mark xff1a https blog csdn net qq 24550925 article details 107282773 关注嘉友创科技公众号 声明 xff1a 文章只做技术交流 xff0c 没有其他任何用途 xff0c 侵

随机推荐

  • 快速去除GIF动图的背景(让背景变透明),保姆级教程

    很多小伙伴在看到好看的动图效果时 xff0c 想用在自己的页面上 xff0c 可是常常会碰到一些动图背景颜色不符合自己的需求 xff0c 所以会产生修改动图背景的想法 xff0c 但是GIF动图终究是GIF动图 xff0c 不像静态图片那样
  • Vue在HTML中如何使用

    x1f440 Vue是什么 一套用于构建用户界面的渐进式JavaScript框架 构建用户界面 xff1a 数据变成界面渐进式 xff1a Vue可以自底向上逐层的应用 x1f440 Vue如何使用 一 引入vue js lt script
  • 简单记录一下怎么看package.json文件

    首先每个vue工程文件从仓库克隆代码下来的时候 xff0c 一般都会包含这个文件 xff0c 这个文件非常重要 xff0c package json包含了关于项目重要信息 xff0c 如下图所示 其中包含了name version desc
  • 项目中常用到的前端vue根据后端接口返回文件地址实现在线预览和下载功能

    简简单单的记录一下项目中做过的东西 项目中时常会有要求查看附件 xff0c 附件的下载的要求 xff0c 在这里简单记录一下前端vue根据后端接口返回文件地址实现在线预览和下载功能 x1f440 文件在线预览 目前我这里使用的是点击a链接跳
  • 记录面试问题

    以下问题不分先后 xff0c 按照印象深浅排序 xff0c 可能一次记录不完成 xff0c 后面想起来会及时补充 xff0c 如有不对 xff0c 恳请各位围观大佬多多指教 x1f64f 印象最深的是一道很简单很简单的题目 xff0c 我结
  • C++中“.“,“->“,“:“和“::“的区别

    在 C 43 43 中 xff0c 34 34 xff0c 34 gt 34 xff0c 34 34 和 34 34 都是运算符 xff0c 它们的作用是明显不同的 xff0c 但是初学者很容易被其迷惑 1 34 34 是成员访问运算符 x
  • ubuntu系统中忘记root密码的解决办法

    1 启动ubuntu按shift进入grub菜单 xff1b 2 选择recovery mode进入Recovery Menu界面 xff0c 选择root Drop to root shell prompt 3 修改root密码操作 xf
  • C++语言实现哈希表中的线性探测法和平方探测法

    哈希表 xff08 Hash表 xff09 xff0c 也称为散列表 xff0c 是一种数据结构 xff0c 通过使用哈希函数将键映射到数组的特定位置来实现高效的查找 插入和删除操作 哈希函数将键转换为一个整数 xff0c 这个整数对应数组
  • C++实现的二叉树前序遍历函数

    include lt iostream gt using namespace std struct TreeNode int val TreeNode left TreeNode right TreeNode int x val x lef
  • c语言和c++实现层序遍历

    层序遍历是一种二叉树的遍历方式 xff0c 也称为广度优先遍历 xff0c 它的遍历顺序是 xff1a 从上到下 xff0c 从左到右 xff0c 一层一层地遍历整棵树 在 C 语言中 xff0c 我们可以使用队列来实现层序遍历 具体实现步
  • C语言获取wifi状态

    mark https blog csdn net dongyoubin article details 122134198 int getWirelessStatus char ath char ssid char ipAddr
  • 最全Visual Studio版本号对应表VisualStudioVersion

    名字 版本号 简称 全称 msvc70 VC7 0 VS2002 Microsoft Visual Studio 2002 msvc71 VC7 1 VS2003 Microsoft Visual Studio 2003 msvc80 VC
  • 二叉树静态实现的示例代码

    使用指针对于初学者容易出现很多困惑 下面是一个完整的二叉树静态实现的示例代码 xff0c 包括初始化 插入节点 各种遍历方法以及一些辅助函数 include lt stdio h gt include lt stdlib h gt defi
  • 广度优先搜索(BFS)算法实现二叉树层序遍历的 C++ 代码

    include lt iostream gt 输入输出流 include lt vector gt 向量容器 include lt queue gt 队列容器 using namespace std 命名空间 定义二叉树节点结构体 stru
  • PAT 1005 Spell It Right

    Given a non negative integer N your task is to compute the sum of all the digits of N and output every digit of the sum
  • 在PC的Ubuntu虚拟机上完成一个TCP 服务器,在设备上实现一个TCP客户端

    要求 在虚拟机上实现一个服务器 xff0c 设备终端上实现一个客户端设备客户端每隔 1 秒 检测一次网卡eth2 1 xff08 WAN口网卡 xff09 的信息 xff08 使用popen调用ifconfig xff09 然后将RX和TX
  • TCP发送数据、接受数据及TCP通信程序练习

    目录 一 TCP发送数据 二 TCP接收数据 三 TCP通信程序练习 一 TCP发送数据 Java中的TCP通信 xff1a Java对于基于TCP协议的网络提供了良好的封装 xff0c 使用Socket对象来代表两端的通信端口 xff0c
  • slam学习笔记

    ubuntu20 04 使用vs code编写 现放cmake文件 xff08 记得链接库文件和配置C 43 43 版本 xff09 cmake minimum required VERSION 2 8 project learingMat
  • SLAM学习笔记

    编译环境ubuntu20 04 vs code xff08 李群 李代数 xff09 先是CMakeLists txt cmake minimum required VERSION 3 0 project learning sophus s
  • SLAM学习笔记

    编译环境ubuntu20 04 xff0c vs code 先cmake文件 cmake minimum required VERSION 2 8 project image set CMAKE BUILD TYPE 34 Release