当前位置: 首页 > news >正文

open3d:使用彩色图和深度图生成点云

一.相关函数介绍

1.create_from_color_and_depth

class RGBDImage(Geometry2D):""" RGBDImage is for a pair of registered color and depth images, viewed from the same view, of the same resolution. If you have other format, convert it first. """def create_from_color_and_depth(self, color, depth, depth_scale=1000.0, depth_trunc=3.0, convert_rgb_to_intensity=True): # real signature unknown; restored from __doc__"""create_from_color_and_depth(color, depth, depth_scale=1000.0, depth_trunc=3.0, convert_rgb_to_intensity=True)Function to make RGBDImage from color and depth imageArgs:color (open3d.geometry.Image): The color image.depth (open3d.geometry.Image): The depth image.depth_scale (float, optional, default=1000.0): The ratio to scale depth values. The depth values will first be scaled and then truncated.depth_trunc (float, optional, default=3.0): Depth values larger than ``depth_trunc`` gets truncated to 0. The depth values will first be scaled and then truncated.convert_rgb_to_intensity (bool, optional, default=True): Whether to convert RGB image to intensity image.Returns:open3d.geometry.RGBDImage"""pass

 解释

这段代码注释定义了一个名为 RGBDImage 的类及其方法 create_from_color_and_depth,这个类和方法属于 Open3D 几何库中的 Geometry2D 类。RGBDImage 类用于处理和存储一对已经配准的彩色图像和深度图像,这些图像是从同一个视角捕获且具有相同的分辨率。

类描述

  • RGBDImage:这个类的注释说明了它用于处理经过配准的彩色图像和深度图像。如果用户的图像数据格式不符合要求,需要先进行转换。

方法:create_from_color_and_depth

这个方法用于从彩色图像和深度图像创建一个 RGBDImage 对象。

参数

  • color (open3d.geometry.Image): 彩色图像。

  • depth (open3d.geometry.Image): 深度图像。

  • depth_scale (float, optional, default=1000.0): 深度值的比例因子。深度值首先会被该比例因子缩放,然后再进行截断。注意:比例因子为1000,说明深度图的坐标值单位默认为mm,单位转换为m。

  • depth_trunc (float, optional, default=3.0): 深度截断值。大于这个值的深度数据会被截断为0。深度值先缩放再截断。 注意:这里意思是将只保留距离相机3m以内的点云。

  • convert_rgb_to_intensity (bool, optional, default=True): 是否将彩色图像转换为强度图像。注意:强度图 即是  灰度图。

返回值

  • open3d.geometry.RGBDImage: 返回一个由彩色和深度图像组合而成的 RGBDImage 对象。

功能说明

该方法的主要目的是将彩色图像和深度图像组合成一个 RGBDImage 对象,这样可以在后续的处理中同时使用颜色信息和深度信息,例如进行点云生成或三维重建等。通过调整 depth_scaledepth_trunc 参数,可以对深度数据进行预处理,以适应不同的应用场景。

 2.create_from_rgbd_image

