Skip to content

Commit a2e7814

Browse files
liubigli-tcpleavauchier
authored andcommitted
updated lidar_hd_pre_transform function; the goal to work also with point clouds that have custom sets of features
1 parent 6e47ce3 commit a2e7814

File tree

4 files changed

+52
-39
lines changed

4 files changed

+52
-39
lines changed

configs/datamodule/hdf5_datamodule.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ points_pre_transform:
1111
_target_: functools.partial
1212
_args_:
1313
- "${get_method:myria3d.pctl.points_pre_transform.lidar_hd.lidar_hd_pre_transform}"
14+
pos_keys: ${dataset_description.pos_keys}
15+
features_keys: ${dataset_description.features_keys}
16+
color_keys: ${dataset_description.color_keys}
1417

1518
pre_filter:
1619
_target_: functools.partial

configs/dataset_description/20220607_151_dalles_proto.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ classification_preprocessing_dict: {3: 5, 4: 5, 160: 64, 161: 64, 162: 64, 0: 1,
1313
# classification_dict = {code_int: name_str, ...} and MUST be sorted (increasing order).
1414
classification_dict: {1: "unclassified", 2: "ground", 5: vegetation, 6: "building", 9: water, 17: bridge, 64: lasting_above}
1515

16+
pos_keys: ["X", "Y", "Z"]
17+
features_keys: ["Intensity", "ReturnNumber", "NumberOfReturns"]
18+
color_keys: ["Red", "Green", "Blue", "Infrared"]
19+
1620
# class_weights for the CrossEntropyLoss with format "[[w1,w2,w3...,wk]]" with w_i a float e.g. 1.0
1721
# Balanced CE: arbitrary weights based on heuristic.
1822
# class_weights: [2.5,1.0,1.0,5.0,20.0,20.0,20.0] normalized so they sum to 7 to preserve scale of CELoss

docs/source/apidoc/default_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ datamodule:
111111
_target_: functools.partial
112112
_args_:
113113
- ${get_method:myria3d.pctl.points_pre_transform.lidar_hd.lidar_hd_pre_transform}
114+
pos_keys: ${dataset_description.pos_keys}
115+
features_keys: ${dataset_description.features_keys}
116+
color_keys: ${dataset_description.color_keys}
114117
pre_filter:
115118
_target_: functools.partial
116119
_args_:
Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,82 @@
11
# function to turn points loaded via pdal into a pyg Data object, with additional channels
2+
from typing import List
23
import numpy as np
4+
import torch
35
from torch_geometric.data import Data
46

57
COLORS_NORMALIZATION_MAX_VALUE = 255.0 * 256.0
68
RETURN_NUMBER_NORMALIZATION_MAX_VALUE = 7.0
79

810

9-
def lidar_hd_pre_transform(points):
11+
def lidar_hd_pre_transform(points, pos_keys: List[str], features_keys: List[str], color_keys: List[str]):
1012
"""Turn pdal points into torch-geometric Data object.
1113
1214
Builds a composite (average) color channel on the fly. Calculate NDVI on the fly.
1315
1416
Args:
1517
las_filepath (str): path to the LAS file.
16-
18+
pos_keys (List[str]): list of keys for positions and base features
19+
features_keys (List[str]): list of keys for
1720
Returns:
1821
Data: the point cloud formatted for later deep learning training.
1922
2023
"""
24+
25+
features = pos_keys + features_keys + color_keys
2126
# Positions and base features
22-
pos = np.asarray([points["X"], points["Y"], points["Z"]], dtype=np.float32).transpose()
27+
pos = np.asarray([points[k] for k in pos_keys], dtype=np.float32).transpose()
2328
# normalization
24-
occluded_points = points["ReturnNumber"] > 1
29+
if "ReturnNumber" in features:
30+
occluded_points = points["ReturnNumber"] > 1
31+
points["ReturnNumber"] = (points["ReturnNumber"]) / (RETURN_NUMBER_NORMALIZATION_MAX_VALUE)
32+
points["NumberOfReturns"] = (points["NumberOfReturns"]) / (
33+
RETURN_NUMBER_NORMALIZATION_MAX_VALUE
34+
)
35+
else:
36+
occluded_points = np.zeros(pos.shape[0], dtype=np.bool_)
2537

26-
points["ReturnNumber"] = (points["ReturnNumber"]) / (RETURN_NUMBER_NORMALIZATION_MAX_VALUE)
27-
points["NumberOfReturns"] = (points["NumberOfReturns"]) / (
28-
RETURN_NUMBER_NORMALIZATION_MAX_VALUE
29-
)
30-
31-
for color in ["Red", "Green", "Blue", "Infrared"]:
38+
for color in color_keys:
3239
assert points[color].max() <= COLORS_NORMALIZATION_MAX_VALUE
3340
points[color][:] = points[color] / COLORS_NORMALIZATION_MAX_VALUE
3441
points[color][occluded_points] = 0.0
3542

3643
# Additional features :
3744
# Average color, that will be normalized on the fly based on single-sample
38-
rgb_avg = (
39-
np.asarray([points["Red"], points["Green"], points["Blue"]], dtype=np.float32)
40-
.transpose()
41-
.mean(axis=1)
42-
)
45+
if "Red" in color_keys and "Green" in color_keys and "Blue" in color_keys:
46+
rgb_avg = (
47+
np.asarray([points["Red"], points["Green"], points["Blue"]], dtype=np.float32)
48+
.transpose()
49+
.mean(axis=1)
50+
)
51+
else:
52+
rgb_avg = None
4353

4454
# NDVI
45-
ndvi = (points["Infrared"] - points["Red"]) / (points["Infrared"] + points["Red"] + 10**-6)
55+
if "Infrared" in color_keys and "Red" in color_keys:
56+
ndvi = (points["Infrared"] - points["Red"]) / (points["Infrared"] + points["Red"] + 10**-6)
57+
else:
58+
ndvi = None
59+
60+
additional_color_features = []
61+
additional_color_keys = []
62+
if rgb_avg is not None:
63+
additional_color_features.append(rgb_avg)
64+
additional_color_keys.append("rgb_avg")
65+
if ndvi is not None:
66+
additional_color_features.append(ndvi)
67+
additional_color_keys.append("ndvi")
4668

47-
# todo
4869
x = np.stack(
4970
[
5071
points[name]
51-
for name in [
52-
"Intensity",
53-
"ReturnNumber",
54-
"NumberOfReturns",
55-
"Red",
56-
"Green",
57-
"Blue",
58-
"Infrared",
59-
]
72+
for name in features_keys + color_keys
6073
]
61-
+ [rgb_avg, ndvi],
74+
+ additional_color_features,
6275
axis=0,
6376
).transpose()
64-
x_features_names = [
65-
"Intensity",
66-
"ReturnNumber",
67-
"NumberOfReturns",
68-
"Red",
69-
"Green",
70-
"Blue",
71-
"Infrared",
72-
"rgb_avg",
73-
"ndvi",
74-
]
77+
x_features_names = [s.encode('utf-8') for s in (features_keys + color_keys + additional_color_keys)]
7578
y = points["Classification"]
7679

77-
data = Data(pos=pos, x=x, y=y, x_features_names=x_features_names)
80+
data = Data(pos=torch.from_numpy(pos), x=torch.from_numpy(x), y=y, x_features_names=x_features_names)
7881

7982
return data

0 commit comments

Comments
 (0)