Open3D从RGBD图像创建点云时遭遇不支持的图像格式错误
问题分析与解决
报错Unsupported image format的核心原因有两个:
- RGB图与深度图尺寸不匹配:GLPN生成深度图时去掉了16像素的padding,导致深度图尺寸(968x968)远小于输入RGB图的1000x1000,Open3D要求两者尺寸完全一致。
- 深度图格式错误:代码中将深度图归一化到0-255并转为
uint8,丢失了真实深度信息,且这种格式不符合Open3D对深度图的预期(需为表示实际距离的数值类型,如uint16或float32)。
修改步骤
1. 修正深度图尺寸,确保与输入图像一致
在GenerateDepthMap函数末尾添加resize逻辑,将处理后的深度图还原为输入图像的尺寸:
def GenerateDepthMap(input_image): # 原有加载模型与推理代码不变 padding = 16 output = predicted_depth.squeeze().cpu().numpy() * 1000.0 output = output[padding:-padding, padding:-padding] # 新增:resize回输入图像的尺寸 output = cv2.resize(output, input_image.size, interpolation=cv2.INTER_LINEAR) return output
2. 修正深度图的数据类型与处理逻辑
在GeneratePointcloud3D函数中,去掉错误的归一化操作,将深度图转为uint16(存储毫米级深度值,符合Open3D要求):
def GeneratePointcloud3D(input_image, depth_map): width, height = input_image.size input_image = np.array(input_image) # 修改:直接转为uint16,保留真实深度值(毫米级) depth_map = depth_map.astype(np.uint16) depth_3d = o3d.geometry.Image(depth_map) image_3d = o3d.geometry.Image(input_image) # 新增depth_scale参数,深度值为毫米级,设置为1.0表示每个单位对应1毫米 rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( image_3d, depth_3d, depth_scale=1.0, convert_rgb_to_intensity=False ) # 原有相机设置与点云生成代码不变 camera_intrinsic = o3d.camera.PinholeCameraIntrinsic() camera_intrinsic.set_intrinsic(width, height, 500, 500, width / 2, height / 2) pointcloud = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, camera_intrinsic) return pointcloud
3. 可选优化:调整相机内参
如果生成的点云比例不符合预期,可以根据实际相机参数调整内参中的焦距(当前代码设置为500,可按需修改)。
完整修改后的核心代码片段
def GenerateDepthMap(input_image): feature_extractor = GLPNImageProcessor.from_pretrained("vinvino02/glpn-nyu") model = GLPNForDepthEstimation.from_pretrained("vinvino02/glpn-nyu") inputs = feature_extractor(images=input_image, return_tensors="pt") with torch.no_grad(): outputs = model(**inputs) predicted_depth = outputs.predicted_depth padding = 16 output = predicted_depth.squeeze().cpu().numpy() * 1000.0 output = output[padding:-padding, padding:-padding] # 还原为输入图像尺寸 output = cv2.resize(output, input_image.size, interpolation=cv2.INTER_LINEAR) return output def GeneratePointcloud3D(input_image, depth_map): width, height = input_image.size input_image = np.array(input_image) # 转换为uint16存储毫米级深度 depth_map = depth_map.astype(np.uint16) depth_3d = o3d.geometry.Image(depth_map) image_3d = o3d.geometry.Image(input_image) rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( image_3d, depth_3d, depth_scale=1.0, convert_rgb_to_intensity=False ) camera_intrinsic = o3d.camera.PinholeCameraIntrinsic() camera_intrinsic.set_intrinsic(width, height, 500, 500, width / 2, height / 2) pointcloud = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, camera_intrinsic) return pointcloud
内容的提问来源于stack exchange,提问作者nowsqwhat
相关产品推荐
相关产品推荐

