Realsense相机在linux下的配置使用,RGB与depth图像对齐

目录

非ROS版本

配置

使用

注意:

ROS版本


非ROS版本

配置

要在linux下使用realsense相机,需要首先配置librealsense。我的环境是Ubuntu18.04,相机是D435i相机。

librealsense的地址在点击这里

但是自己编译的时候发现太慢了,根本不知道是卡住了,还是正常进行但是时间比较漫长。很麻烦,建议不要自己编译,而是直接用apt install 的方式来装,这样装又快又省事,官方也给了相关的说明,点击这里

首先,加载key:

sudo apt-key adv --keyserver keys.gnupg.net --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE

对于16.04系统,

sudo add-apt-repository "deb http://realsense-hw-public.s3.amazonaws.com/Debian/apt-repo xenial main" -u

对于18.04系统:

sudo add-apt-repository "deb http://realsense-hw-public.s3.amazonaws.com/Debian/apt-repo bionic main" -u

然后只要安装下面两个就可以了:

sudo apt-get install librealsense2-dkms
sudo apt-get install librealsense2-utils

上面这两个正常的网速来说,每个顶多半个小时。如果卡着很慢,最好是Ctrl+C掉重新来,不要一直等。

在装完之后,插上相机,输入这个指令就可以打开官方提供的GUI面板了:

realsense-viewer

不过,相机需要连接到USB3.0接口而不是2.0接口,否则打开后会报错。


使用

在GUI面板中可以以bag的形式保存拍摄的内容,相信很多人最关心的就是对这个bag的读取,或者说干脆自己通过代码操控相机,更重要的是把RGB图像和depth图像对齐起来,好从某个像素的位置处读取其对应的深度。

我写了一段Python代码,可以读取播放之前通过GUI面板保存的bag,或者实时通过相机拍摄记录视频(这种方式还可以指定图像的拍摄大小,以及拍摄的帧率)

另外还提供了两种功能:把深度图对齐到彩色图像,或者把彩色图像对齐到深度图像。

首先需要装一个包:

pip install pyrealsense2

然后具体代码如下:

#coding=utf-8
import pyrealsense2 as rs
import numpy as np
import cv2

#0:使用相机
# 1:使用API录制好的bag
USE_ROS_BAG=1
#0:彩色图像对齐到深度图;
# 1:深度图对齐到彩色图像
ALIGN_WAY=1

def Align_version(frames,align,show_pic=0):
    # 对齐版本
    aligned_frames = align.process(frames)
    depth_frame_aligned = aligned_frames .get_depth_frame()
    color_frame_aligned = aligned_frames .get_color_frame()
    # if not depth_frame_aligned or not color_frame_aligned:
    #     continue
    color_image_aligned = np.asanyarray(color_frame_aligned.get_data())
    if USE_ROS_BAG:
        color_image_aligned=cv2.cvtColor(color_image_aligned,cv2.COLOR_BGR2RGB)
    depth_image_aligned = np.asanyarray(depth_frame_aligned.get_data())

    depth_colormap_aligned = cv2.applyColorMap(cv2.convertScaleAbs(depth_image_aligned, alpha=0.05), cv2.COLORMAP_JET)
    images_aligned = np.hstack((color_image_aligned, depth_colormap_aligned))
    if show_pic:
        cv2.imshow('aligned_images', images_aligned)
    return color_image_aligned,depth_image_aligned,depth_colormap_aligned

