Skip to content

Commit 8f54fdf

Browse files
committed
fix video convertor
1 parent 6f14758 commit 8f54fdf

File tree

10 files changed

+521
-287
lines changed

10 files changed

+521
-287
lines changed

requirements_dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
superannotate_schemas>=v1.0.43dev3
1+
superannotate_schemas>=v1.0.43dev4
22

src/superannotate/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@
211211

212212
__author__ = "Superannotate"
213213

214-
WORKING_DIR = os.path.split(os.path.realpath(__file__))[0]
215-
sys.path.append(WORKING_DIR)
214+
sys.path.append(os.path.split(os.path.realpath(__file__))[0])
216215
logging.getLogger("botocore").setLevel(logging.CRITICAL)
217216
logger = get_default_logger()
218217

src/superannotate/lib/core/usecases/images.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ def execute(self) -> Response:
16201620
polling_states[response.get("poll_id")] = False
16211621

16221622
if not polling_states:
1623-
self._response.errors = AppException("Invalid image names or empty folder.")
1623+
self._response.errors = AppException("Invalid item names or empty folder.")
16241624
else:
16251625
for poll_id in polling_states:
16261626
timeout_start = time.time()

src/superannotate/lib/core/usecases/models.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,16 @@ def upload_to_s3_from_folder(self, source: str, folder_path: str):
202202

203203
def _upload_file_to_s3(_to_s3_bucket, _path, _s3_key) -> None:
204204
_to_s3_bucket.upload_file(str(_path), _s3_key)
205-
self.reporter.update_progress()
206205

207206
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
208207
results = []
209-
self.reporter.start_progress(len(files_to_upload), "Uploading")
208+
self.reporter.start_spinner()
210209
for path in files_to_upload:
211210
s3_key = f"{folder_path + '/' if folder_path else ''}{str(Path(path).relative_to(Path(source)))}"
212211
results.append(
213212
executor.submit(_upload_file_to_s3, to_s3_bucket, path, s3_key)
214213
)
215-
self.reporter.finish_progress()
214+
self.reporter.stop_spinner()
216215

