[Python] How to efficiently convert RGB values to HSV in large pointclouds

Discussão em 'Python' iniciado por Stack, Junho 23, 2025.

  1. Stack

    Stack Membro Participativo

    I work with pointclouds structured like this:

    cloud1 = PyntCloud.from_ply('/home/david/Escritorio/CloudCompareGarden1 - Cloud.ply')

    cloud1.vertex
    Out[3]:
    array([ (-3.6057682037353516, -0.18922901153564453, 150.49591064453125, 206, 205, 208, 2033.0),
    (-3.605868101119995, -0.18912899494171143, 150.4914093017578, 187, 186, 188, 2033.0),
    (-3.3447682857513428, -1.1726289987564087, 149.6341094970703, 115, 81, 65, 1313.0),
    ...,
    (-1.169768214225769, -0.8984289765357971, 147.5572967529297, 43, 22, 11, -1631.0),
    (-1.1530683040618896, -0.8945289850234985, 147.5579071044922, 46, 26, 19, -1375.0),
    (-1.151968240737915, -0.8948289752006531, 147.55889892578125, 52, 33, 27, -1055.0)],
    dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ('scalar_Scalar_field', '<f4')])

    cloud1.vertex['red']
    Out[4]: array([206, 187, 115, ..., 43, 46, 52], dtype=uint8)


    And I want to convert the RGB values of each point into HSV, and then "append" the HSV values as 3 independent scalar fields for each point.

    I've already tried the colorsys module and the scikit-image color module.

    I end with this function, which works:

    def add_hsv(self):
    """ Adds to PyntCloud.vertex the values obtained from conversion RGB-HSV

    This function expects the PyntCloud to have a numpy structured array
    as PyntCloud.vertex attribute, with valid RGB values correctly named
    ('red', 'green', 'blue')

    The corresponding HSV values will be added as 3 news SF for every point
    in PyntCloud.vertex

    Examples
    --------
    >>> cloud = PyntCloud.from_ply('example.ply')
    >>> cloud.add_hsv()
    """

    #: get the rgb from vertex in the right format (creating a fake image)
    #: I should probably wrap this stack method as a function as I use it with distance functions too
    rgb = np.array([np.vstack([self.vertex['red'], self.vertex['green'], self.vertex['blue']]).transpose()])

    #: convert rgb to hsv and get the values undoing the fake image
    hsv = color.rgb2hsv(rgb)[0]

    #: get the values independently
    h = np.array(hsv[:,0] * 360, dtype=[('Hue', np.uint16)])
    s = np.array(hsv[:,1] * 100, dtype=[('Saturation',np.float16)])
    v = np.array(hsv[:,2] * 100, dtype=[('Value', np.float16)])

    #: merge the structured arrays and replace the old vertex attribute
    self.vertex = join_struct_arrays([self.vertex, h, s, v])


    Results:

    cloud1.add_hsv()

    cloud1.vertex
    Out[6]:
    array([ (-3.6057682037353516, -0.18922901153564453, 150.49591064453125, 206, 205, 208, 2033.0, 0.7222222222222222, 0.014423076923076872, 0.8156862745098039),
    (-3.605868101119995, -0.18912899494171143, 150.4914093017578, 187, 186, 188, 2033.0, 0.7499999999999988, 0.010638297872340538, 0.7372549019607844),
    (-3.3447682857513428, -1.1726289987564087, 149.6341094970703, 115, 81, 65, 1313.0, 0.05333333333333332, 0.4347826086956522, 0.45098039215686275),
    ...,
    (-1.169768214225769, -0.8984289765357971, 147.5572967529297, 43, 22, 11, -1631.0, 0.057291666666666664, 0.7441860465116279, 0.16862745098039217),
    (-1.1530683040618896, -0.8945289850234985, 147.5579071044922, 46, 26, 19, -1375.0, 0.043209876543209874, 0.5869565217391305, 0.1803921568627451),
    (-1.151968240737915, -0.8948289752006531, 147.55889892578125, 52, 33, 27, -1055.0, 0.04000000000000002, 0.4807692307692308, 0.20392156862745098)],
    dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ('scalar_Scalar_field', '<f4'), ('Hue', '<f8'), ('Saturation', '<f8'), ('Value', '<f8')])


    But I don't like the fact that I have to generate a 'fake' image in order to be able to use the skimage rgb2hsv function, and then undo the fake image.

    So my questions are:

    1. Is there a way to use the skimage conversion function more efficiently, given my data structure?
    2. Is there any other RGB-HSV conversion function around that could simplify my function (maintaining my original PyntCloud structure)?
    3. Should I write my own RGB-HSV conversion function, optimized to work with my particular data structure?

    Thank you very much

    Continue reading...

Compartilhe esta Página