def Unalign_version(frames,show_pic=0):
    # 未对齐版本
    # Wait for a coherent pair of frames: depth and color
    frames = pipeline.wait_for_frames()
    depth_frame = frames .get_depth_frame()
    color_frame = frames .get_color_frame()

    if not USE_ROS_BAG:
        left_frame = frames.get_infrared_frame(1)
        right_frame = frames.get_infrared_frame(2)
        left_image = np.asanyarray(left_frame.get_data())
        right_image = np.asanyarray(right_frame.get_data())
        if show_pic:
            cv2.imshow('left_images', left_image)
            cv2.imshow('right_images', right_image)
    # if not depth_frame or not color_frame:
    #     continue
    color_image = np.asanyarray(color_frame.get_data())
    print("color:",color_image.shape)
    depth_image= np.asanyarray(depth_frame.get_data())
    print("depth:",depth_image.shape)

    #相机API录制的大小rosbag的rgb图像与depth图像不一致,用resize调整到一样大
    if USE_ROS_BAG:
        color_image=cv2.cvtColor(color_image,cv2.COLOR_BGR2RGB)
        if ALIGN_WAY:  #深度图对齐到彩色图像
            depth_image=cv2.resize(depth_image,(color_image.shape[1],color_image.shape[0]))
        else:   #彩色图像对齐到深度图
            color_image=cv2.resize(color_image,(depth_image.shape[1],depth_image.shape[0]))
    # 上色
    depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.05), cv2.COLORMAP_JET)
    # Stack both images horizontally
    images = np.hstack((color_image, depth_colormap))
    if show_pic:
        cv2.imshow('images', images)
    return color_image,depth_image,depth_colormap

if __name__ == "__main__":
    # Configure depth and color streams
    pipeline = rs.pipeline()
    config = rs.config()

    if USE_ROS_BAG:
        config.enable_device_from_file("666.bag")#这是打开相机API录制的视频
    else:
        config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)  #10、15或者30可选,20或者25会报错,其他帧率未尝试
        config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
        #左右双目
        config.enable_stream(rs.stream.infrared, 1, 640, 480, rs.format.y8, 30)  
        config.enable_stream(rs.stream.infrared, 2, 640, 480, rs.format.y8, 30)

    if ALIGN_WAY:
        way=rs.stream.color
    else:
        way=rs.stream.depth
    align = rs.align(way)
    profile =pipeline.start(config)


    depth_sensor = profile.get_device().first_depth_sensor()
    depth_scale = depth_sensor.get_depth_scale()
    print("scale:", depth_scale)
    # 深度比例系数为: 0.0010000000474974513

    try:
        while True:
            frames = pipeline.wait_for_frames()
            color_image_aligned,depth_image_aligned,depth_colormap_aligned=Align_version(frames,align,show_pic=1)
            color_image,depth_image,depth_colormap=Unalign_version(frames,show_pic=1)     
            #print(depth_image_aligned*depth_scale)
            key = cv2.waitKey(1)
            # Press esc or 'q' to close the image window
            if key & 0xFF == ord('q') or key == 27:
                cv2.destroyAllWindows()
                break
    finally:
        # Stop streaming
        pipeline.stop()

插上相机(或者把录好的bag放到同一目录下),修改USE_ROS_BAG和ALIGN_WAY,然后运行这个代码,就可以看到相机拍摄的图像啦。


注意:

1.函数Align_version和Unalign_version分别读取相机或bag的图像,前者还进行深度图与RGB图像的对齐。具体是谁对齐到谁,由变量ALIGN_WAY控制。

2.depth_scale是比例系数,用于在深度图像中直接取值以后,乘以这个系数,得到现实里实际的深度值。(即相机坐标系下的z值。)

这点很多用过深度相机的人也答不上来。即:深度相机采集到的深度,是场景点距离相机坐标系平面的深度,还是距离相机光心的距离?

换句话说,拿深度相机对准一面墙拍摄,现实里这面墙上的每个点距离相机的距离并不同(最近的是相机正前方,最远的是四个墙角)。而根据拍摄得到的深度图,这面墙上各个点进行深度取值,值是否相同?

这里揭晓答案:实验过的人才知道是相同的,相机内部已经进行过换算了。也就是说深度图中记录的深度并不是距离相机的直线距离,而是距离相机平面的垂直深度。

3.直接用相机拍,可以看到左右双目拍摄的结构光点的图像,用bag录好的是不行的。

4.show_pic是用于是否显示图片的变量,两个函数返回的三个变量,分别是彩色图像,深度图像,以及上色以后的深度图像(近处偏冷,远处偏暖)

5.样例图如下:

将深度图对齐到RGB:

上面是没有对齐的版本,可以看出RGB和depth中的手不在同一位置,大小也不同;

下面是对齐后的版本,可以看出RGB和depth中的手的位置已经对齐。

