Deep Learning Techniques in Point Clouds
LiDAR

Understanding the Nature of Point Cloud Data

Point cloud data plays a crucial role in various 3D technologies. This blog post introduces this data format, explaining how it represents objects and scenes as collections of 3D points. We’ll delve into the unique properties of point clouds, including their unordered nature and rich information content.

This is the first part of the Point Cloud Fundamentals topic in Deep Learning Techniques in Point Clouds series.

Point cloud data represents a collection of points in space, typically defined by their X, Y, and Z coordinates. This collection of points represents the external surface of objects or scenes in 3D space. Point clouds are fundamentally unordered; the points are listed without any inherent structure, and changing the order of the points does not change the represented scene or object. This lack of order poses a challenge for certain computational processes, such as deep learning techniques like convolutional neural networks (CNNs), which are traditionally applied to ordered, structured data​​.

Point clouds can include not only the position of points but also additional features such as surface normals, RGB values, and reflective intensity, making them a versatile format for representing the 3D world. This versatility has led to their widespread application across various fields, including robotics, autonomous vehicles, augmented and virtual reality, and industrial purposes like manufacturing and building rendering​​​​.

However, point clouds are inherently irregular and unstructured. The points are not evenly sampled across different regions of an object or scene, resulting in areas with varying densities of points. This irregularity and the lack of a fixed distance between neighboring points contrast with more structured data types, such as pixel arrays in images, where each pixel is regularly spaced on a 2D grid​​.

Given these characteristics, working directly with point clouds presents computational and mathematical challenges, especially when attempting to apply machine learning algorithms designed for structured data. These challenges have spurred the development of various techniques to process and analyze point cloud data effectively, including methods for converting point clouds into more structured forms that are amenable to traditional deep learning approaches​​.

Three points example

The following scripts define and manipulate a simple point cloud structure in Python. A point cloud is represented here as a list of dictionaries, where each dictionary corresponds to a single point in 3D space. The attributes of each point include its spatial coordinates (X, Y, Z), a color value in RGB format, and a surface normal vector (nx, ny, nz). Surface normals are essential for various 3D processing tasks as they represent the orientation of the surface at each point, which can be crucial for lighting calculations in graphics or for determining object boundaries in computer vision.

import plotly.graph_objects as go

# Define the point cloud data
point_cloud = [
    {'coordinates': (1, 2, 3), 'rgb': (255, 0, 0), 'normal': (0, 0, 1)},
    {'coordinates': (4, 5, 6), 'rgb': (0, 255, 0), 'normal': (0, 1, 0)},
    {'coordinates': (7, 8, 9), 'rgb': (0, 0, 255), 'normal': (1, 0, 0)},
]

# Extracting coordinates and converting RGB to a format that plotly accepts
x = [p['coordinates'][0] for p in point_cloud]
y = [p['coordinates'][1] for p in point_cloud]
z = [p['coordinates'][2] for p in point_cloud]
colors = ['rgb({},{},{})'.format(*p['rgb']) for p in point_cloud]

# Create a 3D scatter plot
fig = go.Figure(data=[go.Scatter3d(x=x, y=y, z=z, mode='markers',
                                   marker=dict(size=8, color=colors, opacity=0.8))])

# Update plot layout
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))

# Show plot
fig.show()

House part example

import plotly.graph_objects as go
import numpy as np

# Define a more detailed point cloud data for a house
def create_house_point_cloud():
    point_cloud = []
    
    # Base of the house
    for x in np.linspace(-1, 1, 20):  # Front and back
        for y in [-1, 1]:  # Sides
            for z in np.linspace(0, 1, 10):  # Height
                point_cloud.append({'coordinates': (x, y, z), 'rgb': (184, 134, 11)})  # Dark khaki
    
    for y in np.linspace(-1, 1, 20):  # Sides
        for z in np.linspace(0, 1, 10):  # Height
            point_cloud.append({'coordinates': (-1, y, z), 'rgb': (184, 134, 11)})  # Left wall
            point_cloud.append({'coordinates': (1, y, z), 'rgb': (184, 134, 11)})  # Right wall

   # Roof - two sloping sides meeting at a ridge
    for x in np.linspace(-1, 1, 20):
        for y in np.linspace(-1, 1, 20):
            z = 1  # Height of the flat roof
            point_cloud.append({'coordinates': (x, y, z), 'rgb': (255, 0, 0)})  # Red for roof


    # Door
    for x in np.linspace(-0.25, 0.25, 5):
        for z in np.linspace(0, 0.75, 8):
            point_cloud.append({'coordinates': (x, 1, z), 'rgb': (160, 82, 45)})  # Sienna

    # Windows
    for x in np.linspace(-0.75, -0.25, 5):
        for z in np.linspace(0.5, 0.75, 3):
            point_cloud.append({'coordinates': (x, 1, z), 'rgb': (135, 206, 250)})  # SkyBlue
            point_cloud.append({'coordinates': (x, -1, z), 'rgb': (135, 206, 250)})  # SkyBlue
    
    return point_cloud

point_cloud = create_house_point_cloud()

# Extracting coordinates and converting RGB to a format that plotly accepts
x = [p['coordinates'][0] for p in point_cloud]
y = [p['coordinates'][1] for p in point_cloud]
z = [p['coordinates'][2] for p in point_cloud]
colors = ['rgb({},{},{})'.format(*p['rgb']) for p in point_cloud]

# Create a 3D scatter plot
fig = go.Figure(data=[go.Scatter3d(x=x, y=y, z=z, mode='markers',
                                   marker=dict(size=3, color=colors, opacity=0.8))])

# Update plot layout for better visualization
fig.update_layout(
    title="Detailed House Model Using Point Cloud",
    margin=dict(l=0, r=0, b=0, t=0),
    scene=dict(
        xaxis_title='X Axis',
        yaxis_title='Y Axis',
        zaxis_title='Z Axis',
        xaxis=dict(range=[-2, 2]),
        yaxis=dict(range=[-2, 2]),
        zaxis=dict(range=[0, 3]),
    )
)

# Show plot
fig.show()