Skip to content

Commit 6c7fea0

Browse files
committed
- 更新文档
- 添加api参考 - 修复bug
1 parent c221d21 commit 6c7fea0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+4318
-365
lines changed

ISAT/annotation.py

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@
55
from PIL import Image
66
import numpy as np
77
from json import load, dump
8-
from typing import List
8+
from typing import List, Union
99

10+
__all__ = ['Object', 'Annotation']
1011

1112
class Object:
12-
"""
13-
A class to represent an annotation object.
13+
r"""A class to represent an annotation object.
1414
15-
category: The category of the object.
16-
group: The group of the object.
17-
segmentation: The vertices of the object.
18-
area: The area of the object.
19-
layer: The layer of the object.
20-
bbox: The bbox of the object.
21-
iscrowd: The crowd tag of the object.
22-
note: The note of the object.
15+
Arguments:
16+
category (str): The category of the object.
17+
group (int): The group of the object.
18+
segmentation (list | tuple): The vertices of the object.[(x1, y1), (x2, y2), ...]
19+
area (float): The area of the object.
20+
layer (int): The layer of the object.
21+
bbox (list | tuple): The bbox of the object. [xmin, ymin, xmax, ymax]
22+
iscrowd (bool): The crowd tag of the object.
23+
note (str): The note of the object.
2324
"""
24-
def __init__(self, category:str, group:int, segmentation, area, layer, bbox, iscrowd=0, note=''):
25+
def __init__(self, category: str, group: int, segmentation: Union[list, tuple], area: float, layer: int, bbox: Union[list, tuple], iscrowd: bool=False, note: str=''):
2526
self.category = category
2627
self.group = group
2728
self.segmentation = segmentation
@@ -33,7 +34,23 @@ def __init__(self, category:str, group:int, segmentation, area, layer, bbox, isc
3334

3435

3536
class Annotation:
36-
def __init__(self, image_path, label_path):
37+
r"""A class to represent an annotation containing many objects.
38+
39+
Arguments:
40+
image_path (str): The path to the image.
41+
label_path (str): The path to the label file.
42+
43+
Attributes:
44+
description (str): Always 'ISAT'.
45+
img_folder (str): The path to the folder where the images are located.
46+
img_name (str): The name of the image.
47+
label_path (str): The path to the label file.
48+
note (str): The note of the image.
49+
height (int): The height of the image.
50+
width (int): The width of the image.
51+
depth (int): The depth of the image.
52+
"""
53+
def __init__(self, image_path:str, label_path:str):
3754
img_folder, img_name = os.path.split(image_path)
3855
self.description = 'ISAT'
3956
self.img_folder = img_folder
@@ -52,9 +69,12 @@ def __init__(self, image_path, label_path):
5269
print('Warning: Except image has 2 or 3 ndim, but get {}.'.format(image.ndim))
5370
del image
5471

55-
self.objects:List[Object,...] = []
72+
self.objects:List[Object, ] = []
5673

5774
def load_annotation(self):
75+
r"""
76+
Load annotation from self.label_path
77+
"""
5878
if os.path.exists(self.label_path):
5979
with open(self.label_path, 'r', encoding='utf-8') as f:
6080
dataset = load(f)
@@ -79,7 +99,8 @@ def load_annotation(self):
7999
group = obj.get('group', 0)
80100
if group is None: group = 0
81101
segmentation = obj.get('segmentation', [])
82-
iscrowd = obj.get('iscrowd', 0)
102+
iscrowd = obj.get('iscrowd', False)
103+
iscrowd = iscrowd if isinstance(iscrowd, bool) else bool(iscrowd)
83104
note = obj.get('note', '')
84105
area = obj.get('area', 0)
85106
layer = obj.get('layer', 2)
@@ -92,6 +113,9 @@ def load_annotation(self):
92113
return self
93114

94115
def save_annotation(self):
116+
r"""
117+
Save annotation to self.label_path
118+
"""
95119
dataset = {}
96120
dataset['info'] = {}
97121
dataset['info']['description'] = self.description

ISAT/configs.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
from enum import Enum
33
import os
44

5+
__all__ = ['load_config', 'save_config', 'STATUSMode', 'DRAWMode', 'MAPMode', 'CONTOURMode']
6+
57
ISAT_ROOT = os.path.split(os.path.abspath(__file__))[0]
8+
"""Project root - ISAT/"""
69
SOFTWARE_CONFIG_FILE = os.path.join(ISAT_ROOT, 'software.yaml')
10+
"""Software config file - ISAT/software.yaml"""
711
CONFIG_FILE = os.path.join(ISAT_ROOT, 'isat.yaml')
12+
"""Category config file - ISAT/isat.yaml"""
813
CHECKPOINT_PATH = os.path.join(ISAT_ROOT, 'checkpoints')
9-
SHORTCUT_FILE = os.path.join(ISAT_ROOT, 'shortcut.yaml')
14+
"""Checkpoints save root - ISAT/checkpoints"""
1015

1116
os.makedirs(os.path.join(CHECKPOINT_PATH, 'tmp'), exist_ok=True)
1217

@@ -18,42 +23,62 @@
1823
with open(CONFIG_FILE, 'w') as f:
1924
pass
2025

21-
def load_config(file):
26+
def load_config(file: str) -> dict:
27+
r"""
28+
Load config file
29+
30+
Arguments:
31+
file (str): config file path
32+
33+
Returns:
34+
dict: config dict
35+
"""
2236
with open(file, 'rb')as f:
2337
cfg = yaml.load(f.read(), Loader=yaml.FullLoader)
2438
return cfg
2539

26-
def save_config(cfg, file):
40+
def save_config(cfg: dict, file: str) -> None:
41+
"""
42+
Save config file
43+
44+
Arguments:
45+
cfg (dict): config dict
46+
file (str): config file path
47+
"""
2748
s = yaml.dump(cfg, allow_unicode=True)
2849
with open(file, 'w', encoding='utf-8') as f:
2950
f.write(s)
30-
return True
3151

3252
class STATUSMode(Enum):
53+
"""The status mode"""
3354
VIEW = 0
3455
CREATE = 1
3556
EDIT = 2
3657
REPAINT = 3
3758

3859
class DRAWMode(Enum):
60+
"""The draw mode."""
3961
POLYGON = 0
62+
"""Manually draw polygon"""
4063
SEGMENTANYTHING = 1
64+
"""Segment anything with point prompt."""
4165
SEGMENTANYTHING_BOX = 2
42-
43-
class CLICKMode(Enum):
44-
POSITIVE = 0
45-
NEGATIVE = 1
66+
"""Segment anything with box prompt."""
4667

4768
class MAPMode(Enum):
69+
"""Canvas show map mode"""
4870
LABEL = 0
4971
SEMANTIC = 1
5072
INSTANCE = 2
5173

5274
class CONTOURMode(Enum):
53-
SAVE_MAX_ONLY = 0 # 只保留最多顶点的mask(一般为最大面积)
54-
SAVE_EXTERNAL = 1 # 只保留外轮廓
55-
SAVE_ALL = 2 # 保留所有轮廓
56-
75+
"""
76+
Contour Mode - ways to convert masks to polygons.
77+
"""
78+
SAVE_MAX_ONLY = 0
79+
"""Only save max contour."""
80+
SAVE_EXTERNAL = 1
81+
"""Only save external contour."""
82+
SAVE_ALL = 2
83+
"""Only save all contour."""
5784

58-
if __name__ == '__main__':
59-
cfg = load_config('/mnt/disk2/PycharmProjects/ISAT_with_segment_anything/ISAT/isat.yaml')

ISAT/formats/coco.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,25 @@
99
import tqdm
1010
import numpy as np
1111

12+
__all__ = ['COCO']
1213

1314
class COCO(ISAT):
15+
r"""
16+
COCO format
17+
18+
Attributes:
19+
keep_crowd (bool): keep the crowded objects
20+
"""
1421
def __init__(self):
1522
self.keep_crowd = True
1623

17-
def read_from_coco(self, annotation_file):
24+
def read_from_coco(self, annotation_file: str) -> bool:
25+
r"""
26+
Load annotations from a COCO json file.
27+
28+
Arguments:
29+
annotation_file (str): coco json annotations file.
30+
"""
1831
self.annos.clear()
1932
self.cates = ()
2033

@@ -48,13 +61,13 @@ def read_from_coco(self, annotation_file):
4861

4962
segmentations = anno_coco.get('segmentation', []) # 多个polygon
5063
area = anno_coco.get('area', None) # coco中,area是组面积,isat中是单个polygon面积
51-
iscrowd = anno_coco.get('iscrowd', None)
64+
iscrowd = anno_coco.get('iscrowd', False)
5265
image_id = anno_coco.get('image_id', None)
5366
bbox = anno_coco.get('bbox', [])
5467
category_id = anno_coco.get('category_id', None)
5568
id = anno_coco.get('id', None)
5669

57-
if iscrowd == 0:
70+
if iscrowd is False:
5871
# polygon
5972
for segmentation in segmentations:
6073
xs = segmentation[::2]
@@ -73,7 +86,7 @@ def read_from_coco(self, annotation_file):
7386

7487
objs.append(obj)
7588

76-
elif iscrowd == 1 and self.keep_crowd:
89+
elif iscrowd is True and self.keep_crowd:
7790
if isinstance(segmentations, dict) and 'counts' in segmentations:
7891
# RLE
7992
rles = mscoco_mask.frPyObjects(segmentations, height, width)
@@ -121,8 +134,14 @@ def read_from_coco(self, annotation_file):
121134
self.annos[self.remove_file_suffix(file_name)] = anno
122135
return True
123136

124-
def save_to_coco(self, annotation_file, cates: tuple=()):
137+
def save_to_coco(self, annotation_file: str, cates: tuple=()) -> bool:
138+
r"""
139+
Save annotations to a COCO json file.
125140
141+
Arguments:
142+
annotation_file (str): coco json annotations file.
143+
cates (tuple): coco cates.
144+
"""
126145
coco_anno = {}
127146
# info
128147
coco_anno['info'] = {}

0 commit comments

Comments
 (0)