Skip to content

Commit efca771

Browse files
authored
fix error output caused by circle shape (#40)
* show program name and version info within argparse * lint code * fix error output caused by circle shape
1 parent 7946c19 commit efca771

File tree

4 files changed

+48
-43
lines changed

4 files changed

+48
-43
lines changed

Diff for: src/labelme2yolo/__about__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-FileCopyrightText: 2023-present Wang Xin <[email protected]>
22
#
33
# SPDX-License-Identifier: MIT
4-
'''
4+
"""
55
about version
6-
'''
7-
__version__ = '0.1.4'
6+
"""
7+
__version__ = "0.1.4"

Diff for: src/labelme2yolo/__main__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# SPDX-FileCopyrightText: 2022-present Wang Xin <[email protected]>
22
#
33
# SPDX-License-Identifier: MIT
4-
'''
4+
"""
55
main
6-
'''
6+
"""
77
import sys
88

99
if __name__ == "__main__":

Diff for: src/labelme2yolo/cli/__init__.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
cli init
66
"""
77
import argparse
8-
8+
from labelme2yolo.__about__ import __version__
99
from labelme2yolo.l2y import Labelme2YOLO
1010

1111

1212
def run():
13-
'''
13+
"""
1414
run cli
15-
'''
15+
"""
1616
parser = argparse.ArgumentParser("labelme2yolo")
17+
parser.add_argument(
18+
"-v", "--version", action="version", version="%(prog)s " + __version__
19+
)
1720
parser.add_argument(
1821
"--json_dir", type=str, help="Please input the path of the labelme json files."
1922
)
@@ -22,7 +25,7 @@ def run():
2225
type=float,
2326
nargs="?",
2427
default=0.2,
25-
help="Please input the validation dataset size, for example 0.1.",
28+
help="Please input the validation dataset size, for example 0.2.",
2629
)
2730
parser.add_argument(
2831
"--test_size",
@@ -60,8 +63,7 @@ def run():
6063
parser.print_help()
6164
return 0
6265

63-
convertor = Labelme2YOLO(
64-
args.json_dir, args.output_format, args.label_list)
66+
convertor = Labelme2YOLO(args.json_dir, args.output_format, args.label_list)
6567

6668
if args.json_name is None:
6769
convertor.convert(val_size=args.val_size, test_size=args.test_size)

Diff for: src/labelme2yolo/l2y.py

+35-32
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def train_test_split(dataset_index, test_size=0.2):
3535
"""Split dataset into train set and test set with test_size"""
3636
test_size = min(max(0.0, test_size), 1.0)
3737
total_size = len(dataset_index)
38-
train_size = int(math.ceil(total_size * (1.0 - test_size)))
38+
train_size = int(round(total_size * (1.0 - test_size)))
3939
random.shuffle(dataset_index)
4040
train_index = dataset_index[:train_size]
4141
test_index = dataset_index[train_size:]
@@ -169,22 +169,19 @@ def _update_id_map(self, label: str):
169169
self._label_list.append(label)
170170
self._label_id_map[label] = len(self._label_id_map)
171171

172-
def _make_train_val_dir(self):
172+
def _make_train_val_dir(self, create_test_dir=False):
173173
self._label_dir_path = os.path.join(self._json_dir, "YOLODataset/labels/")
174174
self._image_dir_path = os.path.join(self._json_dir, "YOLODataset/images/")
175175

176-
for yolo_path in (
177-
os.path.join(self._label_dir_path + "train/"),
178-
os.path.join(self._label_dir_path + "val/"),
179-
os.path.join(self._label_dir_path + "test/"),
180-
os.path.join(self._image_dir_path + "train/"),
181-
os.path.join(self._image_dir_path + "val/"),
182-
os.path.join(self._image_dir_path + "test/"),
183-
):
184-
if os.path.exists(yolo_path):
185-
shutil.rmtree(yolo_path)
176+
for yolo_path in [self._label_dir_path, self._image_dir_path]:
177+
shutil.rmtree(yolo_path, ignore_errors=True)
186178

187-
os.makedirs(yolo_path)
179+
parts = ["train", "val", "test"] if create_test_dir else ["train", "val"]
180+
image_dirs = [os.path.join(self._image_dir_path, part) for part in parts]
181+
label_dirs = [os.path.join(self._label_dir_path, part) for part in parts]
182+
dirs = image_dirs + label_dirs
183+
for yolo_path in dirs:
184+
os.makedirs(yolo_path, exist_ok=True)
188185

189186
def _get_dataset_part_json_names(self, dataset_part: str):
190187
"""Get json names in dataset_part folder"""
@@ -196,15 +193,15 @@ def _get_dataset_part_json_names(self, dataset_part: str):
196193
json_names.append(sample_name + ".json")
197194
return json_names
198195

199-
def _train_test_split(self, json_names, val_size, test_size):
196+
def _train_test_split(self, json_names, val_size, test_size=None):
200197
"""Split json names to train, val, test"""
201198
total_size = len(json_names)
202199
dataset_index = list(range(total_size))
203200
train_ids, val_ids = train_test_split(dataset_index, test_size=val_size)
204201
test_ids = []
205202
if test_size is None:
206203
test_size = 0.0
207-
if test_size > 1e-8:
204+
if test_size > 0.0:
208205
train_ids, test_ids = train_test_split(
209206
train_ids, test_size=test_size / (1 - val_size)
210207
)
@@ -220,19 +217,19 @@ def convert(self, val_size, test_size):
220217
os.path.join(self._json_dir, "**", "*.json"), recursive=True
221218
)
222219
json_names = sorted(json_names)
220+
223221
train_json_names, val_json_names, test_json_names = self._train_test_split(
224222
json_names, val_size, test_size
225223
)
226224