def create_from_rgbd_image(self, image, intrinsic, extrinsic, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__ """create_from_rgbd_image(image, intrinsic, extrinsic=(with default value), project_valid_depth_only=True)Factory function to create a pointcloud from an RGB-D image and a camera. Given depth value d at (u, v) image coordinate, the corresponding 3d point is:- z = d / depth_scale- x = (u - cx) * z / fx- y = (v - cy) * z / fyArgs:image (open3d.geometry.RGBDImage): The input image.intrinsic (open3d.camera.PinholeCameraIntrinsic): Intrinsic parameters of the camera.extrinsic (numpy.ndarray[numpy.float64[4, 4]], optional) Default value:array([[1., 0., 0., 0.],[0., 1., 0., 0.],[0., 0., 1., 0.],[0., 0., 0., 1.]])project_valid_depth_only (bool, optional, default=True)Returns:open3d.geometry.PointCloud"""pass

 

解释 

一个用于从深度图像创建三维点云的函数。

  • self:指的是类的实例(在Python中,所有类的方法都需要将实例本身作为第一个参数)。

  • depth: 输入的深度图像,可以是浮点数类型或16位无符号整数类型的图像。

  • intrinsic: 相机的内参矩阵,用于将图像坐标转换为三维坐标。

  • extrinsic: 相机的外参矩阵,默认值是单位矩阵,表示没有旋转或平移的变换。

  • *args, **kwargs: 表示除了上述参数外,可以传递任意数量的额外参数(在实际调用时可能不会用到)。

文档说明

  • 返回值: 返回一个 open3d.geometry.PointCloud 对象,代表从深度图像生成的点云。

  • stride: 步长参数,设置为大于1的值可以降低点云的分辨率。默认为1,表示使用图像中的所有像素。   #注意:一般设置为1

  • project_valid_depth_only: 一个布尔值,默认为True,表示只将有效的深度值投影到三维空间中。   注意:有的时候需要设置为False,这是点云文件中无效值将保存为Nan

坐标转换公式

给定深度值 d(u, v) 图像坐标处,对应的三维点计算公式如下:

  • z = d / depth_scale:深度值转换为实际距离。  注意:depth_scale比例因子在函数1,深度图的单位为mm,  转换成m, 因此depth_scale=1000, 若需要修改,在函数1处进行修改

  • x = (u - cx) * z / fx:计算x坐标,考虑了相机的光学中心和焦距。

  • y = (v - cy) * z / fy:计算y坐标,原理同上。

其中,cxcy 是相机的光学中心坐标,fxfy 是相机的焦距(这些参数通常包含在 intrinsic 参数中)。

程序编写

1.d435i深度相机参数读取程序

参考1:Python读取Realsense D435深度相机内参_pyrealsense2获取深度相机的内参-CSDN博客


#2025.6.5
#参考 https://blog.csdn.net/ZNC1998/article/details/139124353?spm=1001.2014.3001.5506# 获取深度相机的内参import pyrealsense2 as rsdef get_intrinsics():# Create a context object. This object owns the handles to all connected realsense devicespipeline = rs.pipeline()config = rs.config()# Configure the pipeline to stream the depth streamconfig.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)# Start streamingpipeline.start(config)# Get frames from the camera to get the intrinsic parametersprofile = pipeline.get_active_profile()depth_stream = profile.get_stream(rs.stream.depth)intr = depth_stream.as_video_stream_profile().get_intrinsics()# Stop the pipelinepipeline.stop()# Intrinsicsintrinsics_matrix = [[intr.fx, 0, intr.ppx],[0, intr.fy, intr.ppy],[0, 0, 1]]return intrinsics_matrixif __name__ == "__main__":intrinsics_matrix = get_intrinsics()print("Intrinsic matrix for RealSense D435 depth camera:")for row in intrinsics_matrix:print(row)  #按矩阵的行输出"""[646.5264282226562, 0, 640.8402099609375][0, 646.5264282226562, 356.4901123046875][0, 0, 1]"""

参考2:获取D405相机的内参的方法-CSDN博客

该代码需要获取相机本身的SN编号,

方法1:在购买相机时查看包装盒

方法2:使用程序读取

import pyrealsense2 as rs
import numpy as np
import cv2# Configure depth and color streams
#配置深度和视频流
#创建一个pipeline对象,用于管理数据流,以及一个config对象,用于配置相机流。
pipeline = rs.pipeline()
config = rs.config()# Get device product line for setting a supporting resolution
#获取设备产品线以设置支持的分辨率
pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)
device = pipeline_profile.get_device()
print(device) #<pyrealsense2.device: D435I (S/N: 2025651926  FW: 5.16.0.1  on USB3.2)>#注意每个人相机SN编号不一样,根据自已相机读取
import pyrealsense2 as rs# Create a pipeline
pipeline = rs.pipeline()# Create a config and configure the pipeline to stream
config = rs.config()#####
# config.enable_device('your_device_serial_number')  # Optional: specify the serial number of your D405 camera
# 20256519299
config.enable_device('20256519299')   #相机的sn 号,前12位
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)# Start the pipeline
pipeline.start(config)# Get device product line for setting a supporting resolution
profile = pipeline.get_active_profile()
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale()print(f"depth_scale={depth_scale}")# Get the depth sensor's depth stream profile and extract intrinsic parameters
depth_stream = profile.get_stream(rs.stream.depth)
intrinsics = depth_stream.as_video_stream_profile().get_intrinsics()# Print intrinsics
print("Width:", intrinsics.width)
print("Height:", intrinsics.height)
print("PPX:", intrinsics.ppx)
print("PPY:", intrinsics.ppy)
print("FX:", intrinsics.fx)
print("FY:", intrinsics.fy)
print("Distortion Model:", intrinsics.model)
print("Coefficients:", intrinsics.coeffs)# Stop the pipeline
pipeline.stop()"""depth_scale=0.0010000000474974513
Width: 1280
Height: 720
PPX: 640.8402099609375
PPY: 356.4901123046875
FX: 646.5264282226562
FY: 646.5264282226562
Distortion Model: distortion.brown_conrady
Coefficients: [0.0, 0.0, 0.0, 0.0, 0.0]
"""

 

 2.使用深度相机d435i拍摄深度图和彩色图

