Cluster Point Cloud Based on Density Jump
SUMMARY
Cluster Point Cloud Based on Density Jump segments a point cloud by detecting sharp changes in point density and splitting the cloud at the strongest density discontinuity.
This Skill is particularly useful when objects are closely packed or partially touching, making distance-based clustering unreliable. By analyzing how point density changes along a given axis (or a projected axis), the algorithm can separate objects that are difficult to distinguish using standard clustering methods like DBSCAN.
Use this Skill when you expect clear density transitions in your scene, such as stacked items, layered structures, or objects aligned along a dominant direction, and when traditional clustering struggles to produce clean separations.
The Skill
from telekinesis import vitreous
clusters = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=point_cloud,
projection_axis=[0.0, 0.0, 1.0],
num_nearest_neighbors=12,
neighborhood_radius=0.001,
is_point_cloud_linear=False,
)Performance Note
Current Data Limits: The system currently supports up to 1 million points per request (approximately 16MB of data). We're actively optimizing data transfer performance as part of our beta program, with improvements rolling out regularly to enhance processing speed.
Example
Raw Point Cloud Input
Calculated Clusters
Clusters found based on density change.
Parameters: projection_axis = np.array([0, 0, 1.0]), num_nearest_neighbors=5, neighborhood_radius=0.05.
The Code
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib
# Optional for logging
from loguru import logger
DATA_DIR = pathlib.Path("path/to/telekinesis-data")
# Load point cloud
filepath = str(DATA_DIR / "point_clouds" / "mug_preprocessed.ply")
point_cloud = io.load_point_cloud(filepath=filepath)
logger.success(f"Loaded point cloud with {len(point_cloud.positions)} points")
# Execute operation
clusters = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=point_cloud,
projection_axis=[0.0, 0.0, 1.0],
num_nearest_neighbors=12,
neighborhood_radius=0.001,
is_point_cloud_linear=False,
)
logger.success(
"Split point cloud based on density jump"
)The Explanation of the Code
In this example, we use the cluster_point_cloud_based_on_density_jump Skill to segment a point cloud into clusters based on sharp changes in point density. After importing the necessary modules and optionally setting up logging, the point cloud is loaded from a .ply file.
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib
# Optional for logging
from loguru import logger
DATA_DIR = pathlib.Path("path/to/telekinesis-data")
# Load point cloud
filepath = str(DATA_DIR / "point_clouds" / "mug_preprocessed.ply")
point_cloud = io.load_point_cloud(filepath=filepath)
logger.success(f"Loaded point cloud with {len(point_cloud.positions)} points")The Skill analyzes local neighborhoods of points and identifies the steepest drop in density along a specified axis (in this case, the Z-axis). Points are then split into clusters wherever a density jump occurs. This is particularly useful in robotic manipulation and inspection pipelines, for example, separating stacked objects, identifying distinct parts of an assembly, or isolating individual items on a conveyor belt.
# Execute operation
clusters = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=point_cloud,
projection_axis=[0.0, 0.0, 1.0],
num_nearest_neighbors=12,
neighborhood_radius=0.001,
is_point_cloud_linear=False,
)
logger.success(
"Split point cloud based on density jump"
)Running the Example
Runnable examples are available in the Telekinesis examples repository. Follow the README in that repository to set up the environment. Once set up, you can run this specific example with:
cd telekinesis-examples
python examples/vitreous_examples.py --example cluster_point_cloud_based_on_density_jumpHow to Tune the Parameters
The cluster_point_cloud_based_on_density_jump Skill has four parameters that control how density is calculated and where the split occurs:
projection_axis (required):
- Defines the direction along which density changes are analyzed
- Set to the principal axis of the point cloud for best results
- Typical values:
[0, 0, 1]for vertical (Z-axis),[1, 0, 0]for horizontal along X-axis - Should align with the direction where you expect density discontinuities
num_nearest_neighbors (default: 12):
- The number of nearest neighbors used for density estimation at each point
- Increase (15-30) for more stable density calculation, but slower and may smooth out small density changes
- Decrease (6-10) for more sensitivity to local variations, but may be affected by noise
- Typical range: 6-30
neighborhood_radius (default: 0.001):
- The radius of the spherical neighborhood used for density calculation
- Units: Uses the same units as your point cloud (e.g., if point cloud is in meters, radius is in meters; if in millimeters, radius is in millimeters)
- Increase to consider points from a larger area, making estimates more robust but less sensitive to local changes
- Decrease for more sensitivity to local density variations, but may be affected by noise
- Should be set based on the scale of your point cloud:
- Millimeter-scale point clouds (e.g., Zivid where 1 unit = 1 mm): Typical values 1-50 (representing 1-50 mm radius)
- Centimeter-scale point clouds (e.g., 1 unit = 1 cm): Typical values 0.1-5 (representing 0.1-5 cm radius)
- Meter-scale point clouds (e.g., 1 unit = 1 m): Typical values 0.001-0.1 (representing 0.001-0.1 m radius)
is_point_cloud_linear (default: False):
- Set to
Trueif the point cloud represents a linear structure (e.g., rod or wire) - Set to
Falsefor 2D or 3D structures - When
True, uses a different density calculation method optimized for linear structures
TIP
Best practice: Start with default values and adjust projection_axis to align with the principal direction of your objects. Then fine-tune neighborhood_radius based on your point cloud scale (remember it uses the same units as your point cloud), and adjust num_nearest_neighbors if the split is too sensitive or not sensitive enough.
Where to Use the Skill in a Pipeline
Density jump clustering is commonly used in the following pipelines:
- Stacked object separation
- Layered structure analysis
- Assembly part identification
- Conveyor belt item isolation
A typical pipeline for stacked object separation looks as follows:
# Example pipeline using density jump clustering (parameters omitted).
from telekinesis import vitreous
import numpy as np
# 1. Load raw point cloud
point_cloud = vitreous.load_point_cloud(...)
# 2. Preprocess: remove outliers and downsample
filtered_cloud = vitreous.filter_point_cloud_using_statistical_outlier_removal(...)
downsampled_cloud = vitreous.filter_point_cloud_using_voxel_downsampling(...)
# 3. Cluster based on density jump (assuming vertical stacking)
clusters = vitreous.cluster_point_cloud_based_on_density_jump(
point_cloud=downsampled_cloud,
projection_axis=[0.0, 0.0, 1.0], # Vertical axis
num_nearest_neighbors=12,
neighborhood_radius=0.001,
is_point_cloud_linear=False,
)
# 4. Process each cluster separately
for cluster in clusters:
# Compute bounding box, centroid, or other analysis
centroid = vitreous.calculate_point_cloud_centroid(point_cloud=cluster)
bbox = vitreous.calculate_oriented_bounding_box(point_cloud=cluster)Related skills to build such a pipeline:
filter_point_cloud_using_statistical_outlier_removal: clean input before clusteringfilter_point_cloud_using_voxel_downsampling: reduce point cloud density for faster processingcluster_point_cloud_using_dbscan: alternative clustering method for distance-based separationcalculate_point_cloud_centroid: compute center of each clustercalculate_oriented_bounding_box: compute bounding box for each cluster
Alternative Skills
| Skill | vs. Cluster Based on Density Jump |
|---|---|
| cluster_point_cloud_using_dbscan | Use DBSCAN when objects are spatially separated. Use density jump clustering when objects are closely packed or touching and you need to separate them based on density changes along an axis. |
When Not to Use the Skill
Do not use cluster based on density jump when:
- Objects are clearly separated in space (use
cluster_point_cloud_using_dbscaninstead) - There is no clear density discontinuity along any axis (the algorithm may not find a meaningful split)
- You need more than 2 clusters (this Skill always produces exactly 2 clusters)
- The point cloud has uniform density (no density jump to detect)
- You don't know the principal axis (you need to identify the projection axis first)
WARNING
This Skill always produces exactly 2 clusters by splitting at the strongest density discontinuity. If you need multiple clusters or objects are not aligned along a single axis, consider using cluster_point_cloud_using_dbscan instead.

