Skip to content

Commit e551218

Browse files
Vaghinak BasentsyanVaghinak Basentsyan
authored andcommitted
Merge branch 're-design-sdk' of https://github.com/superannotateai/superannotate-python-sdk into re-design-sdk
2 parents d20f1b5 + 09ec2fa commit e551218

File tree

3 files changed

+74
-30
lines changed

3 files changed

+74
-30
lines changed

src/superannotate/lib/app/interface/sdk_interface.py

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -609,9 +609,7 @@ def upload_images_from_public_urls_to_project(
609609

610610
project_name, folder_name = extract_project_folder(project)
611611
existing_images = controller.get_duplicated_images(
612-
project_name=project_name,
613-
folder_name=folder_name,
614-
images=img_names,
612+
project_name=project_name, folder_name=folder_name, images=img_names,
615613
)
616614

617615
image_name_url_map = {}
@@ -1548,6 +1546,28 @@ def upload_images_from_folder_to_project(
15481546
"""
15491547

15501548
project_name, folder_name = extract_project_folder(project)
1549+
if recursive_subfolders:
1550+
logger.info(
1551+
"When using recursive subfolder parsing same name images in different subfolders will overwrite each other."
1552+
)
1553+
1554+
if not isinstance(extensions, (list, tuple)):
1555+
raise AppException(
1556+
"extensions should be a list or a tuple in upload_images_from_folder_to_project"
1557+
)
1558+
1559+
project_folder_name = project_name + (
1560+
f"/{folder_name}" if folder_name != "root" else ""
1561+
)
1562+
1563+
logger.info(
1564+
"Uploading all images with extensions %s from %s to project %s. Excluded file patterns are: %s.",
1565+
extensions,
1566+
folder_path,
1567+
project_folder_name,
1568+
exclude_file_patterns,
1569+
)
1570+
15511571
use_case = controller.upload_images_from_folder_to_project(
15521572
project_name=project_name,
15531573
folder_name=folder_name,
@@ -1559,7 +1579,14 @@ def upload_images_from_folder_to_project(
15591579
recursive_sub_folders=recursive_subfolders,
15601580
image_quality_in_editor=image_quality_in_editor,
15611581
)
1562-
images_to_upload, _ = use_case.images_to_upload
1582+
images_to_upload, duplicates = use_case.images_to_upload
1583+
if len(duplicates):
1584+
logger.warning(
1585+
"%s already existing images found that won't be uploaded.", len(duplicates)
1586+
)
1587+
logger.info(
1588+
"Uploading %s images to project %s.", len(images_to_upload), project_folder_name
1589+
)
15631590
if use_case.is_valid():
15641591
with tqdm(total=len(images_to_upload), desc="Uploading images") as progress_bar:
15651592
for _ in use_case.execute():
@@ -2061,6 +2088,9 @@ def create_annotation_classes_from_classes_json(
20612088
:rtype: list of dicts
20622089
"""
20632090
if not isinstance(classes_json, list):
2091+
logger.info(
2092+
"Creating annotation classes in project %s from %s.", project, classes_json,
2093+
)
20642094
if from_s3_bucket:
20652095
from_session = boto3.Session()
20662096
from_s3 = from_session.resource("s3")
@@ -2073,6 +2103,7 @@ def create_annotation_classes_from_classes_json(
20732103
annotation_classes = json.load(open(classes_json))
20742104
else:
20752105
annotation_classes = classes_json
2106+
20762107
response = controller.create_annotation_classes(
20772108
project_name=project, annotation_classes=annotation_classes,
20782109
)
@@ -2491,9 +2522,26 @@ def upload_annotations_from_folder_to_project(
24912522
"The function does not support projects containing videos attached with URLs"
24922523
)
24932524

2525+
if recursive_subfolders:
2526+
logger.info(
2527+
"When using recursive subfolder parsing same name annotations in different subfolders will overwrite each other.",
2528+
)
2529+
2530+
logger.info(
2531+
"The JSON files should follow specific naming convention. For Vector projects they should be named '<image_name>___objects.json', for Pixel projects JSON file should be names '<image_name>___pixel.json' and also second mask image file should be present with the name '<image_name>___save.png'. In both cases image with <image_name> should be already present on the platform."
2532+
)
2533+
logger.info("Existing annotations will be overwritten.",)
2534+
logger.info(
2535+
"Uploading all annotations from %s to project %s.", folder_path, project_name
2536+
)
2537+
24942538
annotation_paths = get_annotation_paths(
24952539
folder_path, from_s3_bucket, recursive_subfolders
24962540
)
2541+
logger.info(
2542+
"Uploading %s annotations to project %s.", len(annotation_paths), project_name
2543+
)
2544+
24972545
uploaded_annotations = []
24982546
failed_annotations = []
24992547
missing_annotations = []
@@ -2509,8 +2557,6 @@ def upload_annotations_from_folder_to_project(
25092557
annotation_paths=annotation_paths[i : i + chunk_size], # noqa: E203
25102558
client_s3_bucket=from_s3_bucket,
25112559
)
2512-
if response.errors:
2513-
logger.warning(response.errors)
25142560
if response.data:
25152561
uploaded_annotations.extend(response.data[0])
25162562
missing_annotations.extend(response.data[1])

src/superannotate/lib/core/usecases.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,7 +2447,7 @@ def execute(self):
24472447
)
24482448

24492449
if not response.ok:
2450-
self._response.errors = AppException(response.json()['error'])
2450+
self._response.errors = AppException(response.json()["error"])
24512451

24522452
in_progress = response.ok
24532453
if in_progress:
@@ -2727,11 +2727,7 @@ def execute(self):
27272727
unique_annotation_classes.append(annotation_class)
27282728

27292729
created = []
2730-
logger.info(
2731-
"Creating annotation classes in project %s from %s.",
2732-
self._project.name,
2733-
self._annotation_classes,
2734-
)
2730+
27352731
for i in range(0, len(unique_annotation_classes), self.CHUNK_SIZE):
27362732
created += self._service.set_annotation_classes(
27372733
project_id=self._project.uuid,
@@ -3425,9 +3421,10 @@ def execute(self):
34253421
filter(lambda detail: detail.id is not None, images_detail)
34263422
)
34273423
if missing_annotations:
3428-
self._response.errors = AppException(
3429-
f"Couldn't find image {','.join(map(lambda x: x.path, missing_annotations))} for annotation upload."
3430-
)
3424+
for missing in missing_annotations:
3425+
logger.warning(
3426+
f"Couldn't find image {missing.path} for annotation upload."
3427+
)
34313428

34323429
if self._pre_annotation:
34333430
auth_data = self._backend_service.get_pre_annotation_upload_data(
@@ -4544,21 +4541,22 @@ def execute(self) -> Response:
45444541
self._response.errors = "Annotations delete fails."
45454542
break
45464543
else:
4547-
logger.info(f"Annotations deleted")
4544+
logger.info("Annotations deleted")
45484545
break
45494546
else:
45504547
self._response.errors = AppException("Invalid image names or empty folder.")
45514548
return self._response
45524549

45534550

45544551
class GetDuplicateImages(BaseUseCase):
4555-
def __init__(self,
4556-
service: SuerannotateServiceProvider,
4557-
project_id :int,
4558-
team_id: int,
4559-
folder_id: int,
4560-
images: List[str]
4561-
):
4552+
def __init__(
4553+
self,
4554+
service: SuerannotateServiceProvider,
4555+
project_id: int,
4556+
team_id: int,
4557+
folder_id: int,
4558+
images: List[str],
4559+
):
45624560
super().__init__()
45634561
self._service = service
45644562
self._project_id = project_id
@@ -4574,8 +4572,7 @@ def execute(self):
45744572
project_id=self._project_id,
45754573
team_id=self._team_id,
45764574
folder_id=self._folder_id,
4577-
images=self._images[i: i + self._chunk_size],
4575+
images=self._images[i : i + self._chunk_size],
45784576
)
45794577
duplicates += [image["name"] for image in duplications]
45804578
return duplicates
4581-

src/superannotate/lib/infrastructure/controller.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,15 +1472,16 @@ def delete_annotations(
14721472
)
14731473
return use_case.execute()
14741474

1475-
1476-
def get_duplicated_images(self,project_name: str ,folder_name :str ,images: List[str]):
1475+
def get_duplicated_images(
1476+
self, project_name: str, folder_name: str, images: List[str]
1477+
):
14771478
project = self._get_project(project_name)
14781479
folder = self._get_folder(project, folder_name)
14791480
use_case = usecases.GetDuplicateImages(
14801481
service=self._backend_client,
14811482
project_id=project.uuid,
1482-
team_id= project.team_id,
1483-
folder_id= folder.uuid,
1484-
images=images
1483+
team_id=project.team_id,
1484+
folder_id=folder.uuid,
1485+
images=images,
14851486
)
14861487
return use_case.execute()

0 commit comments

Comments
 (0)