注意:深度图拍摄一定是png格式(16位,可以保存深度信息 2^16=65536mm,即 65m;  如果是jpg,  2^8=256mm, 深度信息几乎丢失)


#2025.6.3
"""
参考深度优化后的   深度图, 并保存为png,使用open3d查看  深度图优化后,形成的点云   
""""""
参考: E:\pycharm\pyProject_d435i\my_demo\demo_photo\color_depth_infrared_demo03.py   进行修改
""""""
注意:
1. 深度图 对齐于  彩色图
"""import pyrealsense2 as rs
import numpy as np
import cv2# Configure depth and color streams
#配置深度和视频流
#创建一个pipeline对象,用于管理数据流,以及一个config对象,用于配置相机流。
pipeline = rs.pipeline()
config = rs.config()# Get device product line for setting a supporting resolution
#获取设备产品线以设置支持的分辨率
pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)
device = pipeline_profile.get_device()
# print(device) 
device_product_line = str(device.get_info(rs.camera_info.product_line))
# print(device_product_line) #D400
# #
# pipeline_wrapper是pipeline对象的一个包装器,它提供了对pipeline的额外控制。
# config.resolve(pipeline_wrapper)用于根据配置文件解析pipeline_wrapper,创建一个pipeline_profile对象,该对象包含了流配置的详细信息。
# device是从pipeline_profile中获取的RealSense设备对象。
# device_product_line获取设备的产品线信息,并将其转换为字符串。产品线信息可以是“L500”或“D400”等,这有助于确定设备的型号和功能。
# ##查设备是否包含RGB相机。如果不含,则打印消息并退出程序。
found_rgb = False
for s in device.sensors:if s.get_info(rs.camera_info.name) == 'RGB Camera':found_rgb = Truebreak
if not found_rgb:print("The demo requires Depth camera with Color sensor")exit(0)
# #
# 如果found_rgb仍然是False,这意味着没有找到RGB相机。
# 打印一条消息,说明演示需要带有颜色传感器的深度相机。
# 调用exit(0)以终止程序。exit(0)表示程序正常退出,其中0是退出状态码,通常表示成功。
# ##配置深度和颜色流的参数,包括分辨率、格式和帧率。
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)# config.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)  #蓝色变红色,  黄色变蓝色
config.enable_stream(rs.stream.color, 1280, 720,  rs.format.bgr8, 30)  #正常肉眼颜色config.enable_stream(rs.stream.infrared, 1, 1280, 720,  rs.format.y8, 30)  # 第一个红外摄像头 左#启用红外摄像头流,索引为1,分辨率为1280x720,格式为Y8,帧率为30fps。
config.enable_stream(rs.stream.infrared, 2, 1280, 720,  rs.format.y8, 30)  # 第二个红外摄像头,右# Start streaming
#根据配置启动相机流
conf = pipeline.start(config)
align = rs.align(rs.stream.color)  # 这个函数用于  将深度图像  与彩色图像对齐# align = rs.align(rs.stream.depth) #2025.3.13尝试将  彩色图  与深度图对应,该方法没有用
depth_sensor = conf.get_device().first_depth_sensor()
depth_sensor.set_option(rs.option.emitter_enabled, 1)  # 0关闭红外激光,1开启i =1         #50-63  png  jpg  png    #64    png  png  png
#开始一个无限循环,用于连续捕获图像。
try:while True:# Wait for a coherent pair of frames: depth and color#等待直到有新的帧可用,并分别获取深度帧和颜色帧。如果任一帧丢失,则跳过当前循环。frames = pipeline.wait_for_frames()#对齐彩色和深度图aligned_frames = align.process(frames)  # 获取对齐帧,将深度框与颜色框对齐aligned_depth_frame = aligned_frames.get_depth_frame()  # 获取深度帧aligned_color_frame = aligned_frames.get_color_frame()  # 获取对齐帧中的的color帧# 对齐的两个红外图像aligned_infrared_frame_1 = aligned_frames.get_infrared_frame(1)aligned_infrared_frame_2 = aligned_frames.get_infrared_frame(2)# #未对齐# #未对齐的彩色和深度图# depth_frame = frames.get_depth_frame()# color_frame = frames.get_color_frame()## #未对齐的两个红外图像# # 获取红外图像# infrared_frame_1 = frames.get_infrared_frame(1)# infrared_frame_2 = frames.get_infrared_frame(2)# Validate that both frames are validif not aligned_depth_frame or not aligned_color_frame:continue# if not depth_frame or not color_frame:#     continue# Convert images to numpy arrays#将深度和颜色帧转换为NumPy数组。#对齐aligned_depth_image = np.asanyarray(aligned_depth_frame.get_data())aligned_color_image = np.asanyarray(aligned_color_frame.get_data())aligned_ir_image_1 = np.asanyarray(aligned_infrared_frame_1.get_data())aligned_ir_image_2 = np.asanyarray(aligned_infrared_frame_2.get_data())# #未对齐# depth_image = np.asanyarray(depth_frame.get_data())# color_image = np.asanyarray(color_frame.get_data())## # 将红外帧转换为可显示的图像# ir_image_1 = np.asanyarray(infrared_frame_1.get_data())# ir_image_2 = np.asanyarray(infrared_frame_2.get_data())# Remove background - Set pixels further than clipping_distance to grey# 创建一个3通道的深度图像,并将其与颜色图像组合,去除距离超过1m的背景。grey_color = 153#对齐aligned_depth_image_3d = np.dstack((aligned_depth_image, aligned_depth_image, aligned_depth_image))  # depth image is 1 channel, color is 3 channelsaligned_bg_removed_color = np.where(aligned_depth_image_3d <= 0, grey_color, aligned_color_image)aligned_ir_image_1_2 = np.hstack((aligned_ir_image_1, aligned_ir_image_2))aligned_ir_image_1_2_photo = aligned_ir_image_1_2.copy()# #未对齐# depth_image_3d = np.dstack(#     (depth_image, depth_image,depth_image))  # depth image is 1 channel, color is 3 channels# bg_removed_color = np.where(depth_image_3d <= 0, grey_color, color_image)# Apply colormap on depth image (image must be converted to 8-bit per pixel first)################ 深度图优化# 应用空间滤波器(边缘平滑)spatial = rs.spatial_filter()spatial.set_option(rs.option.filter_magnitude, 2)filtered_frame = spatial.process(aligned_depth_frame)   #接收相机帧,而不是np数组# 应用孔洞填充hole_filling = rs.hole_filling_filter()hole_filling.set_option(rs.option.holes_fill, 2)filled_frame = hole_filling.process(filtered_frame)filled_depth_image = np.asanyarray(filled_frame.get_data())#彩色图 覆盖灰色(深度无效值)aligned_depth_image_3d = np.dstack((filled_depth_image, filled_depth_image,filled_depth_image))  # depth image is 1 channel, color is 3 channelsaligned_bg_removed_color_filled = np.where(aligned_depth_image_3d <= 0, grey_color, aligned_color_image)aligned_depth_colormap_filled = cv2.applyColorMap(cv2.convertScaleAbs(filled_depth_image, alpha=0.05),cv2.COLORMAP_JET)aligned_images_filled = np.hstack((aligned_bg_removed_color_filled, aligned_depth_colormap_filled))################将深度图像转换为彩色图像,以便于可视化。aligned_depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(aligned_depth_image, alpha=0.05), cv2.COLORMAP_JET)aligned_images = np.hstack((aligned_bg_removed_color, aligned_depth_colormap))# np.hstack 水平拼接,   np.vstack 垂直拼接######## #获取深度和颜色图像的尺寸。# depth_colormap_dim = depth_colormap.shape  #行数、列数、通道数# color_colormap_dim = color_image.shape## # If depth and color resolutions are different, resize color image to match depth image for display# #如果深度和颜色图像的尺寸不同,则调整颜色图像的尺寸以匹配深度图像,然后将它们并排显示。# if depth_colormap_dim != color_colormap_dim:#     resized_color_image = cv2.resize(color_image, dsize=(depth_colormap_dim[1], depth_colormap_dim[0]), interpolation=cv2.INTER_AREA)#     images = np.hstack((resized_color_image, depth_colormap))# else:#     images = np.hstack((color_image, depth_colormap))h = 0while (h < 720):# cv2.line(img,(0,i),(1279,i),(0,255,0)):在img图像上绘制一条从点(0,i)到点(1279,i)的水平线。# 线的颜色由BGR值(0,255,0)指定,即绿色。这条线的y坐标是i(图像的行,高),x坐标从0延伸到1279(图像的列,宽)。#对齐cv2.line(aligned_images, (0, h), (2560, h), (0, 255, 0))  #对齐图像cv2.line(aligned_ir_image_1_2, (0, h), (2560, h), (0, 255, 0))# #未对齐# cv2.line(images, (0, i), (2560, i), (0, 255, 0))  #未对齐图像# cv2.line(ir_image_1_2, (0, i), (2560, i), (0, 255, 0))h = h + 36# Show images#对齐后的图像#对齐后的彩色图像(有深度图灰色 覆盖 深度值为0的点)cv2.namedWindow('aligned_RealSense', 0)#可调窗口大小cv2.imshow('aligned_RealSense', aligned_images)#单独运行,无cv2.namedWindow(),##滤波后深度图cv2.namedWindow('aligned_RealSense_filled', 0)  # 可调窗口大小cv2.imshow('aligned_RealSense_filled', aligned_images_filled)  # 单独运行,无cv2.namedWindow(),#红外图像#拼接的红外图像, 1 为左镜头, 2 为右镜头, 拼接后,像素坐标系原点在1 的左上角cv2.namedWindow("aligned_ir_image_1_2", 0)cv2.imshow("aligned_ir_image_1_2", aligned_ir_image_1_2)# #未对齐的图像# cv2.namedWindow('RealSense', 0)  # 可调窗口大小# cv2.imshow('RealSense', images)  # 单独运行,无cv2.namedWindow(),## cv2.namedWindow("ir_image_1_2", 0)# cv2.imshow("ir_image_1_2", ir_image_1_2)# 可以显示窗口,但无法调整大小(opencv-python版本为4.8),可能是opencv安装在虚拟机的问题key = cv2.waitKey(1) & 0xFFif key == ord('w'):  # 如果按下'w'键# 相对路径##深度图#保存对齐彩色图 的深度图(未进行优化)cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_origin_png/depth_origin_%d.png" % i,aligned_depth_image) #aligned_depth_colormap,  aligned_depth_image# 保存对齐彩色图 的深度图(已经进行优化)cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_process/depth_process_%d.png" % i,filled_depth_image)##深度图颜色映射#未优化的深度图颜色映射cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_origin_color/aligned_depth_colormap_%d.png" % i,aligned_depth_colormap)#已优化的深度图颜色映射cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_process_color/aligned_depth_colormap_filled_%d.png" % i,aligned_depth_colormap_filled)##彩色图# 报存彩色图像 jpgcv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\colors_jpg/color_jpg_%d.jpg" % i,aligned_color_image)# 保存彩色图 pngcv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\colors_png/color_png_%d.png" % i,aligned_color_image)##彩色图覆盖灰色(灰色:深度值为0的地方)#原因:使用深度图时可以直接查看是哪个图片深度信息保存较为完整),不需要手动去试#保存未优化的彩色图--灰色覆盖cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\colors_origin_depth_gray/aligned_bg_removed_color_%d.png" %i,aligned_bg_removed_color)#保存未优化的彩色图--灰色覆盖#aligned_bg_removed_color_filledcv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\colors_process_depth_gray/aligned_bg_removed_color_filled_%d.png" % i,aligned_bg_removed_color_filled)# 保存拼接的红外图像cv2.imwrite(r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\inf/inf_hstack_%d.png" % i,aligned_ir_image_1_2_photo )print("Save images %d succeed!" % i)i += 1elif key == ord('q'):  # 如果按下'q'键cv2.destroyAllWindows()break  # 退出循环,关闭窗口#在退出循环或出现异常时,停止相机流。这确保了即使在脚本异常结束时,相机资源也能被正确释放。
finally:# Stop streamingpipeline.stop()

 拍摄效果展示:

 

