I have managed to write this code containing a simple load button for laz/las file and the VTK rendering widget. It applies some automatic color scheme (which one?) to the point cloud based on the colors that I produce by normalizing intensity values to 0-1 range. Question: how to apply a VTK color series to it? I have seen this piece of code but I do not really know where to put it. I tried it several times at several places but it did not produce desired effect (i.e. application of the chosen color scheme). Not sure - maybe it is related to me using vertex filter object. color_series = vtk.vtkColorSeries() color_series.SetColorSchemeName("Blue") lut = color_series.CreateLookupTable() mapper.SetLookupTable(lut) MRE (not containing the color series part above): import sys import vtk from PySide2.QtWidgets import ( QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QFileDialog, ) import laspy import numpy as np from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor from tqdm import tqdm class PointCloudViewer(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Point Cloud Viewer") self.setGeometry(100, 100, 800, 600) layout = QVBoxLayout() central_widget = QWidget(self) central_widget.setLayout(layout) self.setCentralWidget(central_widget) load_button = QPushButton("Load Point Cloud", self) load_button.clicked.connect(self.load_point_cloud) layout.addWidget(load_button) self.vtk_widget = QVTKRenderWindowInteractor(self) layout.addWidget(self.vtk_widget) self.renderer = vtk.vtkRenderer() self.vtk_widget.GetRenderWindow().AddRenderer(self.renderer) self.vtk_widget.GetRenderWindow().GetInteractor().Initialize() self.vtk_widget.GetRenderWindow().GetInteractor().Start() def load_point_cloud(self): file_dialog = QFileDialog(self) file_dialog.setFileMode(QFileDialog.ExistingFiles) file_dialog.setNameFilter("Point Cloud Files (*.las *.laz)") if file_dialog.exec_(): file_paths = file_dialog.selectedFiles() if file_paths: self.display_point_cloud(file_paths[0]) def display_point_cloud(self, file_path): self.renderer.RemoveAllViewProps() self.renderer.SetBackground(0.1, 0.1, 0.1) points, colors = self.read_point_cloud(file_path) poly_data = vtk.vtkPolyData() poly_data.SetPoints(points) poly_data.GetPointData().SetScalars(colors) vertex_filter = vtk.vtkVertexGlyphFilter() vertex_filter.SetInputData(poly_data) vertex_filter.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(vertex_filter.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) actor.GetProperty().SetPointSize(1) self.renderer.AddActor(actor) self.renderer.ResetCamera() self.vtk_widget.GetRenderWindow().Render() def read_point_cloud(self, file_path): las = laspy.read(file_path) points = np.vstack((las.x, las.y, las.z)).transpose() intensity_data = las.intensity min_intensity = np.min(intensity_data) max_intensity = np.max(intensity_data) intensity_data = (intensity_data - min_intensity) / ( max_intensity - min_intensity ) vtk_colors = vtk.vtkFloatArray() vtk_colors.SetName("Intensity") vtk_points = vtk.vtkPoints() chunk_size = max(10000, len(las) // 100) shift = np.array((points[0][0], points[0][1], points[0][2])) for i in tqdm(range(0, len(las), chunk_size)): chunk = points[i : i + chunk_size] - shift chunk_intensity = intensity_data[i : i + chunk_size] for j, point in enumerate(chunk): vtk_points.InsertNextPoint(point) vtk_colors.InsertNextValue(chunk_intensity[j]) return vtk_points, vtk_colors if __name__ == "__main__": app = QApplication(sys.argv) viewer = PointCloudViewer() viewer.show() sys.exit(app.exec_()) I admit that I barely understand the code I managed to assemble in VTK, so any other improvements & explanations not related directly to the question Continue reading...