227-
self._make_train_val_dir()
225+
self._make_train_val_dir(test_size > 0.0)
228226

229227
# convert labelme object to yolo format object, and save them to files
230228
# also get image from labelme json file and save them under images folder
231-
dirs = ("train/", "val/", "test/")
229+
dirs = ("train", "val", "test")
232230
names = (train_json_names, val_json_names, test_json_names)
233231
for target_dir, json_names in zip(dirs, names):
234-
target_part = target_dir.replace("/", "")
235-
logger.info("Converting %s set ...", target_part)
232+
logger.info("Converting %s set ...", target_dir)
236233
for json_name in tqdm.tqdm(json_names):
237234
self.covert_json_to_text(target_dir, json_name)
238235

@@ -291,21 +288,20 @@ def _get_circle_shape_yolo_object(self, shape, img_h, img_w):
291288
(obj_center_x - shape["points"][1][0]) ** 2
292289
+ (obj_center_y - shape["points"][1][1]) ** 2
293290
)
294-
obj_w = 2 * radius
295-
obj_h = 2 * radius
296-
297-
yolo_center_x = round(float(obj_center_x / img_w), 6)
298-
yolo_center_y = round(float(obj_center_y / img_h), 6)
299-
yolo_w = round(float(obj_w / img_w), 6)
300-
yolo_h = round(float(obj_h / img_h), 6)
291+
num_points = 36
292+
points = np.zeros(2 * num_points)
293+
for i in range(num_points):
294+
angle = 2.0 * math.pi * i / num_points
295+
points[2 * i] = (obj_center_x + radius * math.cos(angle)) / img_w
296+
points[2 * i + 1] = (obj_center_y + radius * math.sin(angle)) / img_h
301297

302298
if shape["label"]:
303299
label = shape["label"]
304300
if label not in self._label_list:
305301
self._update_id_map(label)
306302
label_id = self._label_id_map[shape["label"]]
307303

308-
return label_id, yolo_center_x, yolo_center_y, yolo_w, yolo_h
304+
return label_id, points.tolist()
309305

310306
return None
311307

@@ -344,10 +340,17 @@ def _save_dataset_yaml(self):
344340
names_str += f'"{label}", '
345341
names_str = names_str.rstrip(", ")
346342

347-
content = (
348-
f"train: {train_dir}\nval: {val_dir}\ntest: {test_dir}\n"
349-
f"nc: {len(self._label_id_map)}\n"
350-
f"names: [{names_str}]"
351-
)
343+
if os.path.exists(test_dir):
344+
content = (
345+
f"train: {train_dir}\nval: {val_dir}\ntest: {test_dir}\n"
346+
f"nc: {len(self._label_id_map)}\n"
347+
f"names: [{names_str}]"
348+
)
349+
else:
350+
content = (
351+
f"train: {train_dir}\nval: {val_dir}\n"
352+
f"nc: {len(self._label_id_map)}\n"
353+
f"names: [{names_str}]"
354+
)
352355

353356
yaml_file.write(content)

0 commit comments

Comments
 (0)