supervisely 6.73.276__py3-none-any.whl → 6.73.277__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of supervisely might be problematic. Click here for more details.
- supervisely/convert/__init__.py +1 -0
- supervisely/convert/base_converter.py +1 -0
- supervisely/convert/pointcloud/kitti_3d/__init__.py +0 -0
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py +139 -0
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py +110 -0
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/METADATA +1 -1
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/RECORD +11 -8
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/LICENSE +0 -0
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/WHEEL +0 -0
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.276.dist-info → supervisely-6.73.277.dist-info}/top_level.txt +0 -0
supervisely/convert/__init__.py
CHANGED
|
@@ -39,6 +39,7 @@ from supervisely.convert.pointcloud.ply.ply_converter import PlyConverter
|
|
|
39
39
|
from supervisely.convert.pointcloud.bag.bag_converter import BagConverter
|
|
40
40
|
from supervisely.convert.pointcloud.lyft.lyft_converter import LyftConverter
|
|
41
41
|
from supervisely.convert.pointcloud.nuscenes_conv.nuscenes_converter import NuscenesConverter
|
|
42
|
+
from supervisely.convert.pointcloud.kitti_3d.kitti_3d_converter import KITTI3DConverter
|
|
42
43
|
|
|
43
44
|
# Pointcloud Episodes
|
|
44
45
|
from supervisely.convert.pointcloud_episodes.sly.sly_pointcloud_episodes_converter import (
|
|
File without changes
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from supervisely import PointcloudAnnotation, ProjectMeta, is_development, logger
|
|
5
|
+
from supervisely.api.api import Api, ApiField
|
|
6
|
+
from supervisely.convert.base_converter import AvailablePointcloudConverters
|
|
7
|
+
from supervisely.convert.pointcloud.kitti_3d import kitti_3d_helper
|
|
8
|
+
from supervisely.convert.pointcloud.pointcloud_converter import PointcloudConverter
|
|
9
|
+
from supervisely.io.fs import (
|
|
10
|
+
dirs_filter,
|
|
11
|
+
file_exists,
|
|
12
|
+
get_file_ext,
|
|
13
|
+
get_file_name,
|
|
14
|
+
get_file_name_with_ext,
|
|
15
|
+
list_files,
|
|
16
|
+
silent_remove,
|
|
17
|
+
)
|
|
18
|
+
from supervisely.pointcloud_annotation.pointcloud_object_collection import (
|
|
19
|
+
PointcloudObjectCollection,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class KITTI3DConverter(PointcloudConverter):
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return AvailablePointcloudConverters.KITTI3D
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def key_file_ext(self) -> str:
|
|
29
|
+
return ".bin"
|
|
30
|
+
|
|
31
|
+
def validate_format(self) -> bool:
|
|
32
|
+
def _file_filter_fn(file_path):
|
|
33
|
+
return get_file_ext(file_path).lower() == self.key_file_ext
|
|
34
|
+
|
|
35
|
+
def _dir_filter_fn(path):
|
|
36
|
+
return all([(Path(path) / name).exists() for name in kitti_3d_helper.FOLDER_NAMES])
|
|
37
|
+
|
|
38
|
+
input_paths = [d for d in dirs_filter(self._input_data, _dir_filter_fn)]
|
|
39
|
+
if len(input_paths) == 0:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
input_path = input_paths[0]
|
|
43
|
+
velodyne_dir = os.path.join(input_path, "velodyne")
|
|
44
|
+
image_2_dir = os.path.join(input_path, "image_2")
|
|
45
|
+
label_2_dir = os.path.join(input_path, "label_2")
|
|
46
|
+
calib_dir = os.path.join(input_path, "calib")
|
|
47
|
+
|
|
48
|
+
self._items = []
|
|
49
|
+
velodyne_files = list_files(velodyne_dir, filter_fn=_file_filter_fn)
|
|
50
|
+
if len(velodyne_files) == 0:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
kitti_labels = []
|
|
54
|
+
for velodyne_path in velodyne_files:
|
|
55
|
+
file_name = get_file_name(velodyne_path)
|
|
56
|
+
image_path = os.path.join(image_2_dir, f"{file_name}.png")
|
|
57
|
+
label_path = os.path.join(label_2_dir, f"{file_name}.txt")
|
|
58
|
+
calib_path = os.path.join(calib_dir, f"{file_name}.txt")
|
|
59
|
+
if not file_exists(image_path):
|
|
60
|
+
logger.debug(f"Skipping item: {velodyne_path}. Image not found.")
|
|
61
|
+
continue
|
|
62
|
+
if not file_exists(label_path):
|
|
63
|
+
logger.debug(f"Skipping item: {velodyne_path}. Label not found.")
|
|
64
|
+
continue
|
|
65
|
+
if not file_exists(calib_path):
|
|
66
|
+
logger.debug(f"Skipping item: {velodyne_path}. Calibration not found.")
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
label = kitti_3d_helper.read_kitti_label(label_path, calib_path)
|
|
70
|
+
kitti_labels.append(label)
|
|
71
|
+
self._items.append(self.Item(velodyne_path, label, (image_path, calib_path)))
|
|
72
|
+
|
|
73
|
+
self._meta = kitti_3d_helper.convert_labels_to_meta(kitti_labels)
|
|
74
|
+
return self.items_count > 0
|
|
75
|
+
|
|
76
|
+
def to_supervisely(
|
|
77
|
+
self,
|
|
78
|
+
item: PointcloudConverter.Item,
|
|
79
|
+
meta: ProjectMeta,
|
|
80
|
+
renamed_classes: dict = {},
|
|
81
|
+
renamed_tags: dict = {},
|
|
82
|
+
) -> PointcloudAnnotation:
|
|
83
|
+
label = item.ann_data
|
|
84
|
+
objs, figures = kitti_3d_helper.convert_label_to_annotation(label, meta, renamed_classes)
|
|
85
|
+
return PointcloudAnnotation(PointcloudObjectCollection(objs), figures)
|
|
86
|
+
|
|
87
|
+
def upload_dataset(self, api: Api, dataset_id: int, batch_size: int = 1, log_progress=True):
|
|
88
|
+
meta, renamed_classes, renamed_tags = self.merge_metas_with_conflicts(api, dataset_id)
|
|
89
|
+
|
|
90
|
+
if log_progress:
|
|
91
|
+
progress, progress_cb = self.get_progress(self.items_count, "Converting pointclouds...")
|
|
92
|
+
else:
|
|
93
|
+
progress_cb = None
|
|
94
|
+
|
|
95
|
+
for item in self._items:
|
|
96
|
+
# * Convert pointcloud from ".bin" to ".pcd"
|
|
97
|
+
pcd_path = str(Path(item.path).with_suffix(".pcd"))
|
|
98
|
+
if file_exists(pcd_path):
|
|
99
|
+
logger.warning(f"Overwriting file with path: {pcd_path}")
|
|
100
|
+
kitti_3d_helper.convert_bin_to_pcd(item.path, pcd_path)
|
|
101
|
+
|
|
102
|
+
# * Upload pointcloud
|
|
103
|
+
pcd_name = get_file_name_with_ext(pcd_path)
|
|
104
|
+
info = api.pointcloud.upload_path(dataset_id, pcd_name, pcd_path, {})
|
|
105
|
+
pcd_id = info.id
|
|
106
|
+
|
|
107
|
+
# * Convert annotation and upload
|
|
108
|
+
ann = self.to_supervisely(item, meta, renamed_classes, renamed_tags)
|
|
109
|
+
api.pointcloud.annotation.append(pcd_id, ann)
|
|
110
|
+
|
|
111
|
+
# * Upload related images
|
|
112
|
+
image_path, calib_path = item._related_images
|
|
113
|
+
rimage_info = kitti_3d_helper.convert_calib_to_image_meta(image_path, calib_path)
|
|
114
|
+
|
|
115
|
+
image_jsons = []
|
|
116
|
+
camera_names = []
|
|
117
|
+
img = api.pointcloud.upload_related_image(image_path)
|
|
118
|
+
image_jsons.append(
|
|
119
|
+
{
|
|
120
|
+
ApiField.ENTITY_ID: pcd_id,
|
|
121
|
+
ApiField.NAME: get_file_name_with_ext(rimage_info[ApiField.NAME]),
|
|
122
|
+
ApiField.HASH: img,
|
|
123
|
+
ApiField.META: rimage_info[ApiField.META],
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
camera_names.append(rimage_info[ApiField.META]["deviceId"])
|
|
127
|
+
if len(image_jsons) > 0:
|
|
128
|
+
api.pointcloud.add_related_images(image_jsons, camera_names)
|
|
129
|
+
|
|
130
|
+
# * Clean up
|
|
131
|
+
silent_remove(pcd_path)
|
|
132
|
+
if log_progress:
|
|
133
|
+
progress_cb(1)
|
|
134
|
+
|
|
135
|
+
logger.info(f"Dataset ID:{dataset_id} has been successfully uploaded.")
|
|
136
|
+
|
|
137
|
+
if log_progress:
|
|
138
|
+
if is_development():
|
|
139
|
+
progress.close()
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from supervisely import ObjClass, ObjClassCollection, ProjectMeta
|
|
4
|
+
from supervisely.geometry.cuboid_3d import Cuboid3d
|
|
5
|
+
from supervisely.geometry.point_3d import Vector3d
|
|
6
|
+
from supervisely.pointcloud_annotation.pointcloud_figure import PointcloudFigure
|
|
7
|
+
from supervisely.pointcloud_annotation.pointcloud_object import PointcloudObject
|
|
8
|
+
|
|
9
|
+
FOLDER_NAMES = ["velodyne", "image_2", "label_2", "calib"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def read_kitti_label(label_path, calib_path):
|
|
13
|
+
import open3d as o3d # pylint: disable=import-error
|
|
14
|
+
|
|
15
|
+
calib = o3d.ml.datasets.KITTI.read_calib(calib_path)
|
|
16
|
+
label = o3d.ml.datasets.KITTI.read_label(label_path, calib)
|
|
17
|
+
return label
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def convert_labels_to_meta(labels):
|
|
21
|
+
labels = flatten(labels)
|
|
22
|
+
unique_labels = np.unique([l.label_class for l in labels])
|
|
23
|
+
obj_classes = [ObjClass(k, Cuboid3d) for k in unique_labels]
|
|
24
|
+
meta = ProjectMeta(obj_classes=ObjClassCollection(obj_classes))
|
|
25
|
+
return meta
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def convert_bin_to_pcd(src, dst):
|
|
29
|
+
import open3d as o3d # pylint: disable=import-error
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
bin = np.fromfile(src, dtype=np.float32).reshape(-1, 4)
|
|
33
|
+
except ValueError as e:
|
|
34
|
+
raise Exception(
|
|
35
|
+
f"Incorrect data in the KITTI 3D pointcloud file: {src}. "
|
|
36
|
+
f"There was an error while trying to reshape the data into a 4-column matrix: {e}. "
|
|
37
|
+
"Please ensure that the binary file contains a multiple of 4 elements to be "
|
|
38
|
+
"successfully reshaped into a (N, 4) array.\n"
|
|
39
|
+
)
|
|
40
|
+
points = bin[:, 0:3]
|
|
41
|
+
intensity = bin[:, -1]
|
|
42
|
+
intensity_fake_rgb = np.zeros((intensity.shape[0], 3))
|
|
43
|
+
intensity_fake_rgb[:, 0] = intensity
|
|
44
|
+
pc = o3d.geometry.PointCloud(o3d.utility.Vector3dVector(points))
|
|
45
|
+
pc.colors = o3d.utility.Vector3dVector(intensity_fake_rgb)
|
|
46
|
+
o3d.io.write_point_cloud(dst, pc)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def flatten(list_2d):
|
|
50
|
+
return sum(list_2d, [])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _convert_label_to_geometry(label):
|
|
54
|
+
geometries = []
|
|
55
|
+
for l in label:
|
|
56
|
+
bbox = l.to_xyzwhlr()
|
|
57
|
+
dim = bbox[[3, 5, 4]]
|
|
58
|
+
pos = bbox[:3] + [0, 0, dim[1] / 2]
|
|
59
|
+
yaw = bbox[-1]
|
|
60
|
+
position = Vector3d(float(pos[0]), float(pos[1]), float(pos[2]))
|
|
61
|
+
rotation = Vector3d(0, 0, float(-yaw))
|
|
62
|
+
|
|
63
|
+
dimension = Vector3d(float(dim[0]), float(dim[2]), float(dim[1]))
|
|
64
|
+
geometry = Cuboid3d(position, rotation, dimension)
|
|
65
|
+
geometries.append(geometry)
|
|
66
|
+
return geometries
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def convert_label_to_annotation(label, meta, renamed_class_names: dict = None):
|
|
70
|
+
geometries = _convert_label_to_geometry(label)
|
|
71
|
+
figures = []
|
|
72
|
+
objs = []
|
|
73
|
+
for l, geometry in zip(label, geometries): # by object in point cloud
|
|
74
|
+
class_name = renamed_class_names.get(l.label_class, l.label_class)
|
|
75
|
+
pcobj = PointcloudObject(meta.get_obj_class(class_name))
|
|
76
|
+
figures.append(PointcloudFigure(pcobj, geometry))
|
|
77
|
+
objs.append(pcobj)
|
|
78
|
+
|
|
79
|
+
return objs, figures
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def convert_calib_to_image_meta(image_name, calib_path, camera_num=2):
|
|
83
|
+
with open(calib_path, "r") as f:
|
|
84
|
+
lines = f.readlines()
|
|
85
|
+
|
|
86
|
+
assert 0 < camera_num < 4
|
|
87
|
+
intrinsic_matrix = lines[camera_num].strip().split(" ")[1:]
|
|
88
|
+
intrinsic_matrix = np.array(intrinsic_matrix, dtype=np.float32).reshape(3, 4)[:3, :3]
|
|
89
|
+
|
|
90
|
+
obj = lines[4].strip().split(" ")[1:]
|
|
91
|
+
rect_4x4 = np.eye(4, dtype=np.float32)
|
|
92
|
+
rect_4x4[:3, :3] = np.array(obj, dtype=np.float32).reshape(3, 3)
|
|
93
|
+
|
|
94
|
+
obj = lines[5].strip().split(" ")[1:]
|
|
95
|
+
Tr_velo_to_cam = np.eye(4, dtype=np.float32)
|
|
96
|
+
Tr_velo_to_cam[:3] = np.array(obj, dtype=np.float32).reshape(3, 4)
|
|
97
|
+
world_cam = np.transpose(rect_4x4 @ Tr_velo_to_cam)
|
|
98
|
+
extrinsic_matrix = world_cam[:4, :3].T
|
|
99
|
+
|
|
100
|
+
data = {
|
|
101
|
+
"name": image_name,
|
|
102
|
+
"meta": {
|
|
103
|
+
"deviceId": "CAM_LEFT",
|
|
104
|
+
"sensorsData": {
|
|
105
|
+
"extrinsicMatrix": list(extrinsic_matrix.flatten().astype(float)),
|
|
106
|
+
"intrinsicMatrix": list(intrinsic_matrix.flatten().astype(float)),
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
return data
|
|
@@ -560,8 +560,8 @@ supervisely/cli/teamfiles/teamfiles_upload.py,sha256=xnsW2rvdq1e-KGjF1tMBu7Oxh3n
|
|
|
560
560
|
supervisely/collection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
561
561
|
supervisely/collection/key_indexed_collection.py,sha256=x2UVlkprspWhhae9oLUzjTWBoIouiWY9UQSS_MozfH0,37643
|
|
562
562
|
supervisely/collection/str_enum.py,sha256=Zp29yFGvnxC6oJRYNNlXhO2lTSdsriU1wiGHj6ahEJE,1250
|
|
563
|
-
supervisely/convert/__init__.py,sha256=
|
|
564
|
-
supervisely/convert/base_converter.py,sha256=
|
|
563
|
+
supervisely/convert/__init__.py,sha256=742-oqcs_n0YSOQMXPxZoLaZu_72jrMBompsIsUWekI,3043
|
|
564
|
+
supervisely/convert/base_converter.py,sha256=6kQETAOHHRiBXGWCeVVr8Z2dbLYdPHM1to_P3lGvGRY,18028
|
|
565
565
|
supervisely/convert/converter.py,sha256=tWxTDfFv7hwzQhUQrBxzfr6WP8FUGFX_ewg5T2HbUYo,8959
|
|
566
566
|
supervisely/convert/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
567
567
|
supervisely/convert/image/image_converter.py,sha256=r-qdhuwOsk727mXIM26ucQhkoIKigu1M0BF-tw9IfGg,10321
|
|
@@ -613,6 +613,9 @@ supervisely/convert/pointcloud/pointcloud_converter.py,sha256=yCCpzm7GrvL6WT4lNe
|
|
|
613
613
|
supervisely/convert/pointcloud/bag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
614
614
|
supervisely/convert/pointcloud/bag/bag_converter.py,sha256=WWd6A2hS7H4MRgtLdJ-yYgmNU-Wk2eycl6LTTJM2GKQ,11391
|
|
615
615
|
supervisely/convert/pointcloud/bag/bag_helper.py,sha256=2TFe49isZTxMhya-PApqLPxrvGnvRFMBc_--BwyCpWU,4284
|
|
616
|
+
supervisely/convert/pointcloud/kitti_3d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
617
|
+
supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py,sha256=Ipyf1k--0v0Aji7lEbUzseB3E_DqdicuR-eg3ZBkVFk,5462
|
|
618
|
+
supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py,sha256=xrAOD_O7NQu5_rhFF5pE2uwGdZlMh6XXGgtM2rpyd9A,3946
|
|
616
619
|
supervisely/convert/pointcloud/las/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
617
620
|
supervisely/convert/pointcloud/las/las_converter.py,sha256=prbvApwrjQ2cuDD9nAFBDkTLxtsN4jdjCZdNnkNow-g,1722
|
|
618
621
|
supervisely/convert/pointcloud/las/las_helper.py,sha256=1gQ3OZLpe6D25CY_jXWDsrLBiS7nWfCgl3Zq--9TU14,1296
|
|
@@ -1067,9 +1070,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1067
1070
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1068
1071
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1069
1072
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1070
|
-
supervisely-6.73.
|
|
1071
|
-
supervisely-6.73.
|
|
1072
|
-
supervisely-6.73.
|
|
1073
|
-
supervisely-6.73.
|
|
1074
|
-
supervisely-6.73.
|
|
1075
|
-
supervisely-6.73.
|
|
1073
|
+
supervisely-6.73.277.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1074
|
+
supervisely-6.73.277.dist-info/METADATA,sha256=46bfRNq5HF8g4IKBZISbg8yin73sQVYm-XM6H9pnGSA,33573
|
|
1075
|
+
supervisely-6.73.277.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
1076
|
+
supervisely-6.73.277.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1077
|
+
supervisely-6.73.277.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1078
|
+
supervisely-6.73.277.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|