上图为未优化的深度图, 由于d435i深度相机有三个镜头,相机背对人脸,从左往右依次是:

彩色镜头,红外镜头1,红外投影仪,红外镜头2。

出现空洞的原因:

原因1:深度图主要有红外镜头1,2拍摄图像,通过图像匹配生成,因为 三个镜头是分开的,存在三个不同视角,导致彩色画面中像素在深度图中不存在,因此为无效深度值(这里深度图对齐与彩色图);原因2:光照原因导致图像匹配出现问题。

 上图为经过空间滤波,空洞填充的优化深度图,但是其深度信息,  对于立体物体,尤其是微小的立体物体 存在失真, 本来是有高度层次变化的实例物体点云,优化后, 变为平面点云。对于平面点云效果较好。

点云生成以 彩色图jpg(png也可以), 未优化的深度图png

 3.生成点云

#2025.6.5
"""
可视化 拍摄的点云和深度图参考 open3d课程
"""
"""
对  o3d_vis1  进行修改
"""import open3d as o3d
import  numpy as np
import matplotlib.pyplot as plt
import os
import syscolor_raw_path = r'E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\colors_jpg\color_jpg_9.jpg'depth_raw_path = r'E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_origin_png\depth_origin_9.png'# depth_raw_path = r"E:\pycharm\pyProject_d435i\my_demo\second_demo_photo_v2_2025_5_19\images\depth_process\depth_process_1.png"color_raw = o3d.io.read_image(color_raw_path)
depth_raw = o3d.io.read_image(depth_raw_path)'''def create_from_color_and_depth(self, color, depth, depth_scale=1000.0, depth_trunc=3.0, convert_rgb_to_intensity=True): # real signature unknown; restored from __doc__"""create_from_color_and_depth(color, depth, depth_scale=1000.0, depth_trunc=3.0, convert_rgb_to_intensity=True)Function to make RGBDImage from color and depth imageArgs:color (open3d.geometry.Image): The color image.depth (open3d.geometry.Image): The depth image.depth_scale (float, optional, default=1000.0): The ratio to scale depth values. The depth values will first be scaled and then truncated.depth_trunc (float, optional, default=3.0): Depth values larger than ``depth_trunc`` gets truncated to 0. The depth values will first be scaled and then truncated.convert_rgb_to_intensity (bool, optional, default=True): Whether to convert RGB image to intensity image.Returns:open3d.geometry.RGBDImage"""pass
'''print(1.0/(0.0010000000474974513))  #999.999952502551
rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(color_raw, depth_raw,  depth_scale= 1.0/(0.0010000000474974513), depth_trunc=8.0, convert_rgb_to_intensity=False )  #convert_rgb_to_intensity=False需要设置为False,  否则 彩色图片变为强度度,点云失去彩色信息(变为灰度图)
print('rgbd_image\n',rgbd_image)
"""
rgbd_imageRGBDImage of size 
Color image : 1280x720, with 3 channels.
Depth image : 1280x720, with 1 channels.
Use numpy.asarray to access buffer data.
"""
print("color_raw\n",color_raw)
"""
color_rawImage of size 1280x720, with 3 channels.
Use numpy.asarray to access buffer data.
"""
print("depth_raw\n",depth_raw)
"""
depth_rawImage of size 1280x720, with 1 channels.
Use numpy.asarray to access buffer data.
"""plt.subplot(1, 2, 1) #plt.subplot(1, 2, 1):这行代码创建了一个1行2列的子图布局,并激活了第一个子图(位置索引为1)。
# plt.title('mushroom grayscale image')
plt.title('mushroom  image')
plt.imshow(rgbd_image.color)
plt.subplot(1, 2, 2)
plt.title('mushroom depth image')
plt.imshow(rgbd_image.depth)
plt.show()#The RGBD image can be converted into a point cloud, given a set of camera parameters.
"""
Depth Intrinsics: [ 1280x720  p[640.84 356.49]  f[646.526 646.526]  Brown Conrady [0 0 0 0 0] ]
Color Intrinsics: [ 1280x720  p[648.297 368.739]  f[910.241 909.903]  Inverse Brown Conrady [0 0 0 0 0] ]
"""
#Depth Intrinsics   width=1280, height=720, fx=646.526, fy=646.526 , cx=640.84, cy=356.49
#Color Intrinsics   width=1280, height=720, fx=910.241, fy=909.903 , cx=648.297, cy=368.739
"""
个人相机d435i
深度流
depth_scale=0.0010000000474974513
Width: 1280
Height: 720
PPX: 640.8402099609375
PPY: 356.4901123046875
FX: 646.5264282226562
FY: 646.5264282226562
Distortion Model: distortion.brown_conrady
Coefficients: [0.0, 0.0, 0.0, 0.0, 0.0]"""# #方法1: 参考csdn 点运侠 RGBD/点云(用法总结)
# #自定义内参
# inter = o3d.camera.PinholeCameraIntrinsic()
# inter.set_intrinsics(1280, 720, 646.526, 646.526 , 640.84,356.49)
# #重置相机默认外参
# extrinsic = np.array([[1., 0., 0., 0.],
#                       [0., -1., 0., 0.],
#                       [0., 0., -1., 0.],
#                       [0., 0., 0., -1.]])  #呈现点云与人视线相同
# pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image,inter,extrinsic)# 方法2:参考b站open3d博主教程
#个人相机
# pcd = o3d.geometry.PointCloud.create_from_rgbd_image(
#     rgbd_image,
#     o3d.camera.PinholeCameraIntrinsic(width=1280, height=720, fx=646.526, fy=646.526 , cx=640.84, cy=356.49),
#   )# 精度更高
#个人相机
#该函数的参数
"""
create_from_depth_image(depth, intrinsic, extrinsic=(with default value), depth_scale=1000.0, depth_trunc=1000.0, stride=1, project_valid_depth_only=True)
"""'''def create_from_rgbd_image(self, image, intrinsic, extrinsic, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__ """create_from_rgbd_image(image, intrinsic, extrinsic=(with default value), project_valid_depth_only=True)Factory function to create a pointcloud from an RGB-D image and a camera. Given depth value d at (u, v) image coordinate, the corresponding 3d point is:- z = d / depth_scale- x = (u - cx) * z / fx- y = (v - cy) * z / fyArgs:image (open3d.geometry.RGBDImage): The input image.intrinsic (open3d.camera.PinholeCameraIntrinsic): Intrinsic parameters of the camera.extrinsic (numpy.ndarray[numpy.float64[4, 4]], optional) Default value:array([[1., 0., 0., 0.],[0., 1., 0., 0.],[0., 0., 1., 0.],[0., 0., 0., 1.]])project_valid_depth_only (bool, optional, default=True)Returns:open3d.geometry.PointCloud"""pass'''
#方法2
pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image,o3d.camera.PinholeCameraIntrinsic(width=1280, height=720, fx=646.5264282226562, fy=646.5264282226562 , cx=640.8402099609375, cy=356.4901123046875),project_valid_depth_only = False,)#方法3
# height, width  = 720, 1280
# #Depth Intrinsics   width=1280, height=720, fx=646.526, fy=646.526 , cx=640.84, cy=356.49
# fx, fy = 646.526, 646.526   # 焦距(以像素为单位)
# cx, cy = 640.84, 356.49  # 主点(相机坐标系的中心点)
# # 构建内参矩阵
# intrinsic = o3d.camera.PinholeCameraIntrinsic(width, height, fx, fy, cx, cy)
# # 使用相机内参来生成点云
# pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic, project_valid_depth_only=False) #无效值保存为nan# # Flip it, otherwise the pointcloud will be upside down   上下翻转点云
pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])  #呈现点云与人视相同#M18K数据集,D405深度相机 深度流内参;
#width=1280, height=720, fx=647.2796020507812, fy=647.2796020507812 , cx=652.3068237304688, cy=367.90887451171875
o3d.visualization.draw_geometries([pcd])

