• RealSense D435 的开发日记(API 汇总)


    🌞欢迎来到机器学习的世界 
    🌈博客主页:卿云阁

    💌欢迎关注🎉点赞👍收藏⭐️留言📝

    🌟本文由卿云阁原创!

    🌠本阶段属于练气阶段,希望各位仙友顺利完成突破

    📆首发时间:🌹2021年6月23日🌹

    ✉️希望可以和大家一起完成进阶之路!

    🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!


    目录

    🍈 获得相机不同传感器之间的外参转换矩阵以及内参矩阵

    🍉获取设备的传感器信息

    🍊获得深度图单位和米之间的映射

    🍋深度图与RGB图配准

    🍌获取深度图中像素点的深度值

    🍍使用API进行拍照

             🥭Realsense获取像素点在相机坐标系下的三维坐标

    🍎其它相关内容的介绍

    🍆校准​编辑

     

    🍈 获得相机不同传感器之间的外参转换矩阵以及内参矩阵

    1. import pyrealsense2 as rs
    2. pipeline = rs.pipeline()
    3. config = rs.config()
    4. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
    5. config.enable_stream(rs.stream.color, 1280, 720, rs.format.rgb8, 30)
    6. cfg = pipeline.start(config)
    7. device = cfg.get_device()
    8. name = device.get_info(rs.camera_info.name)
    9. print(name)
    10. profile = cfg.get_stream(rs.stream.depth)
    11. profile1 = cfg.get_stream(rs.stream.color)
    12. intr = profile.as_video_stream_profile().get_intrinsics()
    13. intr1 = profile1.as_video_stream_profile().get_intrinsics()
    14. extrinsics = profile1.get_extrinsics_to(profile)
    15. print(extrinsics)
    16. print("深度传感器内参:", intr)
    17. print("RGB相机内参:", intr1)
    1. Intel RealSense D435
    2. rotation: [0.999641, -0.0260036, 0.00641907, 0.0260053, 0.999662, -0.000173101, -0.0064124, 0.000339969, 0.999979]
    3. translation: [-0.0147544, -0.000367906, -0.000408054]
    4. 深度传感器内参: [ 640x480 p[322.424 239.496] f[386.034 386.034] Brown Conrady [0 0 0 0 0] ]
    5. RGB相机内参: [ 1280x720 p[643.807 366.839] f[930.979 930.957] Inverse Brown Conrady [0 0 0 0 0] ]

    注意
       不同分辨率的深度相机和RGB相机对应不同的内参参数,但是外参矩阵是一样的(上述代码的外参指的是RGB相机转换到深度相机的转换矩阵),可以观察到RGB相机有畸变参数,深度相机无畸变参数。

    1. import pyrealsense2 as rs
    2. pipeline = rs.pipeline()
    3. config = rs.config()
    4. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
    5. config.enable_stream(rs.stream.color, 960, 540, rs.format.bgr8, 30)
    6. profile = pipeline.start(config)
    7. frames = pipeline.wait_for_frames()
    8. depth = frames.get_depth_frame()
    9. color = frames.get_color_frame()
    10. # 获取内参
    11. depth_profile = depth.get_profile()
    12. print(depth_profile)
    13. # <pyrealsense2.video_stream_profile: Depth(0) 640x480 @ 30fps Z16>
    14. print(type(depth_profile))
    15. # <class 'pyrealsense2.pyrealsense2.stream_profile'>
    16. print(depth_profile.fps())
    17. # 30
    18. print(depth_profile.stream_index())
    19. # 0
    20. print(depth_profile.stream_name())
    21. # Depth
    22. print(depth_profile.stream_type())
    23. # stream.depth
    24. print('', depth_profile.unique_id)
    25. # <bound method PyCapsule.unique_id of <pyrealsense2.video_stream_profile: Depth(0) 640x480 @ 30fps Z16>>
    26. color_profile = color.get_profile()
    27. print(color_profile)
    28. # <pyrealsense2.video_stream_profile: Color(0) 960x540 @ 30fps BGR8>
    29. print(type(color_profile))
    30. # <class 'pyrealsense2.pyrealsense2.stream_profile'>
    31. print(depth_profile.fps())
    32. # 30
    33. print(depth_profile.stream_index())
    34. # 0
    35. cvsprofile = rs.video_stream_profile(color_profile)
    36. dvsprofile = rs.video_stream_profile(depth_profile)
    37. color_intrin = cvsprofile.get_intrinsics()
    38. print(color_intrin)
    39. # 960x540 p[493.975 265.065] f[673.775 673.824] Brown Conrady [0.151657 -0.50863 -0.000700379 -0.000860805 0.471284]
    40. depth_intrin = dvsprofile.get_intrinsics()
    41. print(depth_intrin)
    42. # [ 640x480 p[306.57 254.527] f[461.453 461.469] None [0 0 0 0 0] ]
    43. extrin = depth_profile.get_extrinsics_to(color_profile)
    44. print(extrin)
    45. # rotation: [0.999965, 0.00762357, 0.00331248, -0.00754261, 0.999688, -0.0238027, -0.0034929, 0.0237769, 0.999711]
    46. # translation: [0.000304107, 0.0142351, -0.00695471]

     🍉获取设备的传感器信息

    1. import pyrealsense2 as rs
    2. import pyrealsense2 as rs
    3. pipeline = rs.pipeline()
    4. config = rs.config()
    5. pipeline_wrapper = rs.pipeline_wrapper(pipeline)
    6. pipeline_profile = config.resolve(pipeline_wrapper)
    7. device = pipeline_profile.get_device()
    8. for s in device.sensors:
    9. print(s.get_info(rs.camera_info.name))
    10. cfg = pipeline.start(config)
    11. device1 = cfg.get_device()
    12. for s in device1.sensors:
    13. print(s.get_info(rs.camera_info.name))

    aaaa

    1. Stereo Module
    2. RGB Camera
    3. Stereo Module
    4. RGB Camera

    两个语句得到的都是pipeline_profile的类,有get_device的方法

    pipeline.start(config)
    
    config.resolve(pipeline_wrapper)
    

    🍊获得深度图单位和米之间的映射

    1. import pyrealsense2 as rs
    2. import pyrealsense2 as rs
    3. # Create a pipeline
    4. pipeline = rs.pipeline()
    5. # Start streaming
    6. profile = pipeline.start()
    7. # Getting the depth sensor's depth scale (see rs-align example for explanation)
    8. depth_sensor = profile.get_device().first_depth_sensor()
    9. depth_scale = depth_sensor.get_depth_scale()
    10. print("Depth Scale is: ", depth_scale)
    Depth Scale is:  0.0010000000474974513

          get_depth_scale的目标是获得深度图单位与米单位之间的映射关系,所以上述表示一个深度图单位等于0.00025米。第二个例子通过get_data方法获得的数值与米单位之间需要乘以一个比例系数。

    🍋深度图与RGB图配准

    1. # First import the library
    2. import pyrealsense2 as rs
    3. # Import Numpy for easy array manipulation
    4. import numpy as np
    5. # Import OpenCV for easy image rendering
    6. import cv2
    7. # Create a pipeline
    8. pipeline = rs.pipeline()
    9. # Create a config and configure the pipeline to stream
    10. # different resolutions of color and depth streams
    11. config = rs.config()
    12. # Get device product line for setting a supporting resolution
    13. pipeline_wrapper = rs.pipeline_wrapper(pipeline)
    14. pipeline_profile = config.resolve(pipeline_wrapper)
    15. device = pipeline_profile.get_device()
    16. device_product_line = str(device.get_info(rs.camera_info.product_line))
    17. found_rgb = False
    18. for s in device.sensors:
    19. if s.get_info(rs.camera_info.name) == 'RGB Camera':
    20. found_rgb = True
    21. break
    22. if not found_rgb:
    23. print("The demo requires Depth camera with Color sensor")
    24. exit(0)
    25. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
    26. if device_product_line == 'L500':
    27. config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
    28. else:
    29. config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
    30. # Start streaming
    31. profile = pipeline.start(config)
    32. # Getting the depth sensor's depth scale (see rs-align example for explanation)
    33. depth_sensor = profile.get_device().first_depth_sensor()
    34. depth_scale = depth_sensor.get_depth_scale()
    35. print("Depth Scale is: ", depth_scale)
    36. # We will be removing the background of objects more than
    37. # clipping_distance_in_meters meters away
    38. clipping_distance_in_meters = 1 # 1 meter
    39. clipping_distance = clipping_distance_in_meters / depth_scale
    40. # Create an align object
    41. # rs.align allows us to perform alignment of depth frames to others frames
    42. # The "align_to" is the stream type to which we plan to align depth frames.
    43. align_to = rs.stream.color
    44. align = rs.align(align_to)
    45. # Streaming loop
    46. try:
    47. while True:
    48. # Get frameset of color and depth
    49. frames = pipeline.wait_for_frames()
    50. # frames.get_depth_frame() is a 640x360 depth image
    51. # Align the depth frame to color frame
    52. aligned_frames = align.process(frames)
    53. # Get aligned frames
    54. aligned_depth_frame = aligned_frames.get_depth_frame() # aligned_depth_frame is a 640x480 depth image
    55. color_frame = aligned_frames.get_color_frame()
    56. # Validate that both frames are valid
    57. if not aligned_depth_frame or not color_frame:
    58. continue
    59. depth_image = np.asanyarray(aligned_depth_frame.get_data())
    60. color_image = np.asanyarray(color_frame.get_data())
    61. # the size of color_frame is (720,1280,3)
    62. # Remove background - Set pixels further than clipping_distance to grey
    63. grey_color = 153
    64. depth_image_3d = np.dstack((depth_image, depth_image, depth_image))
    65. # depth image is 1 channel, color is 3 channels
    66. # depth_image_3d shape is (720,1280,3)
    67. bg_removed = np.where((depth_image_3d > clipping_distance) | (depth_image_3d <= 0), grey_color, color_image)
    68. # the size of bg_removed is (720,1280,3)
    69. # Render images:
    70. # depth align to color on left
    71. # depth on right
    72. depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
    73. images = np.hstack((bg_removed, depth_colormap))
    74. cv2.namedWindow('Align Example', cv2.WINDOW_NORMAL)
    75. cv2.imshow('Align Example', images)
    76. key = cv2.waitKey(1)
    77. # Press esc or 'q' to close the image window
    78. if key & 0xFF == ord('q') or key == 27:
    79. cv2.destroyAllWindows()
    80. break
    81. finally:
    82. pipeline.stop()

     无论初始对于彩色流或是深度流是如何设置分辨率的,经过align.process之后的彩色流和深度流都是(720,1280)大小的(这个大小根据彩色流的设置而定),虽然深度流需要重构为三维来让彩色流和深度流拼接。虽然深度流的大小转换为和彩色流一样的大小,但是分辨率还是根据深度流的设置参数而定的,与大小无关

    🍌获取深度图中像素点的深度值

    get_distance()方法得到的数据是以米为单位的

    1. import cv2
    2. import numpy as np
    3. import pyrealsense2 as rs
    4. pipeline = rs.pipeline()
    5. config = rs.config()
    6. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
    7. # Start streaming
    8. profile = pipeline.start(config)
    9. while True:
    10. frames = pipeline.wait_for_frames()
    11. depth_frames = frames.get_depth_frame()
    12. depth_image = np.asarray(depth_frames.get_data())
    13. depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
    14. distance = depth_frames.get_distance(100, 200)
    15. print(distance)
    16. cv2.imshow("depth image:", depth_colormap)
    17. key = cv2.waitKey(1)
    18. if key == 27:
    19. break
    20. pipeline.stop()
    1. 3.8570001125335693
    2. 3.8570001125335693
    3. 3.8570001125335693
    4. 4.11400032043457
    5. 3.809000253677368
    6. 3.8330001831054688
    7. 3.763000249862671
    8. 4.25600004196167
    9. 5.27400016784668

     🍍使用API进行拍照

    1. import cv2
    2. import numpy as np
    3. import pyrealsense2 as rs
    4. import os
    5. # 配置
    6. pipe = rs.pipeline()
    7. cfg = rs.config()
    8. cfg.enable_stream(rs.stream.color, 1280, 720, rs.format.rgb8, 30)
    9. i = 0
    10. profile = pipe.start(cfg)
    11. while True:
    12. # 获取图片帧
    13. frameset = pipe.wait_for_frames()
    14. color_frame = frameset.get_color_frame()
    15. color_img = np.asanyarray(color_frame.get_data())
    16. # 更改通道的顺序为RGB
    17. cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
    18. cv2.imshow('RealSense', color_img)
    19. k = cv2.waitKey(1)
    20. # Esc退出,
    21. if k == 27:
    22. cv2.destroyAllWindows()
    23. break
    24. # 输入空格保存图片
    25. elif k == ord(' '):
    26. i = i + 1
    27. cv2.imwrite(os.path.join("D:\\Realsense\\pic_capture", str(i) + '.jpg'), color_img)
    28. print("Frames{} Captured".format(i))
    29. pipe.stop()

     只要将数据转换为numpy数组的方式,就可以通过opencv库进行图片的保存

    🥭Realsense获取像素点在相机坐标系下的三维坐标

    1. import pyrealsense2 as rs
    2. import numpy as np
    3. import cv2
    4. import json
    5. def get_aligned_images():
    6. frames = pipeline.wait_for_frames() # 等待获取图像帧
    7. aligned_frames = align.process(frames) # 获取对齐帧
    8. aligned_depth_frame = aligned_frames.get_depth_frame() # 获取对齐帧中的depth帧
    9. color_frame = aligned_frames.get_color_frame() # 获取对齐帧中的color帧
    10. ############### 相机参数的获取 #######################
    11. intr = color_frame.profile.as_video_stream_profile().intrinsics # 获取相机内参
    12. depth_intrin = aligned_depth_frame.profile.as_video_stream_profile().intrinsics # 获取深度参数(像素坐标系转相机坐标系会用到)
    13. camera_parameters = {'fx': intr.fx, 'fy': intr.fy,
    14. 'ppx': intr.ppx, 'ppy': intr.ppy,
    15. 'height': intr.height, 'width': intr.width,
    16. 'depth_scale': profile.get_device().first_depth_sensor().get_depth_scale()
    17. }
    18. # 保存内参到本地
    19. with open('D:\\Realsense\\intrinsics.json', 'w') as fp:
    20. json.dump(camera_parameters, fp)
    21. #######################################################
    22. depth_image = np.asanyarray(aligned_depth_frame.get_data()) # 深度图(默认16位)
    23. depth_image_8bit = cv2.convertScaleAbs(depth_image, alpha=0.03) # 深度图(8位)
    24. depth_image_3d = np.dstack((depth_image_8bit, depth_image_8bit, depth_image_8bit)) # 3通道深度图
    25. color_image = np.asanyarray(color_frame.get_data()) # RGB图
    26. # 返回相机内参、深度参数、彩色图、深度图、齐帧中的depth帧
    27. return intr, depth_intrin, color_image, depth_image_3d, aligned_depth_frame
    28. pipeline = rs.pipeline() # 定义流程pipeline
    29. config = rs.config() # 定义配置config
    30. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) # 配置depth流
    31. config.enable_stream(rs.stream.color, 960, 540, rs.format.bgr8, 30) # 配置color流
    32. profile = pipeline.start(config) # 流程开始
    33. align_to = rs.stream.color # 与color流对齐
    34. align = rs.align(align_to)
    35. while True:
    36. intr, depth_intrin, rgb, depth, aligned_depth_frame = get_aligned_images() # 获取对齐的图像与相机内参
    37. # 定义需要得到真实三维信息的像素点(x, y),本例程以中心点为例
    38. x = 320
    39. y = 240
    40. dis = aligned_depth_frame.get_distance(x, y) # (x, y)点的真实深度值
    41. print("distance:",dis)
    42. camera_coordinate = rs.rs2_deproject_pixel_to_point(intr, [x, y], dis)
    43. # (x, y)点在相机坐标系下的真实值,为一个三维向量。
    44. # 其中camera_coordinate[2]仍为dis,camera_coordinate[0]和camera_coordinate[1]为相机坐标系下的xy真实距离。
    45. print(camera_coordinate)
    46. cv2.imshow('RGB image', rgb) # 显示彩色图像
    47. key = cv2.waitKey(1)
    48. # Press esc or 'q' to close the image window
    49. if key & 0xFF == ord('q') or key == 27:
    50. pipeline.stop()
    51. break
    52. cv2.destroyAllWindows()

     

     

        获得像素点在相机坐标系下的三维坐标之后,通过手眼标定就可以转化为在机械臂基底坐标系下的坐标,进而执行下一步操作。所得到的三维坐标应该是以米为单位的。

    🍎其它相关内容的介绍

    像素坐标:
          通过SDK提供的图像流都关联一个独立的2D以像素为单位的坐标系。[0,0]点位于左上角,[w-1,h-1]点位于右下角。w和h分别代表列和行,从相机的角度来看,x轴指向右边,y轴指向下边。这个坐标系就是所谓的像素坐标系,用来索引特定的像素点。

    点坐标:
           通过SDK提供的图像流都关联一个独立的3D以米为单位的坐标系。这个坐标系的原点[0,0,0]指的是物理成像仪的中心。在这个空间中,x轴正向指向右,y轴正向指向下,z轴正向指向前。该空间中的坐标称为“点”,用于描述三维空间中可能在特定图像中可见的位置。

    相机内参
    流的2D和3D坐标系的转换关系是通过相机内参来描述的,包含在rs2_intrinsics结构体中。不同的RealSense设备的内参是不同的,rs2_intrinsics结构体必须要能够描述由这些设备产生的图像。

    相机外参
    每种图像流的三维坐标系是不同的,比如说,通常来说深度图像是通过一个或多个红外成像仪生成的,而彩色流是通过一个独立的彩色成像仪形成的。这些不同的流所对应的三维坐标系之间的关系是通过外参进行描述的,包含在rs2_extrinsics的结构体中。

    🍆校准

     

    这张图片也就是说,在 Viewer 上进行校准,当误差小于一定值时,可以忽略。

    如果校准过程中报错:可能是没有足够的有效深度像素,通常可以通过确保投影仪处于打开状态来补救。

     

  • 相关阅读:
    【附源码】Python计算机毕业设计石家庄学院跳蚤市场
    三十四、Java Iterator(迭代器)
    用Python绘制分子结构
    归并排序的复杂度
    易基因|DNA甲基化揭示应激反应影响婴儿免疫相关基因的表观遗传调控机制 | 表观发育
    Go语句与表达式深度解析:全案例手册
    JavaSE的思维导图
    pdd.order.list.get拼多多店铺订单列表查询接口(店铺订单详情接口,订单明文接口,订单解密接口,订单插旗接口,订单备注接口)代码对接教程
    【linux驱动开发】-gpiolib概念与实践
    【深度学习环境配置】windows出现出现‘git‘ 不是内部或外部命令,也不是可运行的程序
  • 原文地址:https://blog.csdn.net/zzqingyun/article/details/125421849