Realsense相机的RGB与depth图像的对齐

news2024/11/15 10:49:46

第三部分 将RGB图像和Depth图像对齐


文章目录

  • 第三部分 将RGB图像和Depth图像对齐
  • 前言
  • 一、创建对齐的cpp文件
    • 1.用vim创建C++文件
  • 二、使用CMake构建C++工程
    • 1.创建并编写CMakeList.txt文件
    • 2.编译CMakeLists.txt
  • 总结


前言

将RGB图像和深度图像对齐有两种方式,一种是将深度图对齐到RGB图像上,另一种是将RGB图像对齐到深度图上。此处采用的是第一种将深度图对齐到RGB图上。


一、创建对齐的cpp文件

1.用vim创建C++文件

在指定文件夹下进入终端,并输入以下代码创建cpp文件:

vim duiqi.cpp

回车后进入编辑界面:
请添加图片描述
按键盘“i”进入编辑模式,输入C++代码。

对齐的代码如下:

#include <iostream>
using namespace std;
#include <sstream>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <opencv2/opencv.hpp>
using namespace cv;
#include <librealsense2/rs.hpp>
// 获取深度像素对应长度单位转换
float get_depth_scale(rs2::device dev);
// 检查摄像头数据管道设置是否改变
bool profile_changed(const std::vector<rs2::stream_profile> &current, const std::vector<rs2::stream_profile> &prev);
int main(int argc, char *argv[])
try
{
    // 创建 opencv 窗口
    const char *depth_win = "depth_Image";
    namedWindow(depth_win, WINDOW_AUTOSIZE);
    const char *color_win = "color_Image";
    namedWindow(color_win, WINDOW_AUTOSIZE);
    // 深度图像颜色
    rs2::colorizer c;
    // 创建数据管道
    rs2::pipeline pipe;
    rs2::config pipe_config;
    pipe_config.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
    pipe_config.enable_stream(RS2_STREAM_COLOR, 640, 480, RS2_FORMAT_RGB8, 30);
    // start() 函数返回数据管道的profile
    rs2::pipeline_profile profile = pipe.start(pipe_config);
    // rs2::pipeline_profile profile = pipe.start();
    // 使用数据管道的 profile 获取深度图像像素对应于长度单位(米)的转换比例
    float depth_scale = get_depth_scale(profile.get_device());
    cout << "depth_scale = " << depth_scale << endl;
    // 选择彩色图像数据流来作为对齐对象
    rs2_stream align_to = RS2_STREAM_COLOR; // 对齐的是彩色图,所以彩色图是不变的
    // // 将深度图对齐到RGB图
    rs2::align align(align_to);
    while (getWindowProperty(depth_win, WND_PROP_AUTOSIZE) && getWindowProperty(color_win, WND_PROP_AUTOSIZE))
    {
        // 堵塞程序直到新的一帧捕获
        rs2::frameset frameset = pipe.wait_for_frames();
        // 正在对齐深度图到其他图像流,我们要确保对齐的图像流不发生改变
        if (profile_changed(pipe.get_active_profile().get_streams(), profile.get_streams()))
        {
            // 如果profile发生改变,则更新align对象,重新获取深度图像像素到长度单位的转换比例
            profile = pipe.get_active_profile();
            align = rs2::align(align_to);
            depth_scale = get_depth_scale(profile.get_device());
        }
        // 获取对齐后的帧
        auto processed = align.process(frameset);
        // 尝试获取对齐后的深度图像帧和其他帧
        rs2::frame aligned_color_frame = processed.get_color_frame();                 // RGB图
        rs2::frame aligned_depth_frame = processed.get_depth_frame().apply_filter(c); // 深度图
        // 获取对齐之前的color图像
        rs2::frame before_depth_frame = frameset.get_depth_frame().apply_filter(c); // 获取对齐之前的深度图
        // 获取宽高
        const int depth_w = aligned_depth_frame.as<rs2::video_frame>().get_width();
        const int depth_h = aligned_depth_frame.as<rs2::video_frame>().get_height();
        const int color_w = aligned_color_frame.as<rs2::video_frame>().get_width();
        const int color_h = aligned_color_frame.as<rs2::video_frame>().get_height();
        const int b_color_w = before_depth_frame.as<rs2::video_frame>().get_width();
        const int b_color_h = before_depth_frame.as<rs2::video_frame>().get_height();
        // 如果其中一个未能获取,继续迭代
        if (!aligned_depth_frame || !aligned_color_frame)
        {
            continue;
        }
        // 创建opencv类型,并传入数据
        Mat aligned_depth_image(Size(depth_w, depth_h), CV_8UC3, (void *)aligned_depth_frame.get_data(), Mat::AUTO_STEP);
        Mat aligned_color_image(Size(color_w, color_h), CV_8UC3, (void *)aligned_color_frame.get_data(), Mat::AUTO_STEP);
        Mat before_depth_image(Size(b_color_w, b_color_h), CV_8UC3, (void *)before_depth_frame.get_data(), Mat::AUTO_STEP);
        // 彩色图RGB转BGR
        cvtColor(aligned_color_image, aligned_color_image, COLOR_RGB2BGR);
        // 显示
        imshow(depth_win, aligned_depth_image);
        imshow(color_win, aligned_color_image);
        imshow("before aligned depth Image", before_depth_image);
        waitKey(10);
    }
    return EXIT_SUCCESS;
}
catch (const std::exception &e)
{
    std::cerr << e.what() << '\n';
}
float get_depth_scale(rs2::device dev)
{
    // 遍历设备的传感器
    for (rs2::sensor &sensor : dev.query_sensors())
    {
        // 检查传感器是否是深度传感器
        if (rs2::depth_sensor dpt = sensor.as<rs2::depth_sensor>())
            return dpt.get_depth_scale();
    }
    throw std::runtime_error("Device does not have a depth sensor");
}
bool profile_changed(const std::vector<rs2::stream_profile> &current, const std::vector<rs2::stream_profile> &prev)
{
    for (auto &&sp : prev)
    {
        // if previous profile is in current ( maybe just added another)
        auto itr = std::find_if(std::begin(current), std::end(current), [&sp](const rs2::stream_profile &current_sp)
                                { return sp.unique_id() == current_sp.unique_id(); });
        if (itr == std::end(current))
        {
            return true;
        }
    }
    return false;
}