获取的彩色图和深度图

 

 

截断距离为3m

注意:此时

project_valid_depth_only = True  该参数设置为True才能显示点云,若设置为False则不会显示点云。不清楚原因,希望看到朋友的可以在评论区解释一下()

 

截断距离设为   depth_trunc=8.0

 

 

 

近距离看,远程点云有些失真,(可能是光照原因)褐色是玻璃(平面),显示的点云为凹形。 

 

参考资料

1.open3d官网RGBD images - Open3D 0.19.0 documentation

2.点云侠

【2025最新版】Open3D 深度图像与彩色图像生成RGBD/点云(用法总结)_3d相机如何生成点云-CSDN博客 

3.kimi.ai

获取相机内参

1.Python读取Realsense D435深度相机内参_pyrealsense2获取深度相机的内参-CSDN博客

2.获取D405相机的内参的方法-CSDN博客

深度相机使用

1.intelrealsense github 代码库示例

相关文章:

  • js 比较两个对象的值,不相等就push对象的key
  • 虚拟仿真技术赋能家庭教育实训室建设要点解析​
  • Cursor AI编程助手模型选择对了吗?
  • C++ Primer Plus 7.8 函数与 array 对象
  • 传统业务对接AI-AI编程框架-Rasa的业务应用实战(2)--选定Python环境 安装rasa并初始化工程
  • springboot实现查询学生
  • 图像尺寸测量仪应用刀具尺寸测量
  • Git操作记录
  • Git Svn
  • Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
  • 【从0-1的CSS】第1篇:CSS简介,选择器已经常用样式
  • C++虚函数表(虚表Virtual Table,简称vtable、VFT)(编译器为支持运行时多态(动态绑定)而自动生成的一种内部数据结构)虚函数指针vptr
  • PPT转图片拼贴工具 v1.0
  • dvwa11——XSS(Reflected)
  • 【Maniskill】使用Ppo的官方基线训练时出现指标突然“塌陷”的现象
  • CSP-VP37th
  • ML Kit与YOLO:移动AI与实时检测终极对决
  • 前缀和题目:逐步求和得到正数的最小值
  • 打造智慧医疗枢纽,香港维尔利引领东南亚健康科技升级
  • 【Docker管理工具】部署Docker可视化管理面板Dpanel
  • 网页游戏折扣充值平台/成都网站优化
  • 政府门户网站建设 投标文件/专业做网站设计
  • 重庆网站设计中心/河北seo基础
  • 电子商务网站规划原则/线上平台推广方式
  • 免费做印章的网站/新闻播报最新
  • 上海做网站比较有名的公司有哪些/免费发广告的平台