1

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)  
2
  • Please edit your question to include an actual question. As it stands, it's just a statement of what you're working on.
    – csk
    Commented Sep 27, 2018 at 20:24
  • I used the same code as above. I have a text file that has XYZ and RGB values in it. To convert it to .las format i use lfile = laspy.file.File(r"D:\las\tolas.las", mode='w',header=LasHeader(x_scale=0.01,y_scale=0.01,z_scale=0.01)) header = laspy.header.Header(point_format=2) lfile.x = x/0.01 lfile.y = y/0.01 lfile.z = z/0.01 lfile.set_red = r lfile.set_green = g lfile.set_blue = b lfile.close() But the RGB values are not being set. Where did I go wrong. The las format is 1.2
    – pinky j
    Commented Jul 23, 2019 at 6:36

2 Answers 2

4

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.

2

The issue was that I was not using the set method from laspy writer. I modified the Outfile.red to outfile.set_red.

This makes a nice las 1.2 file from scratch.

Working code:

def write_las(self, point_array, filename, info):
    #Creates las files for the calculated points and rawpoints 
    try:
        red, green, blue = info            
        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)
        
        hdr = laspy.header.Header()
        hdr.major_version = 1
        hdr.minor_version = 2
        hdr.version_major = 1
        hdr.version_minor = 2
        
        outfile = laspy.file.File(filename, mode="w", header = hdr)
        
        xmin = np.floor(np.min(point_array[:,0]))
        ymin = np.floor(np.min(point_array[:,1]))
        zmin = np.floor(np.min(point_array[:,2]))
        
        outfile.header.offset = [xmin, ymin, zmin]
        outfile.header.scale = [0.001, 0.001, 0.001]
        outfile.header.global_encoding = 9
        outfile.x = point_array[:,0]
        outfile.y = point_array[:,1]
        outfile.z = point_array[:,2]
        filler.fill(classify)
        outfile.classification = filler[:,0]
        filler.fill(red)
        outfile.red = filler[:,0]
        filler.fill(blue)
        outfile.blue = filler[:,0]
        filler.fill(green)
        outfile.green = filler[:,0]
        filler.fill(intensity)
        outfile.intensity = filler[:,0]
        filler.fill(0)
        outfile.return_num = filler[:,0]
        filler.fill(3)
        outfile.num_returns = filler[:,0]
        filler.fill(48658)
        outfile.pt_src_id = filler[:,0]
        
        '''
        Intensity unsigned short 2 bytes
        Return Number 3 bits (bits 0, 1, 2) 3 bits *
        Number of Returns (given pulse) 3 bits (bits 3, 4, 5) 3 bits *
        Scan Direction Flag 1 bit (bit 6) 1 bit *
        Edge of Flight Line 1 bit (bit 7) 1 bit *
        Classification unsigned char 1 byte *
        Scan Angle Rank (-90 to +90) – Left side unsigned char 1 byte *
        User Data unsigned char 1 byte
        Point Source ID unsigned short 2 bytes *
        '''
        outfile.close()

        print(f'Completed {filename} \n')
       
        return 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.