Skip to content

Commit 49320f5

Browse files
Vaghinak BasentsyanVaghinak Basentsyan
authored andcommitted
Added cli version command
Add consensus benchmark
1 parent 18b2ec5 commit 49320f5

27 files changed

+352
-128
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,5 @@ _mask.c
143143
tags
144144
temp
145145
debug_*
146-
*.idea
146+
*.idea
147+
*.DS_Store

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
minversion = 3.0
33
log_cli=true
44
python_files = test_*.py
5-
;addopts = -n24 --dist=loadscope
5+
addopts = -n32 --dist=loadscope

sonar-project.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ sonar.python.version=3.8
88
#sonar.sources=.
99
# Encoding of the source code. Default is default system encoding
1010
#sonar.sourceEncoding=UTF-8
11+
sonar.python.coverage.reportPaths = ./coverage.xml
12+

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

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,15 +2565,30 @@ def benchmark(
25652565
project_name = project
25662566
if isinstance(project, dict):
25672567
project_name = project["name"]
2568-
response = controller.benchmark(
2569-
project_name=project_name,
2570-
ground_truth_folder_name=gt_folder,
2571-
folder_names=folder_names,
2572-
export_root=export_root,
2573-
image_list=image_list,
2574-
annot_type=annot_type,
2575-
show_plots=show_plots,
2576-
)
2568+
2569+
if export_root is None:
2570+
with tempfile.TemporaryDirectory() as temp_dir:
2571+
export_root = temp_dir
2572+
response = controller.benchmark(
2573+
project_name=project_name,
2574+
ground_truth_folder_name=gt_folder,
2575+
folder_names=folder_names,
2576+
export_root=export_root,
2577+
image_list=image_list,
2578+
annot_type=annot_type,
2579+
show_plots=show_plots,
2580+
)
2581+
2582+
else:
2583+
response = controller.benchmark(
2584+
project_name=project_name,
2585+
ground_truth_folder_name=gt_folder,
2586+
folder_names=folder_names,
2587+
export_root=export_root,
2588+
image_list=image_list,
2589+
annot_type=annot_type,
2590+
show_plots=show_plots,
2591+
)
25772592
return response.data
25782593

25792594

@@ -2603,14 +2618,28 @@ def consensus(
26032618
:return: Pandas DateFrame with columns (creatorEmail, QA, imageName, instanceId, className, area, attribute, folderName, score)
26042619
:rtype: pandas DataFrame
26052620
"""
2606-
response = controller.consensus(
2607-
project_name=project,
2608-
folder_names=folder_names,
2609-
export_root=export_root,
2610-
image_list=image_list,
2611-
annot_type=annot_type,
2612-
show_plots=show_plots,
2613-
)
2621+
2622+
if export_root is None:
2623+
with tempfile.TemporaryDirectory() as temp_dir:
2624+
export_root = temp_dir
2625+
response = controller.consensus(
2626+
project_name=project,
2627+
folder_names=folder_names,
2628+
export_path=export_root,
2629+
image_list=image_list,
2630+
annot_type=annot_type,
2631+
show_plots=show_plots,
2632+
)
2633+
2634+
else:
2635+
response = controller.consensus(
2636+
project_name=project,
2637+
folder_names=folder_names,
2638+
export_path=export_root,
2639+
image_list=image_list,
2640+
annot_type=annot_type,
2641+
show_plots=show_plots,
2642+
)
26142643
return response.data
26152644

26162645

src/superannotate/lib/core/usecases.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,6 +3627,9 @@ def attribute_to_list(attribute_df):
36273627
if self._show_plots:
36283628
consensus_plot(consensus_df, self._folder_names)
36293629

3630+
self._response.data = consensus_df
3631+
return self._response
3632+
36303633

36313634
class RunSegmentationUseCase(BaseUseCase):
36323635
def __init__(

src/superannotate/lib/infrastructure/controller.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import copy
22
import io
3-
import tempfile
43
from functools import cached_property
54
from typing import Iterable
65
from typing import List
@@ -1224,20 +1223,25 @@ def benchmark(
12241223
show_plots: bool,
12251224
):
12261225
project = self._get_project(project_name)
1227-
if export_root is None:
1228-
with tempfile.TemporaryDirectory() as export_dir:
1229-
# TODO fix prepare_export & download_export calls
1230-
export = self.prepare_export(project.name)
1231-
self.download_export(
1232-
project_name=project.name,
1233-
export_name=export["name"],
1234-
folder_path=export_dir,
1235-
)
1226+
export_response = self.prepare_export(
1227+
project.name,
1228+
folder_names=folder_names,
1229+
include_fuse=False,
1230+
only_pinned=False,
1231+
)
1232+
self.download_export(
1233+
project_name=project.name,
1234+
export_name=export_response.data["name"],
1235+
folder_path=export_root,
1236+
extract_zip_contents=True,
1237+
to_s3_bucket=False,
1238+
)
1239+
12361240
use_case = usecases.BenchmarkUseCase(
12371241
project=project,
12381242
ground_truth_folder_name=ground_truth_folder_name,
12391243
folder_names=folder_names,
1240-
export_dir=export_dir,
1244+
export_dir=export_root,
12411245
image_list=image_list,
12421246
annotation_type=annot_type,
12431247
show_plots=show_plots,
@@ -1248,24 +1252,30 @@ def consensus(
12481252
self,
12491253
project_name: str,
12501254
folder_names: list,
1251-
export_root: str,
1255+
export_path: str,
12521256
image_list: list,
12531257
annot_type: str,
12541258
show_plots: bool,
12551259
):
12561260
project = self._get_project(project_name)
1257-
if export_root is None:
1258-
with tempfile.TemporaryDirectory() as export_dir:
1259-
export = self.prepare_export(project.name)
1260-
self.download_export(
1261-
project_name=project.name,
1262-
export_name=export["name"],
1263-
folder_path=export_dir,
1264-
)
1261+
1262+
export_response = self.prepare_export(
1263+
project.name,
1264+
folder_names=folder_names,
1265+
include_fuse=False,
1266+
only_pinned=False,
1267+
)
1268+
self.download_export(
1269+
project_name=project.name,
1270+
export_name=export_response.data["name"],
1271+
folder_path=export_path,
1272+
extract_zip_contents=True,
1273+
to_s3_bucket=False,
1274+
)
12651275
use_case = usecases.ConsensusUseCase(
12661276
project=project,
12671277
folder_names=folder_names,
1268-
export_dir=export_dir,
1278+
export_dir=export_path,
12691279
image_list=image_list,
12701280
annotation_type=annot_type,
12711281
show_plots=show_plots,

tests/convertors/test_consensus.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import os
2+
import time
3+
from os.path import dirname
4+
5+
import src.superannotate as sa
6+
from tests.integration.base import BaseTestCase
7+
8+
9+
class TestConsensus(BaseTestCase):
10+
PROJECT_NAME = "consensus"
11+
PROJECT_DESCRIPTION = "Desc"
12+
PROJECT_TYPE = "Vector"
13+
NEW_PROJECT_NAME = "new"
14+
TEST_FOLDER_PTH = "data_set"
15+
TEST_FOLDER_PATH = "data_set/sample_project_vector"
16+
MODEL_NAME = "Instance segmentation (trained on COCO)"
17+
TEST_EXPORT_ROOT = "data_set/consensus_benchmark/consensus_test_data"
18+
CONSENSUS_PREFIX = "consensus_"
19+
20+
@property
21+
def folder_path(self):
22+
return os.path.join(dirname(dirname(__file__)), self.TEST_FOLDER_PATH)
23+
24+
@property
25+
def export_path(self):
26+
return os.path.join(dirname(dirname(__file__)), self.TEST_EXPORT_ROOT)
27+
28+
def test_consensus(self):
29+
annot_types = ['polygon', 'bbox', 'point']
30+
folder_names = ['consensus_1', 'consensus_2', 'consensus_3']
31+
df_column_names = [
32+
'creatorEmail', 'imageName', 'instanceId', 'area', 'className',
33+
'attributes', 'folderName', 'score'
34+
]
35+
export_path = self.export_path
36+
for i in range(1, 4):
37+
sa.create_folder(self.PROJECT_NAME, "consensus_" + str(i))
38+
sa.create_annotation_classes_from_classes_json(
39+
self.PROJECT_NAME, self.export_path + "/classes/classes.json"
40+
)
41+
sa.upload_images_from_folder_to_project(
42+
self.PROJECT_NAME, self.export_path + "/images", annotation_status="Completed"
43+
)
44+
for i in range(1, 4):
45+
sa.upload_images_from_folder_to_project(
46+
self.PROJECT_NAME + f'/{self.CONSENSUS_PREFIX}' + str(i),
47+
self.export_path + "/images",
48+
annotation_status="Completed"
49+
)
50+
time.sleep(2)
51+
sa.upload_annotations_from_folder_to_project(self.PROJECT_NAME, self.export_path)
52+
for i in range(1, 4):
53+
sa.upload_annotations_from_folder_to_project(
54+
self.PROJECT_NAME + f'/{self.CONSENSUS_PREFIX}' + str(i),
55+
self.export_path + f'/{self.CONSENSUS_PREFIX}' + str(i)
56+
)
57+
58+
for annot_type in annot_types:
59+
res_df = sa.consensus(self.PROJECT_NAME, folder_names, annot_type=annot_type)
60+
#test content of projectName column
61+
assert sorted(res_df['folderName'].unique()) == folder_names
62+
63+
#test structure of resulting DataFrame
64+
assert sorted(res_df.columns) == sorted(df_column_names)
65+
66+
#test lower bound of the score
67+
assert (res_df['score'] >= 0).all()
68+
69+
#test upper bound of the score
70+
assert (res_df['score'] <= 1).all()
71+
72+
image_names = [
73+
'bonn_000000_000019_leftImg8bit.png',
74+
'bielefeld_000000_000321_leftImg8bit.png'
75+
]
76+
77+
#test filtering images with given image names list
78+
res_images = sa.consensus(
79+
self.PROJECT_NAME,
80+
folder_names,
81+
export_root=export_path,
82+
image_list=image_names
83+
)
84+
85+
assert sorted(res_images['imageName'].unique()) == sorted(image_names)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[{"id":466281,"project_id":61619,"name":"person","color":"#96963a","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z","attribute_groups":[]},{"id":466282,"project_id":61619,"name":"car","color":"#b01cb4","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z","attribute_groups":[{"id":219243,"class_id":466282,"name":"color","is_multiselect":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z","attributes":[{"id":853751,"group_id":219243,"project_id":61619,"name":"red","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z"},{"id":853752,"group_id":219243,"project_id":61619,"name":"blue","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z"},{"id":853753,"group_id":219243,"project_id":61619,"name":"green","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z"},{"id":853754,"group_id":219243,"project_id":61619,"name":"yellow","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z"}]}]},{"id":466283,"project_id":61619,"name":"sign","color":"#fed339","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z","attribute_groups":[]},{"id":466284,"project_id":61619,"name":"tree","color":"#249e9e","count":0,"createdAt":"2021-03-09T10:46:38.000Z","updatedAt":"2021-03-09T10:46:38.000Z","attribute_groups":[]}]
1+
[{"id":772150,"project_id":106166,"name":"person","color":"#96963a","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z","attribute_groups":[]},{"id":772151,"project_id":106166,"name":"car","color":"#b01cb4","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z","attribute_groups":[{"id":296037,"class_id":772151,"name":"color","is_multiselect":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z","attributes":[{"id":1074666,"group_id":296037,"project_id":106166,"name":"red","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z"},{"id":1074667,"group_id":296037,"project_id":106166,"name":"blue","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z"},{"id":1074668,"group_id":296037,"project_id":106166,"name":"green","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z"},{"id":1074669,"group_id":296037,"project_id":106166,"name":"yellow","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z"}]}]},{"id":772152,"project_id":106166,"name":"sign","color":"#fed339","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z","attribute_groups":[]},{"id":772153,"project_id":106166,"name":"tree","color":"#249e9e","count":0,"createdAt":"2021-08-25T05:53:40.000Z","updatedAt":"2021-08-25T05:53:40.000Z","attribute_groups":[]}]

0 commit comments

Comments
 (0)