supervisely 6.73.232__py3-none-any.whl → 6.73.233__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/api/video/video_api.py +14 -1
- supervisely/nn/inference/cache.py +79 -18
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/METADATA +1 -1
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/RECORD +8 -8
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/LICENSE +0 -0
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/WHEEL +0 -0
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.232.dist-info → supervisely-6.73.233.dist-info}/top_level.txt +0 -0
|
@@ -1372,6 +1372,19 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
1372
1372
|
},
|
|
1373
1373
|
)
|
|
1374
1374
|
|
|
1375
|
+
def notify_tracking_warning(self, track_id: int, video_id: int, message: str):
|
|
1376
|
+
self._api.post(
|
|
1377
|
+
"videos.notify-annotation-tool",
|
|
1378
|
+
data={
|
|
1379
|
+
"type": "videos:tracking-warning",
|
|
1380
|
+
"data": {
|
|
1381
|
+
ApiField.VIDEO_ID: str(video_id),
|
|
1382
|
+
ApiField.TRACK_ID: str(track_id),
|
|
1383
|
+
ApiField.MESSAGE: message,
|
|
1384
|
+
},
|
|
1385
|
+
},
|
|
1386
|
+
)
|
|
1387
|
+
|
|
1375
1388
|
# def upload(self):
|
|
1376
1389
|
# #"/videos.bulk.upload"
|
|
1377
1390
|
# pass
|
|
@@ -2055,7 +2068,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
2055
2068
|
hashes=[h],
|
|
2056
2069
|
metas=[meta],
|
|
2057
2070
|
skip_download=skip_download,
|
|
2058
|
-
force_metadata_for_links=force_metadata_for_links
|
|
2071
|
+
force_metadata_for_links=force_metadata_for_links,
|
|
2059
2072
|
)
|
|
2060
2073
|
if len(links) != 1:
|
|
2061
2074
|
raise RuntimeError(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import os
|
|
3
2
|
import shutil
|
|
4
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
5
4
|
from enum import Enum
|
|
6
5
|
from logging import Logger
|
|
7
6
|
from pathlib import Path
|
|
@@ -16,6 +15,7 @@ from cachetools import Cache, LRUCache, TTLCache
|
|
|
16
15
|
from fastapi import BackgroundTasks, FastAPI, Form, Request, UploadFile
|
|
17
16
|
|
|
18
17
|
import supervisely as sly
|
|
18
|
+
from supervisely._utils import batched
|
|
19
19
|
from supervisely.io.fs import silent_remove
|
|
20
20
|
|
|
21
21
|
|
|
@@ -151,6 +151,38 @@ class PersistentImageTTLCache(TTLCache):
|
|
|
151
151
|
def get_project_meta(self, project_meta_name):
|
|
152
152
|
return self[project_meta_name]
|
|
153
153
|
|
|
154
|
+
def copy_to(self, name, path):
|
|
155
|
+
shutil.copyfile(str(self[name]), path)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class VideoFrameReader:
|
|
159
|
+
def __init__(self, video_path: str, frame_indexes: List[int]):
|
|
160
|
+
self.video_path = video_path
|
|
161
|
+
self.frame_indexes = frame_indexes
|
|
162
|
+
self.cap = None
|
|
163
|
+
self.prev_idx = -1
|
|
164
|
+
|
|
165
|
+
def __enter__(self):
|
|
166
|
+
self.cap = cv2.VideoCapture(str(self.video_path))
|
|
167
|
+
return self
|
|
168
|
+
|
|
169
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
170
|
+
if self.cap is not None:
|
|
171
|
+
self.cap.release()
|
|
172
|
+
|
|
173
|
+
def read_frames(self) -> Generator:
|
|
174
|
+
try:
|
|
175
|
+
for frame_index in self.frame_indexes:
|
|
176
|
+
if frame_index != self.prev_idx + 1:
|
|
177
|
+
self.cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
|
|
178
|
+
ret, frame = self.cap.read()
|
|
179
|
+
if not ret:
|
|
180
|
+
raise KeyError(f"Frame {frame_index} not found in video {self.video_path}")
|
|
181
|
+
yield cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
182
|
+
self.prev_idx = frame_index
|
|
183
|
+
finally:
|
|
184
|
+
self.cap.release()
|
|
185
|
+
|
|
154
186
|
|
|
155
187
|
class InferenceImageCache:
|
|
156
188
|
class _LoadType(Enum):
|
|
@@ -238,25 +270,18 @@ class InferenceImageCache:
|
|
|
238
270
|
return_images,
|
|
239
271
|
)
|
|
240
272
|
|
|
273
|
+
def _read_frames_from_cached_video_iter(self, video_id, frame_indexes):
|
|
274
|
+
video_path = self._cache.get_video_path(video_id)
|
|
275
|
+
with VideoFrameReader(video_path, frame_indexes) as reader:
|
|
276
|
+
for frame in reader.read_frames():
|
|
277
|
+
yield frame
|
|
278
|
+
|
|
241
279
|
def _read_frames_from_cached_video(
|
|
242
280
|
self, video_id: int, frame_indexes: List[int]
|
|
243
281
|
) -> List[np.ndarray]:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
cap = cv2.VideoCapture(str(video_path))
|
|
248
|
-
frames = []
|
|
249
|
-
prev_idx = -1
|
|
250
|
-
for frame_index in frame_indexes:
|
|
251
|
-
if frame_index != prev_idx + 1:
|
|
252
|
-
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
|
|
253
|
-
ret, frame = cap.read()
|
|
254
|
-
if not ret:
|
|
255
|
-
raise KeyError(f"Frame {frame_index} not found in video {video_id}")
|
|
256
|
-
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
|
|
257
|
-
prev_idx = frame_index
|
|
258
|
-
cap.release()
|
|
259
|
-
return frames
|
|
282
|
+
return [
|
|
283
|
+
frame for frame in self._read_frames_from_cached_video_iter(video_id, frame_indexes)
|
|
284
|
+
]
|
|
260
285
|
|
|
261
286
|
def get_frame_from_cache(self, video_id: int, frame_index: int) -> np.ndarray:
|
|
262
287
|
name = self._frame_name(video_id, frame_index)
|
|
@@ -664,3 +689,39 @@ class InferenceImageCache:
|
|
|
664
689
|
# TODO: sleep if slowdown
|
|
665
690
|
sleep(0.1)
|
|
666
691
|
continue
|
|
692
|
+
|
|
693
|
+
def download_frames_to_paths(self, api, video_id, frame_indexes, paths, progress_cb=None):
|
|
694
|
+
def _download_frame(frame_index):
|
|
695
|
+
self.download_frame(api, video_id, frame_index)
|
|
696
|
+
name = self._frame_name(video_id, frame_index)
|
|
697
|
+
return frame_index, name
|
|
698
|
+
|
|
699
|
+
def _download_and_save(this_frame_indexes, this_paths):
|
|
700
|
+
if video_id in self._cache:
|
|
701
|
+
for path, frame in zip(
|
|
702
|
+
this_paths,
|
|
703
|
+
self._read_frames_from_cached_video_iter(video_id, this_frame_indexes),
|
|
704
|
+
):
|
|
705
|
+
sly.image.write(path, frame)
|
|
706
|
+
if progress_cb is not None:
|
|
707
|
+
progress_cb()
|
|
708
|
+
return
|
|
709
|
+
|
|
710
|
+
futures = []
|
|
711
|
+
frame_index_to_path = {}
|
|
712
|
+
for frame_index, path in zip(this_frame_indexes[:5], this_paths[:5]):
|
|
713
|
+
frame_index_to_path[frame_index] = path
|
|
714
|
+
futures.append(executor.submit(_download_frame, frame_index))
|
|
715
|
+
for future in as_completed(futures):
|
|
716
|
+
frame_index, name = future.result()
|
|
717
|
+
path = frame_index_to_path[frame_index]
|
|
718
|
+
self._cache.copy_to(name, path)
|
|
719
|
+
if progress_cb is not None:
|
|
720
|
+
progress_cb()
|
|
721
|
+
if len(this_frame_indexes) > 5:
|
|
722
|
+
_download_and_save(this_frame_indexes[5:], this_paths[5:])
|
|
723
|
+
|
|
724
|
+
# optimization for frame read from video file
|
|
725
|
+
frame_indexes, paths = zip(*sorted(zip(frame_indexes, paths), key=lambda x: x[0]))
|
|
726
|
+
executor = ThreadPoolExecutor(max_workers=5)
|
|
727
|
+
_download_and_save(frame_indexes, paths)
|
|
@@ -64,7 +64,7 @@ supervisely/api/pointcloud/pointcloud_object_api.py,sha256=bO1USWb9HAywG_CW4CDu1
|
|
|
64
64
|
supervisely/api/pointcloud/pointcloud_tag_api.py,sha256=iShtr052nOElxsyMyZEUT2vypEm6kP00gnP13ABX24A,4691
|
|
65
65
|
supervisely/api/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
66
|
supervisely/api/video/video_annotation_api.py,sha256=Um_7UOJtP_E25X6v41mrZfDbJaJuLMGoZm2IULwyg3w,10977
|
|
67
|
-
supervisely/api/video/video_api.py,sha256=
|
|
67
|
+
supervisely/api/video/video_api.py,sha256=KO_Nfqa4xDWrc7FqOR14PciC0TX8PF0g0peqgPnctEE,94677
|
|
68
68
|
supervisely/api/video/video_figure_api.py,sha256=quksohjhgrK2l2-PtbbNE99fOW6uWXX59-_4xfc-I-k,6244
|
|
69
69
|
supervisely/api/video/video_frame_api.py,sha256=4GwSI4xdCNYEUvTqzKc-Ewd44fw5zqkFoD24jrrN_aY,10214
|
|
70
70
|
supervisely/api/video/video_object_api.py,sha256=IC0NP8EoIT_d3xxDRgz2cA3ixSiuJ5ymy64eS-RfmDM,2227
|
|
@@ -816,7 +816,7 @@ supervisely/nn/benchmark/visualization/widgets/sidebar/sidebar.py,sha256=tKPURRS
|
|
|
816
816
|
supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
817
817
|
supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=YiCpt-mdINJnNBWsUTPkRR_9w09Ne2Y0n93DY8vsE8I,4090
|
|
818
818
|
supervisely/nn/inference/__init__.py,sha256=mtEci4Puu-fRXDnGn8RP47o97rv3VTE0hjbYO34Zwqg,1622
|
|
819
|
-
supervisely/nn/inference/cache.py,sha256=
|
|
819
|
+
supervisely/nn/inference/cache.py,sha256=KvzCgMbEBLdiJAxJDLicIPKAlYb52P9_kpNPWfiVY8Y,28194
|
|
820
820
|
supervisely/nn/inference/inference.py,sha256=CmQe6QnhZuUV128jcIp2YKsgeggAtmc1NL7PdFnc_hw,116997
|
|
821
821
|
supervisely/nn/inference/session.py,sha256=jmkkxbe2kH-lEgUU6Afh62jP68dxfhF5v6OGDfLU62E,35757
|
|
822
822
|
supervisely/nn/inference/video_inference.py,sha256=8Bshjr6rDyLay5Za8IB8Dr6FURMO2R_v7aELasO8pR4,5746
|
|
@@ -997,9 +997,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
997
997
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
998
998
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
999
999
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1000
|
-
supervisely-6.73.
|
|
1001
|
-
supervisely-6.73.
|
|
1002
|
-
supervisely-6.73.
|
|
1003
|
-
supervisely-6.73.
|
|
1004
|
-
supervisely-6.73.
|
|
1005
|
-
supervisely-6.73.
|
|
1000
|
+
supervisely-6.73.233.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1001
|
+
supervisely-6.73.233.dist-info/METADATA,sha256=MJtm60rKHXwewU1uAmNhtaWHuI_g_Y4oGxJbqM-oiFM,33150
|
|
1002
|
+
supervisely-6.73.233.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
1003
|
+
supervisely-6.73.233.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1004
|
+
supervisely-6.73.233.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1005
|
+
supervisely-6.73.233.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|