Python – Adding RGB Values to Laspy Synthetic Point Generation

laslaspylidarpythonrgb

What is the correct way to add RGB values to points made from scratch?

Laspy is working great for me so far. I want to add RGB values to synthetic points that I've generated. I am using 2 numpy arrays. The first stores all of the XYZ (floats) values. The second array stores the point data record (intensity, classification; Red, Green, Blue). There are only 1200 points and they classify fine. When I comment out the "RGB" the file is generated.

Code:

def makeLASfile(finishPoints,LASheader, valuesP):
    #From laspy
    print("Your Making LAS file")
        
    outfile = laspy.file.File("C:\\Users\\XXXXX\\Documents\\Programming\\Python Scripts\\Laspy\\Circleoutput.las", mode="w", header=LASheader)
    outfile.header.offset = LASheader.offset
    outfile.header.scale = [0.001,0.001,0.001]
    
    outfile.x = finishPoints[ :,0]
    outfile.y = finishPoints[ :,1]
    outfile.z = finishPoints[ :,2]
    
    outfile.intensity=valuesP[ :,0] #intensity 
    outfile.flag_byte=valuesP[ :,1] #flag_byte
    outfile.Raw_Classification = valuesP[ :,2] #classification
    outfile.user_data = valuesP[ :,3] #user_data
    outfile.pt_src_id = valuesP[ :,4] #pt_src_id
    outfile.Red = valuesP[ :,5] #red
    #outfile.green=valuesP[ :,6] #green
    #outfile.blue = valuesP[ :,7] #blue 
    
    outfile.close()

The issue is that I have something not formatted correctly for the RGB and I get the following exception:

> Traceback (most recent call last):
  File "C:\Program Files\Python37\lib\site-packages\laspy\base.py", line 1221, in set_dimension
    spec = self.point_format.lookup[name]
KeyError: 'red'

    self.set_dimension("red", red)
  File "C:\Program Files\Python37\lib\site-packages\laspy\base.py", line 1225, in set_dimension
    "not found.")
laspy.util.LaspyException: Dimension: rednot found.*

UPDATE

https://pointly.ai/how-to-convert-your-point-cloud-data-into-las-laz/
provides a nice 'How-to' using Pandas and Laspy

***Update for laspy 2.0 ***

        rgbinfo = (255,127,0)
        red, green, blue = rgbinfo       
        classify = 10
        intensity = 16000            
        point_count = point_array.shape[0]
        print(point_array.shape)            
        print(f'Main las file points = {point_count}')
        filler = np.empty((point_count,1), dtype = int)
        pointrecord = laspy.create(file_version="1.2", point_format=3)
        pointrecord.header.offsets = np.min(point_array, axis=0)
        pointrecord.header.scales = [0.001, 0.001, 0.001]
        pointrecord.header.generating_software = "SSI_RoadScan"
        pointrecord.header.point_count = point_count
        pointrecord = laspy.create(point_format=3,file_version="1.2") 
        pointrecord.x = point_array[:,0]
        pointrecord.y = point_array[:,1]
        pointrecord.z = point_array[:,2]
        filler.fill(classify)
        pointrecord.classification = filler[:,0]
        filler.fill(red)
        pointrecord.red = filler[:,0]
        filler.fill(blue)
        pointrecord.blue = filler[:,0]
        filler.fill(green)
        pointrecord.green = filler[:,0]
        filler.fill(intensity)
        pointrecord.intensity = filler[:,0]
        pointrecord.write(filename)  

Best Answer

The header needs to be set with a point format that supports RGB colors, see: https://pythonhosted.org/laspy/tut_background.html. For LAS 1.2, the minimum point format for color is 2:

header = laspy.header.Header(point_format=2) # LAS point format 2 supports color

with laspy.file.File(output_path, mode="w", header=header) as lasfile:

    lasfile.header.offset = offset
    lasfile.header.scale = [1.0, 1.0, 1.0]

    lasfile.x = xs
    lasfile.y = ys
    lasfile.z = zs

    lasfile.red = reds
    lasfile.green = greens
    lasfile.blue = blues

By the way, the color calls are property attributes in laspy, so calls to "red" and "set_red" are equivalent.

Related Question