输入完毕后,按“ESC”健进入命令模式,输入“:wq”保存并退出文本编辑器。
在这里插入图片描述
在这里插入图片描述

C++文件即被创建完毕。

二、使用CMake构建C++工程

1.创建并编写CMakeList.txt文件

使用VScode打开项目文件
在这里插入图片描述
在项目目录中,New File一个CMakeLists.txt:
在这里插入图片描述
将下段代码复制进CMakeList.txt文件中,并保存:

cmake_minimum_required(VERSION 3.1.0)
project(realsense)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
set(DEPENDENCIES realsense2 ${OpenCV_LIBS})
add_executable(duiqi duiqi.cpp)
target_link_libraries(duiqi ${DEPENDENCIES})

在这里插入图片描述
保存后的结果如下:
在这里插入图片描述

2.编译CMakeLists.txt

  1. 在当前目录下,创建build文件夹
mkdir build
  1. 进入到build文件夹
cd build
  1. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
 cmake ..
  1. 执行make命令,生成target
make

示例如下:
在这里插入图片描述
5.在命令行输入“./duiqi",执行build文件夹下生成的可执行文件

./duiqi

在这里插入图片描述
6.对齐后的结果如图:
在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了如何将RGB图像和深度图像对齐。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音视频开发-第一章-H264编解码

