supervisely 6.73.377__py3-none-any.whl → 6.73.379__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.
- supervisely/__init__.py +1 -1
- supervisely/api/entity_annotation/tag_api.py +223 -20
- supervisely/api/image_api.py +81 -1
- supervisely/api/pointcloud/pointcloud_api.py +8 -0
- supervisely/convert/image/sly/sly_image_converter.py +10 -7
- supervisely/convert/pointcloud/pointcloud_converter.py +103 -12
- supervisely/convert/pointcloud/sly/sly_pointcloud_converter.py +5 -1
- supervisely/convert/pointcloud_episodes/pointcloud_episodes_converter.py +122 -12
- supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_converter.py +5 -1
- supervisely/project/pointcloud_episode_project.py +126 -4
- supervisely/project/pointcloud_project.py +160 -19
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/METADATA +1 -1
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/RECORD +17 -17
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/LICENSE +0 -0
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/WHEEL +0 -0
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.377.dist-info → supervisely-6.73.379.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import imghdr
|
|
2
2
|
import os
|
|
3
3
|
from typing import Dict, List, Optional, Set, Tuple, Union
|
|
4
|
+
from uuid import UUID
|
|
4
5
|
|
|
5
6
|
from supervisely import (
|
|
6
7
|
Api,
|
|
@@ -16,7 +17,9 @@ from supervisely.io.fs import get_file_ext, get_file_name
|
|
|
16
17
|
from supervisely.io.json import load_json_file
|
|
17
18
|
from supervisely.pointcloud.pointcloud import ALLOWED_POINTCLOUD_EXTENSIONS
|
|
18
19
|
from supervisely.pointcloud.pointcloud import validate_ext as validate_pcd_ext
|
|
20
|
+
from supervisely.pointcloud_annotation.constants import OBJECT_KEY
|
|
19
21
|
from supervisely.project.project_settings import LabelingInterface
|
|
22
|
+
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
class PointcloudEpisodeConverter(BaseConverter):
|
|
@@ -47,7 +50,14 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
47
50
|
def create_empty_annotation(self) -> PointcloudEpisodeAnnotation:
|
|
48
51
|
return PointcloudEpisodeAnnotation()
|
|
49
52
|
|
|
50
|
-
def set_related_images(self, related_images:
|
|
53
|
+
def set_related_images(self, related_images: Tuple[str, str, Optional[str]]) -> None:
|
|
54
|
+
"""Adds related image to the item.
|
|
55
|
+
|
|
56
|
+
related_images tuple:
|
|
57
|
+
- path to image
|
|
58
|
+
- path to .json with image metadata
|
|
59
|
+
- path to .figures.json (can be None if no figures)
|
|
60
|
+
"""
|
|
51
61
|
self._related_images.append(related_images)
|
|
52
62
|
|
|
53
63
|
def __init__(
|
|
@@ -104,7 +114,10 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
104
114
|
else:
|
|
105
115
|
progress_cb = None
|
|
106
116
|
|
|
107
|
-
frame_to_pointcloud_ids = {}
|
|
117
|
+
frame_to_pointcloud_ids: Dict[int, int] = {}
|
|
118
|
+
pcl_to_rimg_figures: Dict[int, Dict[str, List[Dict]]] = {}
|
|
119
|
+
pcl_to_hash_to_id: Dict[int, Dict[str, int]] = {}
|
|
120
|
+
key_id_map = KeyIdMap()
|
|
108
121
|
for batch in batched(self._items, batch_size=batch_size):
|
|
109
122
|
item_names = []
|
|
110
123
|
item_paths = []
|
|
@@ -129,12 +142,21 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
129
142
|
rimg_infos = []
|
|
130
143
|
camera_names = []
|
|
131
144
|
if len(item._related_images) > 0:
|
|
132
|
-
img_paths
|
|
145
|
+
img_paths: List[str] = []
|
|
146
|
+
ann_paths: List[str] = []
|
|
147
|
+
fig_paths: List[Optional[str]] = []
|
|
148
|
+
|
|
149
|
+
for triple in item._related_images:
|
|
150
|
+
img_paths.append(triple[0])
|
|
151
|
+
ann_paths.append(triple[1])
|
|
152
|
+
fig_paths.append(triple[2] if len(triple) > 2 else None)
|
|
153
|
+
|
|
133
154
|
rimg_hashes = api.pointcloud_episode.upload_related_images(img_paths)
|
|
134
|
-
|
|
135
|
-
|
|
155
|
+
|
|
156
|
+
for img_ind, (img_hash, ann_path, fig_path) in enumerate(
|
|
157
|
+
zip(rimg_hashes, ann_paths, fig_paths)
|
|
136
158
|
):
|
|
137
|
-
meta_json = load_json_file(
|
|
159
|
+
meta_json = load_json_file(ann_path)
|
|
138
160
|
try:
|
|
139
161
|
if ApiField.META not in meta_json:
|
|
140
162
|
raise ValueError("Related image meta not found in json file.")
|
|
@@ -152,19 +174,102 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
152
174
|
ApiField.META: meta_json[ApiField.META],
|
|
153
175
|
}
|
|
154
176
|
)
|
|
155
|
-
|
|
177
|
+
|
|
178
|
+
if fig_path is not None:
|
|
179
|
+
try:
|
|
180
|
+
figs_json = load_json_file(fig_path)
|
|
181
|
+
pcl_to_rimg_figures.setdefault(pcd_id, {})[img_hash] = figs_json
|
|
182
|
+
except Exception as e:
|
|
183
|
+
logger.debug(
|
|
184
|
+
f"Failed to read figures json '{fig_path}': {repr(e)}"
|
|
185
|
+
)
|
|
186
|
+
|
|
156
187
|
except Exception as e:
|
|
157
188
|
logger.warning(
|
|
158
|
-
f"Failed to
|
|
189
|
+
f"Failed to process related image meta '{ann_path}': {repr(e)}"
|
|
159
190
|
)
|
|
160
191
|
continue
|
|
161
192
|
|
|
193
|
+
uploaded_rimgs = api.pointcloud.add_related_images(rimg_infos, camera_names)
|
|
194
|
+
try:
|
|
195
|
+
# build mapping hash->id
|
|
196
|
+
for info, uploaded in zip(rimg_infos, uploaded_rimgs):
|
|
197
|
+
img_hash = info.get(ApiField.HASH)
|
|
198
|
+
img_id = (
|
|
199
|
+
uploaded.get(ApiField.ID)
|
|
200
|
+
if isinstance(uploaded, dict)
|
|
201
|
+
else getattr(uploaded, "id", None)
|
|
202
|
+
)
|
|
203
|
+
if img_hash is not None and img_id is not None:
|
|
204
|
+
pcl_to_hash_to_id.setdefault(pcd_id, {})[img_hash] = img_id
|
|
205
|
+
except Exception as e:
|
|
206
|
+
logger.debug(
|
|
207
|
+
f"Failed to build hash->ID mapping for related images: {repr(e)}"
|
|
208
|
+
)
|
|
209
|
+
|
|
162
210
|
if log_progress:
|
|
163
211
|
progress_cb(len(batch))
|
|
164
212
|
|
|
165
213
|
if self.items_count > 0:
|
|
166
214
|
ann = self.to_supervisely(self._items[0], meta, renamed_classes, renamed_tags)
|
|
167
|
-
api.pointcloud_episode.annotation.append(
|
|
215
|
+
api.pointcloud_episode.annotation.append(
|
|
216
|
+
dataset_id, ann, frame_to_pointcloud_ids, key_id_map
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# ---- upload figures for processed batch ----
|
|
220
|
+
if len(pcl_to_rimg_figures) > 0:
|
|
221
|
+
if log_progress:
|
|
222
|
+
progress, progress_cb = self.get_progress(
|
|
223
|
+
self.items_count, "Uploading figures for related images..."
|
|
224
|
+
)
|
|
225
|
+
else:
|
|
226
|
+
progress_cb = None
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
dataset_info = api.dataset.get_info_by_id(dataset_id)
|
|
230
|
+
project_id = dataset_info.project_id
|
|
231
|
+
|
|
232
|
+
figures_to_upload: List[Dict] = []
|
|
233
|
+
for pcl_id, hash_to_figs in pcl_to_rimg_figures.items():
|
|
234
|
+
hash_to_ids = pcl_to_hash_to_id.get(pcl_id, {})
|
|
235
|
+
if len(hash_to_ids) == 0:
|
|
236
|
+
continue
|
|
237
|
+
|
|
238
|
+
for img_hash, figs_json in hash_to_figs.items():
|
|
239
|
+
if img_hash not in hash_to_ids:
|
|
240
|
+
continue
|
|
241
|
+
img_id = hash_to_ids[img_hash]
|
|
242
|
+
|
|
243
|
+
for fig in figs_json:
|
|
244
|
+
try:
|
|
245
|
+
fig[ApiField.ENTITY_ID] = img_id
|
|
246
|
+
fig[ApiField.DATASET_ID] = dataset_id
|
|
247
|
+
fig[ApiField.PROJECT_ID] = project_id
|
|
248
|
+
if OBJECT_KEY in fig:
|
|
249
|
+
fig[ApiField.OBJECT_ID] = key_id_map.get_object_id(
|
|
250
|
+
UUID(fig[OBJECT_KEY])
|
|
251
|
+
)
|
|
252
|
+
except Exception as e:
|
|
253
|
+
logger.debug(
|
|
254
|
+
f"Failed to process figure json for img_hash={img_hash}: {repr(e)}"
|
|
255
|
+
)
|
|
256
|
+
continue
|
|
257
|
+
|
|
258
|
+
figures_to_upload.extend(figs_json)
|
|
259
|
+
|
|
260
|
+
if len(figures_to_upload) > 0:
|
|
261
|
+
try:
|
|
262
|
+
api.image.figure.create_bulk(
|
|
263
|
+
figures_json=figures_to_upload, dataset_id=dataset_id
|
|
264
|
+
)
|
|
265
|
+
except Exception as e:
|
|
266
|
+
logger.debug(f"Failed to upload figures for related images: {repr(e)}")
|
|
267
|
+
|
|
268
|
+
if log_progress:
|
|
269
|
+
progress_cb(len(pcl_to_rimg_figures))
|
|
270
|
+
|
|
271
|
+
except Exception as e:
|
|
272
|
+
logger.debug(f"Unexpected error during figures upload: {repr(e)}")
|
|
168
273
|
|
|
169
274
|
if log_progress:
|
|
170
275
|
if is_development():
|
|
@@ -177,7 +282,7 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
177
282
|
pcd_dict = {}
|
|
178
283
|
frames_pcd_map = None
|
|
179
284
|
used_img_ext = set()
|
|
180
|
-
rimg_dict, rimg_json_dict = {}, {}
|
|
285
|
+
rimg_dict, rimg_json_dict, rimg_fig_dict = {}, {}, {}
|
|
181
286
|
for root, _, files in os.walk(self._input_data):
|
|
182
287
|
for file in files:
|
|
183
288
|
full_path = os.path.join(root, file)
|
|
@@ -187,7 +292,9 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
187
292
|
|
|
188
293
|
ext = get_file_ext(full_path)
|
|
189
294
|
recognized_ext = imghdr.what(full_path)
|
|
190
|
-
if
|
|
295
|
+
if file.endswith(".figures.json"):
|
|
296
|
+
rimg_fig_dict[file] = full_path
|
|
297
|
+
elif ext == ".json":
|
|
191
298
|
rimg_json_dict[file] = full_path
|
|
192
299
|
elif recognized_ext:
|
|
193
300
|
if ext.lower() == ".pcd":
|
|
@@ -226,9 +333,12 @@ class PointcloudEpisodeConverter(BaseConverter):
|
|
|
226
333
|
if rimg_name in rimg_dict:
|
|
227
334
|
rimg_path = rimg_dict[rimg_name]
|
|
228
335
|
rimg_ann_name = f"{rimg_name}.json"
|
|
336
|
+
rimg_fig_name = f"{rimg_name}.figures.json"
|
|
337
|
+
rimg_fig_path = rimg_fig_dict.get(rimg_fig_name)
|
|
338
|
+
|
|
229
339
|
if rimg_ann_name in rimg_json_dict:
|
|
230
340
|
rimg_ann_path = rimg_json_dict[rimg_ann_name]
|
|
231
|
-
item.set_related_images((rimg_path, rimg_ann_path))
|
|
341
|
+
item.set_related_images((rimg_path, rimg_ann_path, rimg_fig_path))
|
|
232
342
|
items.append(item)
|
|
233
343
|
else:
|
|
234
344
|
logger.warning(f"Pointcloud file {pcd_name} not found. Skipping frame.")
|
|
@@ -127,7 +127,11 @@ class SLYPointcloudEpisodesConverter(PointcloudEpisodeConverter):
|
|
|
127
127
|
rimg_ann_name = f"{rimg_name}.json"
|
|
128
128
|
if rimg_ann_name in rimg_json_dict:
|
|
129
129
|
rimg_ann_path = rimg_json_dict[rimg_ann_name]
|
|
130
|
-
|
|
130
|
+
rimg_fig_name = f"{rimg_name}.figures.json"
|
|
131
|
+
rimg_fig_path = os.path.join(os.path.dirname(rimg_ann_path), rimg_fig_name)
|
|
132
|
+
if not os.path.exists(rimg_fig_path):
|
|
133
|
+
rimg_fig_path = None
|
|
134
|
+
item.set_related_images((rimg_path, rimg_ann_path, rimg_fig_path))
|
|
131
135
|
self._items.append(item)
|
|
132
136
|
else:
|
|
133
137
|
logger.warning(f"Pointcloud file {pcd_name} not found. Skipping frame.")
|
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
import os
|
|
7
7
|
import random
|
|
8
8
|
from typing import Callable, Dict, List, NamedTuple, Optional, Tuple, Union
|
|
9
|
+
from uuid import UUID
|
|
9
10
|
|
|
10
11
|
from tqdm import tqdm
|
|
11
12
|
|
|
@@ -17,6 +18,7 @@ from supervisely.api.pointcloud.pointcloud_api import PointcloudInfo
|
|
|
17
18
|
from supervisely.collection.key_indexed_collection import KeyIndexedCollection
|
|
18
19
|
from supervisely.io.fs import dir_exists, get_file_name, list_files, mkdir, touch
|
|
19
20
|
from supervisely.io.json import dump_json_file, load_json_file
|
|
21
|
+
from supervisely.pointcloud_annotation.constants import OBJECT_KEY
|
|
20
22
|
from supervisely.pointcloud_annotation.pointcloud_episode_annotation import (
|
|
21
23
|
PointcloudEpisodeAnnotation,
|
|
22
24
|
)
|
|
@@ -354,6 +356,7 @@ class PointcloudEpisodeProject(PointcloudProject):
|
|
|
354
356
|
def _list_items_for_splits(project) -> List[EpisodeItemInfo]:
|
|
355
357
|
items = []
|
|
356
358
|
for dataset in project.datasets:
|
|
359
|
+
dataset: PointcloudEpisodeDataset
|
|
357
360
|
for item_name in dataset:
|
|
358
361
|
items.append(
|
|
359
362
|
EpisodeItemInfo(
|
|
@@ -745,7 +748,7 @@ def download_pointcloud_episode_project(
|
|
|
745
748
|
datasets_infos = api.dataset.get_list(project_id)
|
|
746
749
|
|
|
747
750
|
for dataset in datasets_infos:
|
|
748
|
-
dataset_fs = project_fs.create_dataset(dataset.name)
|
|
751
|
+
dataset_fs: PointcloudEpisodeDataset = project_fs.create_dataset(dataset.name)
|
|
749
752
|
pointclouds = api.pointcloud_episode.get_list(dataset.id)
|
|
750
753
|
|
|
751
754
|
# Download annotation to project_path/dataset_path/annotation.json
|
|
@@ -774,6 +777,30 @@ def download_pointcloud_episode_project(
|
|
|
774
777
|
pc_to_frame = {v: k for k, v in frame_to_pc_map.items()}
|
|
775
778
|
item_to_ann = {name: pc_to_frame[name] for name in pointcloud_names}
|
|
776
779
|
|
|
780
|
+
batch_rimg_figures = {}
|
|
781
|
+
if download_related_images:
|
|
782
|
+
try:
|
|
783
|
+
rimgs = api.pointcloud_episode.get_list_related_images_batch(
|
|
784
|
+
dataset.id, pointcloud_ids
|
|
785
|
+
)
|
|
786
|
+
if len(rimgs) > 0:
|
|
787
|
+
rimg_ids = [rimg[ApiField.ID] for rimg in rimgs]
|
|
788
|
+
batch_rimg_figures = api.image.figure.download(
|
|
789
|
+
dataset_id=dataset.id, image_ids=rimg_ids
|
|
790
|
+
)
|
|
791
|
+
else:
|
|
792
|
+
batch_rimg_figures = []
|
|
793
|
+
except Exception as e:
|
|
794
|
+
logger.info(
|
|
795
|
+
"INFO FOR DEBUGGING",
|
|
796
|
+
extra={
|
|
797
|
+
"project_id": project_id,
|
|
798
|
+
"dataset_id": dataset.id,
|
|
799
|
+
"pointcloud_ids": pointcloud_ids,
|
|
800
|
+
},
|
|
801
|
+
)
|
|
802
|
+
raise e
|
|
803
|
+
|
|
777
804
|
for pointcloud_id, pointcloud_name, pointcloud_info in zip(
|
|
778
805
|
pointcloud_ids, pointcloud_names, batch
|
|
779
806
|
):
|
|
@@ -830,6 +857,7 @@ def download_pointcloud_episode_project(
|
|
|
830
857
|
|
|
831
858
|
path_img = os.path.join(related_images_path, name)
|
|
832
859
|
path_json = os.path.join(related_images_path, name + ".json")
|
|
860
|
+
path_figures = os.path.join(related_images_path, name + ".figures.json")
|
|
833
861
|
|
|
834
862
|
try:
|
|
835
863
|
api.pointcloud_episode.download_related_image(rimage_id, path_img)
|
|
@@ -846,9 +874,37 @@ def download_pointcloud_episode_project(
|
|
|
846
874
|
},
|
|
847
875
|
)
|
|
848
876
|
raise e
|
|
849
|
-
|
|
850
877
|
dump_json_file(rimage_info, path_json)
|
|
851
878
|
|
|
879
|
+
try:
|
|
880
|
+
if rimage_id in batch_rimg_figures:
|
|
881
|
+
rimg_figures = batch_rimg_figures[rimage_id]
|
|
882
|
+
rimg_figures_json = []
|
|
883
|
+
for fig in rimg_figures:
|
|
884
|
+
fig_json = fig.to_json()
|
|
885
|
+
if ApiField.OBJECT_ID in fig_json:
|
|
886
|
+
fig_json[OBJECT_KEY] = str(
|
|
887
|
+
key_id_map.get_object_key(fig_json[ApiField.OBJECT_ID])
|
|
888
|
+
)
|
|
889
|
+
fig_json.pop(ApiField.OBJECT_ID, None)
|
|
890
|
+
rimg_figures_json.append(fig_json)
|
|
891
|
+
else:
|
|
892
|
+
raise RuntimeError(f"Figure {fig} has no object id")
|
|
893
|
+
dump_json_file(rimg_figures_json, path_figures)
|
|
894
|
+
except Exception as e:
|
|
895
|
+
logger.info(
|
|
896
|
+
"INFO FOR DEBUGGING",
|
|
897
|
+
extra={
|
|
898
|
+
"project_id": project_id,
|
|
899
|
+
"dataset_id": dataset.id,
|
|
900
|
+
"pointcloud_id": pointcloud_id,
|
|
901
|
+
"pointcloud_name": pointcloud_name,
|
|
902
|
+
"rimage_id": rimage_id,
|
|
903
|
+
"path_figures": path_figures,
|
|
904
|
+
},
|
|
905
|
+
)
|
|
906
|
+
raise e
|
|
907
|
+
|
|
852
908
|
pointcloud_info = pointcloud_info._asdict() if download_pointclouds_info else None
|
|
853
909
|
try:
|
|
854
910
|
dataset_fs.add_item_file(
|
|
@@ -901,6 +957,7 @@ def upload_pointcloud_episode_project(
|
|
|
901
957
|
|
|
902
958
|
key_id_map = KeyIdMap()
|
|
903
959
|
for dataset_fs in project_fs.datasets:
|
|
960
|
+
dataset_fs: PointcloudEpisodeDataset
|
|
904
961
|
ann_json_path = dataset_fs.get_ann_path()
|
|
905
962
|
|
|
906
963
|
if os.path.isfile(ann_json_path):
|
|
@@ -974,8 +1031,9 @@ def upload_pointcloud_episode_project(
|
|
|
974
1031
|
|
|
975
1032
|
# STEP 3 — upload photo context
|
|
976
1033
|
img_infos = {"img_paths": [], "img_metas": []}
|
|
977
|
-
|
|
978
1034
|
# STEP 3.1 — upload images
|
|
1035
|
+
pcl_to_rimg_figures: Dict[int, Dict[str, List[Dict]]] = {}
|
|
1036
|
+
pcl_to_hash_to_id: Dict[int, Dict[str, int]] = {}
|
|
979
1037
|
for pcl_info in pcl_infos:
|
|
980
1038
|
related_items = dataset_fs.get_related_images(pcl_info.name)
|
|
981
1039
|
images_paths_for_frame = [img_path for img_path, _ in related_items]
|
|
@@ -1014,6 +1072,7 @@ def upload_pointcloud_episode_project(
|
|
|
1014
1072
|
img_hash = next(images_hashes_iterator)
|
|
1015
1073
|
if "deviceId" not in meta_json[ApiField.META].keys():
|
|
1016
1074
|
meta_json[ApiField.META]["deviceId"] = f"CAM_{str(img_ind).zfill(2)}"
|
|
1075
|
+
|
|
1017
1076
|
img_infos["img_metas"].append(
|
|
1018
1077
|
{
|
|
1019
1078
|
ApiField.ENTITY_ID: pcl_info.id,
|
|
@@ -1022,10 +1081,38 @@ def upload_pointcloud_episode_project(
|
|
|
1022
1081
|
ApiField.META: meta_json[ApiField.META],
|
|
1023
1082
|
}
|
|
1024
1083
|
)
|
|
1084
|
+
img_name = meta_json[ApiField.NAME]
|
|
1085
|
+
related_images_dir = dataset_fs.get_related_images_path(pcl_info.name)
|
|
1086
|
+
fig_json_path = os.path.join(related_images_dir, img_name + ".figures.json")
|
|
1087
|
+
if os.path.isfile(fig_json_path):
|
|
1088
|
+
try:
|
|
1089
|
+
figs_json = load_json_file(fig_json_path)
|
|
1090
|
+
pcl_to_rimg_figures.setdefault(pcl_info.id, {})[img_hash] = figs_json
|
|
1091
|
+
except Exception as e:
|
|
1092
|
+
logger.info(
|
|
1093
|
+
"INFO FOR DEBUGGING",
|
|
1094
|
+
extra={
|
|
1095
|
+
"project_id": project.id,
|
|
1096
|
+
"dataset_id": dataset.id,
|
|
1097
|
+
"pointcloud_id": pcl_info.id,
|
|
1098
|
+
"fig_json_path": fig_json_path,
|
|
1099
|
+
},
|
|
1100
|
+
)
|
|
1101
|
+
raise e
|
|
1025
1102
|
|
|
1026
1103
|
if len(img_infos["img_metas"]) > 0:
|
|
1027
1104
|
try:
|
|
1028
|
-
api.pointcloud_episode.add_related_images(img_infos["img_metas"])
|
|
1105
|
+
uploaded_rimgs = api.pointcloud_episode.add_related_images(img_infos["img_metas"])
|
|
1106
|
+
# build mapping hash->id
|
|
1107
|
+
for info, uploaded in zip(img_infos["img_metas"], uploaded_rimgs):
|
|
1108
|
+
img_hash = info.get(ApiField.HASH)
|
|
1109
|
+
img_id = (
|
|
1110
|
+
uploaded.get(ApiField.ID)
|
|
1111
|
+
if isinstance(uploaded, dict)
|
|
1112
|
+
else getattr(uploaded, "id", None)
|
|
1113
|
+
)
|
|
1114
|
+
if img_hash is not None and img_id is not None:
|
|
1115
|
+
pcl_to_hash_to_id[img_hash] = img_id
|
|
1029
1116
|
except Exception as e:
|
|
1030
1117
|
logger.info(
|
|
1031
1118
|
"INFO FOR DEBUGGING",
|
|
@@ -1037,4 +1124,39 @@ def upload_pointcloud_episode_project(
|
|
|
1037
1124
|
)
|
|
1038
1125
|
raise e
|
|
1039
1126
|
|
|
1127
|
+
for pcl_info in pcl_infos:
|
|
1128
|
+
rimg_figures = pcl_to_rimg_figures.get(pcl_info.id)
|
|
1129
|
+
if not rimg_figures:
|
|
1130
|
+
continue
|
|
1131
|
+
|
|
1132
|
+
try:
|
|
1133
|
+
for img_hash, figs_json in rimg_figures.items():
|
|
1134
|
+
if img_hash in pcl_to_hash_to_id:
|
|
1135
|
+
img_id = pcl_to_hash_to_id[img_hash]
|
|
1136
|
+
for fig in figs_json:
|
|
1137
|
+
fig[ApiField.ENTITY_ID] = img_id
|
|
1138
|
+
fig[ApiField.DATASET_ID] = dataset.id
|
|
1139
|
+
fig[ApiField.PROJECT_ID] = project.id
|
|
1140
|
+
fig[ApiField.OBJECT_ID] = key_id_map.get_object_id(
|
|
1141
|
+
UUID(fig[OBJECT_KEY])
|
|
1142
|
+
)
|
|
1143
|
+
|
|
1144
|
+
api.image.figure.create_bulk(
|
|
1145
|
+
figures_json=[fig for figs in rimg_figures.values() for fig in figs],
|
|
1146
|
+
dataset_id=dataset.id,
|
|
1147
|
+
)
|
|
1148
|
+
|
|
1149
|
+
except Exception as e:
|
|
1150
|
+
logger.info(
|
|
1151
|
+
"INFO FOR DEBUGGING",
|
|
1152
|
+
extra={
|
|
1153
|
+
"project_id": project.id,
|
|
1154
|
+
"dataset_id": dataset.id,
|
|
1155
|
+
"pointcloud_id": pcl_info.id,
|
|
1156
|
+
"pointcloud_name": pcl_info.name,
|
|
1157
|
+
"rimg_figures": rimg_figures,
|
|
1158
|
+
},
|
|
1159
|
+
)
|
|
1160
|
+
raise e
|
|
1161
|
+
|
|
1040
1162
|
return project.id, project.name
|