AbelPierre 2023-02-14 20:45 采纳率: 0%
浏览 140
已结题

python-pcl存储彩色点云至PCD中的rgb值发生变化导致图片失真

问题描述:python-pcl将彩色点云存储至PCD后,RGB的ASCII值发生巨大变化,导致图片失真。ASCII值如图1所示,原图片和失真图片如图2所示

img

图1 打开PCD的图,左为rosrun pcl_ros pcl_to_pcd出来的图,右为自己代码的图(RGB的部分不对),代码见下部代码块

img

图2 可视化点云图,左为正确图,右为失真图


import rospy
import numpy as np
import cv2
import pcl
from pcl import pcl_visualization
import ros_numpy
import open3d as o3d
from sensor_msgs.msg import PointCloud2
from sensor_msgs import point_cloud2
from sensor_msgs.msg import PointField

address = "/home/wmra/catkin_ws/src/my_pcl_tutorial/pictures2"

def morphological_primitives_running(msg):
    pcl_points = ros_numpy.numpify(msg) # ros_numpy.numpify()生成的图片是[Heijht,Weight,4],高宽和宽度是像素坐标,"4"是像素坐标上点云的xyz和颜色
    print("pcl_points",pcl_points)
    pcl_points_color = ros_numpy.point_cloud2.split_rgb_field(pcl_points) # 分离点云点的RGB通道
    print("pcl_points_color",pcl_points_color)
    height, width = pcl_points.shape[0], pcl_points.shape[1] # 图片像素高度,矩阵行数480 图片像素宽度,矩阵列数640 shape[2]是通道数 
    print("pcl_points.shape",pcl_points.shape)
    print("pcl_points_color['b']",pcl_points_color['b'])
    print("pcl_points_color['g']",pcl_points_color['g'])
    print("pcl_points_color['r']",pcl_points_color['r'])
    #img = cv2.imread("/home/wmra/catkin_ws/src/my_pcl_tutorial/scripts/grasp3_Color.png")
    #b,g,r = cv2.split(img)
    #img_rgb = cv2.merge([r,g,b])
    img_rgb = cv2.merge([np.array(pcl_points_color['b']), np.array(pcl_points_color['g']), np.array(pcl_points_color['r'])])
    #cv2.imshow("img_rgb", img_rgb)
    #cv2.waitKey(0)
    pcl_points_color_red, pcl_points_color_green, pcl_points_color_blue = np.resize(pcl_points_color['r'], height * width), np.resize(pcl_points_color['g'], height * width), np.resize(pcl_points_color['b'], height * width) # 将三色提取出来,[:, :, np.newaxis] np.newaxis放在哪个位置,就会给哪个位置增加维度
    pcl_points_color_red, pcl_points_color_green, pcl_points_color_blue = pcl_points_color_red.astype(np.uint32), pcl_points_color_green.astype(np.uint32), pcl_points_color_blue.astype(np.uint32)  # 
    pcl_pcd_points = np.zeros((height * width, 3), dtype=np.float32)
    pcl_pcd_rgb = np.zeros((height * width, 1), dtype=np.uint32)
    print("pcl_points_color['x']",pcl_points_color['x'])
    pcl_pcd_points[:, 0] = np.resize(pcl_points_color['x'], height * width) # 有序点云按照图片从左到右依次排列
    pcl_pcd_points[:, 1] = np.resize(pcl_points_color['y'], height * width)
    pcl_pcd_points[:, 2] = np.resize(pcl_points_color['z'], height * width)
    pcl_pcd_rgb[:, 0] = 255 << 24 | pcl_points_color_red << 16 | pcl_points_color_green << 8 | pcl_points_color_blue     # <<是左移运算符,转换为2进制,然后左移1位,此时十进制2变成十进制4
    pcl_pcd = np.concatenate((pcl_pcd_points, pcl_pcd_rgb), axis=1)
    print("pcl_pcd",pcl_pcd)
    cloud_points = pcl.PointCloud_PointXYZRGB()
    cloud_points.from_list(pcl_pcd)
    print(type(cloud_points))
    print(cloud_points[3])
    print("Saving points in 1.pcd")
    pcl.save(cloud_points, address + '/1.pcd', format = "pcd")  # 存储全部点云


def ros_running():
    rospy.init_node('morphological_primitives_ros', anonymous=True)
    rospy.Subscriber("/camera/depth_registered/points", PointCloud2, morphological_primitives_running, queue_size= 5)  #realsense
    rospy.spin()


if __name__ == "__main__":
   
    ros_running() 

补充描述

在pcl.save之前的 print("pcl_pcd",pcl_pcd) 结果为

pcl_pcd [[-2.90159917e+00 -2.20055056e+00  5.37000036e+00  4.28272238e+09]
 [-2.89273000e+00 -2.20055056e+00  5.37000036e+00  4.28298555e+09]
 [-2.86130571e+00 -2.18333936e+00  5.32800007e+00  4.28278842e+09]
 ...
 [            nan             nan             nan  4.28864552e+09]
 [            nan             nan             nan  4.28884213e+09]
 [            nan             nan             nan  4.28877633e+09]]

之后的print(cloud_points[3])结果为:


(-2.852505922317505, -2.1833393573760986, 5.328000068664551, 4282591232.0)

希望在不改变基本代码框架(用ros的数据即可)的情况下得到各位的指导

  • 写回答

6条回答 默认 最新

  • 志在青云 2023-02-14 20:58
    关注

    在将彩色点云存储至PCD文件中时,您将RGB信息合并到了一个32位的无符号整数中,但在存储之前,RGB通道的值需要进行类型转换,以适应这样的数据格式。在您的代码中,您使用了.astype(np.uint32)将RGB通道转换为32位的无符号整数,但这会导致RGB值的范围从0-255变为0-4294967295。在打开PCD文件时,一些软件将RGB值视为ASCII字符,因此在转换过程中发生了失真。为了解决这个问题,您可以将RGB值转换为0-255的范围,然后再将它们合并到一个32位的无符号整数中。例如,您可以使用以下代码转换RGB通道:

    [pcl_points_color_red = (pcl_points_color['r'] * 255).astype(np.uint32)
    pcl_points_color_green = (pcl_points_color['g'] * 255).astype(np.uint32)
    pcl_points_color_blue = (pcl_points_color['b'] * 255).astype(np.uint32)]()
    
    

    这将RGB值从0-1的范围转换为0-255的范围,以便在存储到PCD文件中时保留颜色信息。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 2月22日
  • 创建了问题 2月14日