217216
def download_to_local_storage(self, destination: str, extract_zip=False):
218217
exports = self._service.get_exports(
@@ -227,22 +226,22 @@ def download_to_local_storage(self, destination: str, extract_zip=False):
227226
if not export:
228227
raise AppException("Export not found.")
229228
export_status = export["status"]
230-
231-
while export_status != ExportStatus.COMPLETE.value:
232-
logger.info("Waiting 5 seconds for export to finish on server.")
233-
time.sleep(5)
234-
235-
export = self._service.get_export(
236-
team_id=self._project.team_id,
237-
project_id=self._project.id,
238-
export_id=export["id"],
239-
)
240-
if "error" in export:
241-
raise AppException(export["error"])
242-
export_status = export["status"]
243-
if export_status in (ExportStatus.ERROR.value, ExportStatus.CANCELED.value):
244-
raise AppException("Couldn't download export.")
245-
229+
if export_status != ExportStatus.COMPLETE.value:
230+
logger.info("Waiting for export to finish on server.")
231+
self.reporter.start_spinner()
232+
while export_status != ExportStatus.COMPLETE.value:
233+
export = self._service.get_export(
234+
team_id=self._project.team_id,
235+
project_id=self._project.id,
236+
export_id=export["id"],
237+
)
238+
if "error" in export:
239+
raise AppException(export["error"])
240+
export_status = export["status"]
241+
if export_status in (ExportStatus.ERROR.value, ExportStatus.CANCELED.value):
242+
self.reporter.stop_spinner()
243+
raise AppException("Couldn't download export.")
244+
self.reporter.stop_spinner()
246245
filename = Path(export["path"]).name
247246
filepath = Path(destination) / filename
248247
with requests.get(export["download"], stream=True) as response:

src/superannotate/lib/core/video_convertor.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __init__(self, annotation_data: dict, fps: int):
3636
self.fps = fps
3737
self.ratio = 1000 * 1000 / fps
3838
self._frame_id = 1
39-
self.frames_count = int(self.duration * fps)
39+
self.frames_count = int(math.ceil(self.duration * fps))
4040
self.annotations: dict = {}
4141
self._mapping = {}
4242
self._process()
@@ -107,7 +107,7 @@ def get_median(self, annotations: List[dict]) -> dict:
107107
if len(annotations) == 1:
108108
return annotations[0]
109109
first_annotations = annotations[:1][0]
110-
median = (first_annotations["timestamp"] // self.ratio) + (self.ratio / 2)
110+
median = (first_annotations["timestamp"] // self.ratio) * self.ratio + self.ratio / 2
111111
median_annotation = first_annotations
112112
distance = abs(median - first_annotations["timestamp"])
113113
for annotation in annotations[1:]:
@@ -163,8 +163,6 @@ def _process(self):
163163
class_name = instance["meta"].get("className")
164164
for parameter in instance["parameters"]:
165165
frames_mapping = defaultdict(list)
166-
last_frame_no = None
167-
last_annotation = None
168166
interpolated_frames = {}
169167
for timestamp in parameter["timestamps"]:
170168
frames_mapping[
@@ -190,33 +188,35 @@ def _process(self):
190188
instance_id=instance_id
191189
)
192190
)
191+
193192
start_median_frame = self.get_median(frames_mapping[from_frame_no])
194193
end_median_frame = self.get_median(frames_mapping[to_frame_no])
195-
interpolated_frames[from_frame_no] = Annotation(
196-
instanceId=instance_id,
197-
type=annotation_type,
198-
className=class_name,
199-
x=start_median_frame.get("x"),
200-
y=start_median_frame.get("y"),
201-
points=start_median_frame.get("points"),
202-
attributes=start_median_frame["attributes"],
203-
keyframe=True,
204-
)
205-
last_annotation = Annotation(
194+
for frame_no, frame in (from_frame_no, start_median_frame), (last_frame_no, end_median_frame):
195+
interpolated_frames[frame_no] = Annotation(
196+
instanceId=instance_id,
197+
type=annotation_type,
198+
className=class_name,
199+
x=frame.get("x"),
200+
y=frame.get("y"),
201+
points=frame.get("points"),
202+
attributes=frame["attributes"],
203+
keyframe=True,
204+
)
205+
if frames_mapping and not interpolated_frames:
206+
median = self.get_median(frames_mapping[1])
207+
interpolated_frames[1] = Annotation(
206208
instanceId=instance_id,
207209
type=annotation_type,
208210
className=class_name,
209-
x=start_median_frame.get("x"),
210-
y=start_median_frame.get("y"),
211-
points=end_median_frame.get("points"),
212-
attributes=end_median_frame["attributes"],
211+
x=median.get("x"),
212+
y=median.get("y"),
213+
points=median.get("points"),
214+
attributes=median["attributes"],
213215
keyframe=True,
214216
)
215-
self._add_annotation(last_frame_no, last_annotation)
216-
[
217+
218+
for frame_no, annotation in interpolated_frames.items():
217219
self._add_annotation(frame_no, annotation)
218-
for frame_no, annotation in interpolated_frames.items()
219-
]
220220

221221
def __iter__(self):
222222
for frame_no in range(1, int(self.frames_count) + 1):

src/superannotate/lib/infrastructure/controller.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ def benchmark(
11741174
if export_response.errors:
11751175
return export_response
11761176

1177-
usecases.DownloadExportUseCase(
1177+
response = usecases.DownloadExportUseCase(
11781178
service=self._backend_client,
11791179
project=project,
11801180
export_name=export_response.data["name"],
@@ -1183,7 +1183,8 @@ def benchmark(
11831183
to_s3_bucket=False,
11841184
reporter=self.default_reporter,
11851185
).execute()
1186-
1186+
if response.errors:
1187+
raise AppException(response.errors)
11871188
use_case = usecases.BenchmarkUseCase(
11881189
project=project,
11891190
ground_truth_folder_name=ground_truth_folder_name,

src/superannotate/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "4.3.5dev2"
1+
__version__ = "4.3.4dev2"

tests/integration/annotations/test_get_annotations_per_frame.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import math
23
import os
34
from os.path import dirname
45
from pathlib import Path
@@ -47,8 +48,10 @@ def test_video_annotation_upload(self):
4748
self.assertEqual(
4849
len(annotations),
4950
int(
50-
json.load(
51-
open(f"{self.annotations_path}/{self.VIDEO_NAME}.json"))["metadata"]["duration"] / (
52-
1000 * 1000)
51+
math.ceil(
52+
json.load(
53+
open(f"{self.annotations_path}/{self.VIDEO_NAME}.json"))["metadata"]["duration"] / (
54+
1000 * 1000)
55+
)
5356
)
5457
)

0 commit comments

Comments
 (0)