将RGB对齐到深度图:

上面是没有对齐的版本,可以看出RGB和depth中手不在同一位置,大小也不同;

而下面是对齐后的版本,可以看出RGB已经被对齐到了深度图,其中没有深度值的地方也就不再显示RGB值。(从这个里我们可以看出RGB相机和Depth相机的感受视野是不一样的。

5.我们以上图的手的图像为例,发现深度图的手部存在重影。

(其实不是重影,从下面RGB对齐到的地方可以看出,这个地方没有采集到深度。)

为什么会这样?这不是相机坏了或者是代码有问题。这个叫“残影”。

官方的解答是:用立体视觉生成的深度数据将左成像器用作立体匹配的参考,从而在左成像器和右成像器的视场中形成一个非重叠区域,在该区域中,帧的左边缘将没有深度数据。与距离较远的场景相比,较近的场景会导致更宽的无效深度范围。

这点可以参考博客:

Intel Realsense D435 深度图为什么会出现残影?(Invalid Depth Band 无效深度带)(黑洞)

ROS版本

如果你准备用在机器人上,可以使用ros驱动。

以下内容默认你掌握ros的基本使用,否则通过上面的方法尝试去解决。

ros的安装我这里不介绍,自行搜索ros安装教程,以20.04ubuntu系统的noetic为例。

装好ros以后,安装realsense的ros驱动:

sudo apt-get install ros-noetic-realsense2-camera
sudo apt-get install ros-noetic-realsense2-description

装好以后,到/opt/ros/noetic/share/realsense2_camera/launch 这个路径下,可以看看这个相机驱动自带哪些launch文件。

我这里提供一个luanch文件供启动:

<launch>
  <arg name="serial_no"           default=""/>
  <arg name="json_file_path"      default=""/>
  <arg name="camera"              default="camera"/>
  <arg name="tf_prefix"           default="$(arg camera)"/>

  <arg name="fisheye_width"       default="640"/>
  <arg name="fisheye_height"      default="480"/>
  <arg name="enable_fisheye"      default="true"/>

  <arg name="depth_width"         default="640"/>
  <arg name="depth_height"        default="480"/>
  <arg name="enable_depth"        default="true"/>

  <arg name="infra_width"         default="640"/>
  <arg name="infra_height"        default="480"/>
  <arg name="enable_infra1"       default="true"/>
  <arg name="enable_infra2"       default="true"/>

  <arg name="color_width"         default="640"/>
  <arg name="color_height"        default="480"/>
  <arg name="enable_color"        default="true"/>

  <arg name="fisheye_fps"         default="30"/>
  <arg name="depth_fps"           default="30"/>
  <arg name="infra_fps"           default="30"/>
  <arg name="color_fps"           default="30"/>
  <arg name="gyro_fps"            default="400"/>
  <arg name="accel_fps"           default="250"/>
  <arg name="enable_gyro"         default="true"/>
  <arg name="enable_accel"        default="true"/>

  <arg name="enable_pointcloud"   default="true"/>
  <arg name="enable_sync"         default="true"/>
  <arg name="align_depth"         default="true"/>

  <arg name="filters"             default=""/>

  <group ns="$(arg camera)">
    <include file="$(find realsense2_camera)/launch/includes/nodelet.launch.xml">
      <arg name="tf_prefix"                value="$(arg tf_prefix)"/>
      <arg name="serial_no"                value="$(arg serial_no)"/>
      <arg name="json_file_path"           value="$(arg json_file_path)"/>

      <arg name="enable_pointcloud"        value="$(arg enable_pointcloud)"/>
      <arg name="enable_sync"              value="$(arg enable_sync)"/>
      <arg name="align_depth"              value="$(arg align_depth)"/>

      <arg name="fisheye_width"            value="$(arg fisheye_width)"/>
      <arg name="fisheye_height"           value="$(arg fisheye_height)"/>
      <arg name="enable_fisheye"           value="$(arg enable_fisheye)"/>

      <arg name="depth_width"              value="$(arg depth_width)"/>
      <arg name="depth_height"             value="$(arg depth_height)"/>
      <arg name="enable_depth"             value="$(arg enable_depth)"/>

      <arg name="color_width"              value="$(arg color_width)"/>
      <arg name="color_height"             value="$(arg color_height)"/>
      <arg name="enable_color"             value="$(arg enable_color)"/>

      <arg name="infra_width"              value="$(arg infra_width)"/>
      <arg name="infra_height"             value="$(arg infra_height)"/>
      <arg name="enable_infra1"            value="$(arg enable_infra1)"/>
      <arg name="enable_infra2"            value="$(arg enable_infra2)"/>

      <arg name="fisheye_fps"              value="$(arg fisheye_fps)"/>
      <arg name="depth_fps"                value="$(arg depth_fps)"/>
      <arg name="infra_fps"                value="$(arg infra_fps)"/>
      <arg name="color_fps"                value="$(arg color_fps)"/>
      <arg name="gyro_fps"                 value="$(arg gyro_fps)"/>
      <arg name="accel_fps"                value="$(arg accel_fps)"/>
      <arg name="enable_gyro"              value="$(arg enable_gyro)"/>
      <arg name="enable_accel"             value="$(arg enable_accel)"/>

      <arg name="filters"                  value="$(arg filters)"/>
    </include>
  </group>
</launch>

可以看到其中

  <arg name="enable_pointcloud"   default="true"/>
  <arg name="enable_sync"         default="true"/>
  <arg name="align_depth"         default="true"/>

这三句比较重要,enable_pointcloud 表示 会发布一个"camera_color_optical_frame"坐标系下的点云, align_depth 会对齐深度图和rgb图像。

其中,/camera/color/image_raw 话题是 RGB图像,/camera/aligned_depth_to_color/image_raw是对齐到RGB图像的depth图像。使用时只要监听这两个图像的话题即可,并且深度部分的单位是毫米。

<think>好的,我现在需要帮助用户解决在Ubuntu上运行patch-realsense-ubuntu-lts-hwe.sh脚本时遇到的linux-headers-5.10.104-tegra包缺失的问题。首先,我要先理解用户的问题。用户提到在打补丁时遇到报错,具体是找不到这个特定的头文件包,导致无法继续。用户希望安装或配置这个缺失的包,以便成功执行补丁脚本。 首先,我需要了解这个linux-headers包的作用。通常,当需要编译内核模块或进行系统级修改时,需要对应的内核头文件。这些头文件包含了内核的函数和数据结构定义,是编译过程中必需的。如果缺少对应的头文件,补丁脚本可能无法继续,因为它需要这些文件来构建内核模块。 接下来,用户的环境是Ubuntu,但包名中有“tegra”,这可能意味着用户使用的是NVIDIA Jetson平台,因为Tegra是NVIDIA的处理器系列,常用于嵌入式设备如Jetson系列。Jetson设备通常运行基于Ubuntu的定制版本,比如L4T(Linux for Tegra)。因此,用户可能是在Jetson设备上运行Ubuntu,并且尝试安装Intel RealSense相机的驱动或SDK,这需要打内核补丁。 根据用户提供的引用信息,补丁脚本不支持当前的内核版本,建议使用RSUSB Backend方式编译SDK。这说明官方可能没有为这个特定的内核版本提供支持,所以直接安装头文件可能不可行。但用户还是想尝试安装正确的头文件,或者寻找替代方法。 接下来,我需要考虑可能的解决方案。首先,用户需要确认他们的内核版本是否确实需要这个特定的头文件包。可以检查当前的内核版本,使用uname -r命令。假设用户的内核版本是5.10.104-tegra,那么需要找到对应的linux-headers包。 在Ubuntu系统中,通常可以使用apt来安装头文件包,比如sudo apt install linux-headers-$(uname -r)。但如果是定制内核,比如由NVIDIA提供的L4T内核,标准的Ubuntu仓库可能不包含这些头文件。这时候可能需要从NVIDIA的官方源或者L4T的SDK Manager中获取。 如果NVIDIA提供了这些头文件包,用户需要添加正确的仓库源,然后进行安装。如果没有,可能需要手动下载或编译头文件,但这比较复杂,且容易出错。此外,补丁脚本可能要求特定版本的头文件,如果版本不匹配,安装其他版本可能也不起作用。 另一个可能性是,用户的内核版本太新或太旧,官方尚未支持,因此补丁脚本无法应用。这时候,按照引用中的建议,改用RSUSB Backend方式可能更可行。这种方法不需要内核补丁,而是通过用户空间的USB通信,牺牲部分性能来避免内核模块的编译。这可能是官方推荐的替代方案,尤其当遇到内核兼容性问题时。 总结可能的解决步骤: 1. 确认内核版本和头文件包名称是否正确。 2. 检查是否有可用的官方源提供该头文件包。 3. 尝试使用apt安装,或者从NVIDIA官网下载对应的头文件。 4. 如果无法安装,考虑使用RSUSB Backend方式绕过内核补丁的需求。 5. 如果必须打补丁,可能需要手动修改补丁脚本或寻找其他补丁方法。 现在,我需要将这些步骤详细地解释给用户,并提供具体的命令和参考。同时,要指出可能遇到的障碍,比如找不到包时的替代方案,或者如何配置RSUSB Backend。 需要注意用户可能对Linux系统和包管理不太熟悉,所以需要给出明确的命令和步骤。同时,提醒用户注意不同环境下的差异,比如Jetson设备的特殊性。 最后,根据用户提供的引用[^1],需要强调如果确实无法安装头文件,RSUSB Backend是官方推荐的解决方案,确保用户理解这一点,避免他们在无法解决问题时继续浪费时间。</think>### 解决方案 #### 1. 验证内核版本和头文件包名称 首先确认当前系统的内核版本是否缺失的包名一致: ```bash uname -r ``` 如果输出为`5.10.104-tegra`,则需要安装对应的头文件包。若不一致,需根据实际内核版本调整后续操作。 #### 2. 尝试通过官方仓库安装 对于NVIDIA Jetson设备(L4T系统),头文件包通常包含在`linux-headers-$(uname -r)`中。执行以下命令尝试安装: ```bash sudo apt update sudo apt install linux-headers-5.10.104-tegra ``` **可能结果**: - **成功**:直接完成补丁脚本执行。 - **失败(找不到包)**:需手动下载或启用NVIDIA官方源(见下一步)。 #### 3. 从NVIDIA官方源获取头文件包 Jetson设备的头文件包通常通过NVIDIA开发者网站或SDK Manager提供: 1. 访问[NVIDIA L4T下载页面](https://developer.nvidia.com/embedded/linux-tegra)查找对应L4T版本。 2. 下载包含头文件的`kernel_src.tbz2`或`headers`包。 3. 解压并手动复制到`/usr/src/linux-headers-5.10.104-tegra`目录。 #### 4. RSUSB Backend替代方案(推荐) 若无法安装头文件包,遵循官方建议使用**RSUSB Backend**模式编译RealSense SDK,绕过内核补丁需求: ```bash mkdir build && cd build cmake .. -DFORCE_RSUSB_BACKEND=ON -DBUILD_EXAMPLES=true make -j4 sudo make install ``` 此模式通过用户空间USB协议实现功能,无需内核补丁[^1]。 #### 5. 手动编译内核头文件(高级) 若必须使用内核补丁,可尝试从L4T源码编译头文件: ```bash sudo apt install build-essential bc wget https://developer.nvidia.com/embedded/l4t/r32_release_v7.2/sources/t186/public_sources.tbz2 tar -xvf public_sources.tbz2 cd Linux_for_Tegra/source/public/kernel_src.tbz2 tar -xvf kernel_src.tbz2 cd kernel/kernel-4.9 make headers_install ``` --- ### 关键问题分析 - **Tegra头文件特殊性**:NVIDIA Jetson设备的头文件包通常不包含在标准Ubuntu仓库中,需通过官方渠道获取。 - **内核版本匹配**:补丁脚本依赖严格的内核版本匹配,手动修改补丁可能导致系统不稳定。 - **RSUSB Backend的妥协**:牺牲部分性能(如帧率同步功能)换取兼容性,适合非严格依赖内核优化的场景。 ---
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值