目录参考原文一、概述二、封装格式2.1、视频文件封装格式2.2、音视频编码方式2.2.1、视频编码方式2.2.2、音频编码方式三、H264相关概念3.1、H264基本单元3.2、帧类型3.3、GOP(画面组)3.4、IDR 帧四、H264压缩方式4.1、H264压缩方式4.2、H264压缩方式说明五、H264分层结构5.1、…

【websocket】前端websocket 实时通信

前端websocket 实时通信 文章目录前端websocket 实时通信什么是websocket为什么传统的http协议不能做到websocket实现的功能websocket前后端所用到的事件对比WebSocket.readyState代码什么是websocket websocket是HTML5开始提供的一种网络通信协议&#xff0c;它诞生的目的是在…

60条小妙招帮助你开车更省油

1、把备胎和千斤顶&#xff0c;工具&#xff0c;都放在家里&#xff0c;不跑长途不带这些&#xff0c;省油。2、说明书上说92号或以上标号&#xff0c;那么加95号油省油。如果是95或以上的标注&#xff0c;那就加98省油。3、驾驶中尽量减少急加速 急刹车&#xff0c;省油。4、驾…

Java——多态

好久不见啊&#xff0c;兄弟们&#xff01;&#xff01;这不将近期末考试了吗&#xff0c;阿涛平日里课听的不多&#xff0c;所以最近都在疯狂补课&#xff0c;祖宗之法也可变&#xff0c;阿涛的学校终于不是二十周校历了&#xff01;&#xff01;希望从今往后我们的生活都能够…

[oeasy]python0041_ 转义字符_转义序列_escape_序列_sequence

转义序列 回忆上次内容 上次回顾了5bit-Baudot博多码的来历从 莫尔斯码 到 博多码 原来 人 来 收发电报 现在 机器 来 收发电报 输入方式 从 电键改成 键盘 输出方式 从 纸带变成 打印纸张 后来 电传打字机ASR-33成为 初代 经典终端 除了 \n 和 \r 之外 还有什么 特殊字符 吗…

前端格式化工具使用(eslint、stylelint、prettier、lint-staged和husky搭配格式化代码)

目录 eslint 安装eslint .eslintrc.js env extends parser parserOptions rules globals plugins 屏蔽eslint检测具体规则 官方规则 stylelint 安装stylelint 创建stylelint配置文件 .eslintrc.js extends sass文件的格式检查 prettier 安装使用prettier …

Vue组件-插槽

一、插槽 1. 组件的三大核心&#xff1a;属性&#xff08;data、props&#xff09;、事件、插槽 2. 插槽&#xff08;slot&#xff09; 插槽&#xff08;slot&#xff09;将父组件的内容与子组件的模板相混合&#xff0c;从而弥补了视图的不足。 插槽的目的&#xff1a;使组件…

ConstraintLayout2

ConstraintLayout2ImageFilterView 属性 app:altSrc&#xff1a;altSrc提供的资源将会和src提供的资源通过crossfade属性形成交叉淡化效果。默认情况下,crossfade0&#xff0c;altSrc所引用的资源不可见,取值在0-1app:saturation&#xff1a;float型&#xff0c;默认1&#xf…

FPGA知识汇集-时钟系统的移植

ASIC 和FPGA芯片的内核之间最大的不同莫过于时钟结构。ASIC设计需要采用诸如时钟树综合、时钟延迟匹配等方式对整个时钟结构进行处理&#xff0c;但是 FPGA设计则完全不必。因为后者有内建的时钟资源:锁相环、频率综合器、移相器&#xff0c;以及具有低延迟特性的专用时钟布线网…

Unity基于状态机的架构与设计

我们做游戏的时候经常会有流程控制&#xff0c;流程控制的方法有很多&#xff0c;行为决策树&#xff0c;状态机等。本质差别都不大&#xff0c;就是把每一段执行逻辑做成一个一个的节点&#xff0c;根据条件执行某个节点&#xff0c;切换到某个节点。今天给大家分享一下基于状…

如何在VSCode中添加Python解释器并安装Python库

如何在VSCode中添加Python解释器并安装Python库作者介绍一&#xff0e; 安装VScode编辑器二&#xff0e; 安装Python解释器三&#xff0e; 在VScode中添加Python解释器四&#xff0e; 创建项目并在VScode中打开&#xff1b;五、在VScode中安装Python库作者介绍 孟莉苹&#xf…

【TypeScript入门】TypeScript入门篇——对象

对象其实就是一种封装的概念&#xff0c;它把事物封装成一个类&#xff0c;然后提供类的接口&#xff0c;而具体的过程人们是看不到的。 一、对象实例 二、TypeScript 类型模板 三、鸭子类型(Duck Typing) 对象是包含一组键值对的实例。 值可以是标量、函数、数组、对象等&am…

Linux常用命令——lsof命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) lsof 显示Linux系统当前已打开的所有文件列表lsof -p pid 补充说明 lsof命令用于查看你进程打开的文件&#xff0c;打开文件的进程&#xff0c;进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系…

十四、Node.js 中 session验证登录

在前一篇内容中讲到这个cookie实现验证登录&#xff0c;cookie是存储在客户端的&#xff0c;而session是存储在服务器的&#xff0c;相比较session的安全性会更高&#xff0c;session对象存储特定用户会话所需要的属性以及配置信息&#xff0c;服务通过session对象将用户的信息…

CPU使用率过高的原因及解决方法

常见的CPU使用率过高可不是职场CPU哦&#xff0c;而是电脑的中央处理器&#xff0c;CPU作为计算机系统重要的运算和控制核心&#xff0c;可谓是“很忙”的存在。在我们日常使用电脑设备时&#xff0c;由于打开的软件、游戏、网页等程序容易导致电脑运作卡顿&#xff0c;这时候就…

《图机器学习》-Traditional Methods for Machine Learning in Graphs

Traditional Methods for Machine Learning in Graphs前言一、Node-Level Tasks and Features二、Link-Level Tasks and Features三、Graph-Level Tasks and Features前言 图机器学习任务可以分为三种&#xff1a; Node-level prediction&#xff1a;节点级的预测 如对节点进…

最优控制学习笔记3----无约束条件的泛函极值问题

无约束条件的最优控制问题 设函数 x(t)x(t)x(t) 在 [t0,tf][t_0, t_f][t0​,tf​] 区间上连续可到&#xff0c;考虑 Lagrange型性能指标函数 J[x(t)]∫t0tfL[x(t),x˙(t),t]dtJ[x(t)]\displaystyle\int_{t_0}^{t_f}L[x(t), \dot{x}(t), t]dtJ[x(t)]∫t0​tf​​L[x(t),x˙(t),…

Linux---常见指令

目录 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令 06.rmdir指令 && rm 指令 07.man指令 08.cp指令 09.mv指令 10. cat指令 11.more指令 12.less指令 13.head指令 13.tail指令 简述重定向和管道概念&#xff1a; 14.时间相关的指令 15.Ca…

Git Fork操作与配置

我理解的git fork&#xff1a;将别人&#xff08;张三&#xff09;仓库包括文件&#xff0c;提交历史&#xff0c;issues等复制一份到自己的github账号下。我们在可以通过修改本地项目的代码&#xff0c;然后&#xff0c;给&#xff08;张三&#xff09;发送一个Merge Request&…

C. Yet Another Tournament(贪心)

Problem - C - Codeforces 通用领域 医学 计算机 金融经济 你正在参加另一场比赛。有n1个参与者:你和其他n个对手&#xff0c;编号从1到n。 每两名参与者将相互竞争一次。如果对手i和对手j比赛&#xff0c;他获胜当且仅当i>j。 当我的对手和你对弈时&#xff0c;一切都变…