Skip to content

Commit c008d6c

Browse files
authored
Merge pull request #12 from GreatV/dev
add output_format option
2 parents 14b716e + 1f31b4b commit c008d6c

File tree

5 files changed

+49
-70
lines changed

5 files changed

+49
-70
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
dataset/
2+
13
# Byte-compiled / optimized / DLL files
24
__pycache__/
35
*.py[cod]

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ If you've already marked your segmentation dataset by LabelMe, it's easy to use
1414

1515
## New
1616
- export data as yolo polygon annotation (for YOLOv5 v7.0 segmentation)
17-
17+
- Now you can choose the output format of the label text. The available options are `plygon` and `bbox`.
1818
## Installation
1919

2020
```console
@@ -30,6 +30,8 @@ pip install labelme2yolo
3030

3131
**--json_name (Optional)** Convert single LabelMe JSON file.
3232

33+
**--output_format (Optional)** The output format of label.
34+
3335
## How to Use
3436

3537
### 1. Convert JSON files, split training, validation and test dataset by --val_size and --test_size

src/labelme2yolo/__about__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# SPDX-FileCopyrightText: 2022-present Wang Xin <[email protected]>
1+
# SPDX-FileCopyrightText: 2023-present Wang Xin <[email protected]>
22
#
33
# SPDX-License-Identifier: MIT
44

5-
__version__ = '0.0.8'
5+
__version__ = '0.0.9'

src/labelme2yolo/cli/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ def run():
1616
type=float,
1717
nargs="?",
1818
default=None,
19-
help="Please input the validation dataset size, for example 0.1 ",
19+
help="Please input the validation dataset size, for example 0.1.",
2020
)
2121
parser.add_argument(
2222
"--test_size",
2323
type=float,
2424
nargs="?",
2525
default=None,
26-
help="Please input the validation dataset size, for example 0.1 ",
26+
help="Please input the test dataset size, for example 0.1.",
2727
)
2828
parser.add_argument(
2929
"--json_name",
@@ -32,13 +32,21 @@ def run():
3232
default=None,
3333
help="If you put json name, it would convert only one json file to YOLO.",
3434
)
35+
parser.add_argument(
36+
"--output_format",
37+
type=str,
38+
default="polygon",
39+
help='The default output format for labelme2yolo is "polygon".'
40+
' However, you can choose to output in bbox format by specifying the "bbox" option.',
41+
)
42+
3543
args = parser.parse_args()
3644

3745
if not args.json_dir:
3846
parser.print_help()
3947
return 0
4048

41-
convertor = Labelme2YOLO(args.json_dir)
49+
convertor = Labelme2YOLO(args.json_dir, args.output_format)
4250

4351
if args.json_name is None:
4452
convertor.convert(val_size=args.val_size, test_size=args.test_size)

src/labelme2yolo/l2y.py

Lines changed: 31 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -93,27 +93,28 @@ def get_label_id_map(json_dir):
9393
return OrderedDict([(label, label_id) for label_id, label in enumerate(label_set)])
9494

9595

96-
def extend_point_list(point_list):
96+
def extend_point_list(point_list, format="polygon"):
9797
xmin = min([float(point) for point in point_list[::2]])
9898
xmax = max([float(point) for point in point_list[::2]])
9999
ymin = min([float(point) for point in point_list[1::2]])
100100
ymax = max([float(point) for point in point_list[1::2]])
101101

102-
return np.array([xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax])
102+
if (format == "polygon"):
103+
return np.array([xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax])
104+
if (format == "bbox"):
105+
return np.array([xmin, ymin, xmax - xmin, ymax - ymin])
103106

104107

105108
def save_yolo_label(json_name, label_dir_path, target_dir, yolo_obj_list):
106-
txt_path = os.path.join(
107-
label_dir_path, target_dir, json_name.replace(".json", ".txt")
108-
)
109+
txt_path = os.path.join(label_dir_path,
110+
target_dir,
111+
json_name.replace(".json", ".txt"))
109112

110113
with open(txt_path, "w+") as f:
111-
for yolo_obj_idx, yolo_obj in enumerate(yolo_obj_list):
112-
yolo_obj_line = (
113-
"%s %s %s %s %s\n" % yolo_obj
114-
if yolo_obj_idx + 1 != len(yolo_obj_list)
115-
else "%s %s %s %s %s" % yolo_obj
116-
)
114+
for yolo_obj in yolo_obj_list:
115+
label, points = yolo_obj
116+
points = [str(item) for item in points]
117+
yolo_obj_line = f"{label} {' '.join(points)}\n"
117118
f.write(yolo_obj_line)
118119

119120

@@ -130,10 +131,11 @@ def save_yolo_image(json_data, json_name, image_dir_path, target_dir):
130131

131132
class Labelme2YOLO(object):
132133

133-
def __init__(self, json_dir):
134+
def __init__(self, json_dir, output_format):
134135
self._json_dir = json_dir
136+
self._output_format = output_format
135137

136-
self._label_id_map = self._get_label_id_map(self._json_dir)
138+
self._label_id_map = get_label_id_map(self._json_dir)
137139

138140
def _make_train_val_dir(self):
139141
self._label_dir_path = os.path.join(self._json_dir,
@@ -152,20 +154,6 @@ def _make_train_val_dir(self):
152154

153155
os.makedirs(yolo_path)
154156

155-
@staticmethod
156-
def _get_label_id_map(self, json_dir):
157-
label_set = set()
158-
159-
for file_name in os.listdir(json_dir):
160-
if file_name.endswith('json'):
161-
json_path = os.path.join(json_dir, file_name)
162-
data = json.load(open(json_path))
163-
for shape in data['shapes']:
164-
label_set.add(shape['label'])
165-
166-
return OrderedDict([(label, label_id)
167-
for label_id, label in enumerate(label_set)])
168-
169157
def _train_test_split(self, folders, json_names, val_size, test_size):
170158
if len(folders) > 0 and 'train' in folders and 'val' in folders and 'test' in folders:
171159
train_folder = os.path.join(self._json_dir, 'train/')
@@ -233,28 +221,28 @@ def covert_json_to_text(self, target_dir, json_name):
233221
print('Converting %s for %s ...' %
234222
(json_name, target_dir.replace('/', '')))
235223

236-
img_path = self._save_yolo_image(json_data,
237-
json_name,
238-
self._image_dir_path,
239-
target_dir)
224+
img_path = save_yolo_image(json_data,
225+
json_name,
226+
self._image_dir_path,
227+
target_dir)
240228
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
241-
self._save_yolo_label(json_name,
242-
self._label_dir_path,
243-
target_dir,
244-
yolo_obj_list)
229+
save_yolo_label(json_name,
230+
self._label_dir_path,
231+
target_dir,
232+
yolo_obj_list)
245233

246234
def convert_one(self, json_name):
247235
json_path = os.path.join(self._json_dir, json_name)
248236
json_data = json.load(open(json_path))
249237

250238
print('Converting %s ...' % json_name)
251239

252-
img_path = self._save_yolo_image(json_data, json_name,
253-
self._json_dir, '')
240+
img_path = save_yolo_image(json_data, json_name,
241+
self._json_dir, '')
254242

255243
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
256-
self._save_yolo_label(json_name, self._json_dir,
257-
'', yolo_obj_list)
244+
save_yolo_label(json_name, self._json_dir,
245+
'', yolo_obj_list)
258246

259247
def _get_yolo_object_list(self, json_data, img_path):
260248
yolo_obj_list = []
@@ -298,35 +286,14 @@ def _get_other_shape_yolo_object(self, shape, img_h, img_w):
298286
points[::2] = [float(point[0]) / img_w for point in point_list]
299287
points[1::2] = [float(point[1]) / img_h for point in point_list]
300288
if len(points) == 4:
301-
points = extend_point_list(points)
289+
if self._output_format == "polygon":
290+
points = extend_point_list(points)
291+
if self._output_format == "bbox":
292+
points = extend_point_list(points, "bbox")
302293
label_id = self._label_id_map[shape['label']]
303294

304295
return label_id, points.tolist()
305296

306-
@staticmethod
307-
def _save_yolo_label(self, json_name, label_dir_path, target_dir, yolo_obj_list):
308-
txt_path = os.path.join(label_dir_path,
309-
target_dir,
310-
json_name.replace('.json', '.txt'))
311-
312-
with open(txt_path, 'w+') as f:
313-
for yolo_obj in yolo_obj_list:
314-
label, points = yolo_obj
315-
points = [str(item) for item in points]
316-
yolo_obj_line = f"{label} {' '.join(points)}\n"
317-
f.write(yolo_obj_line)
318-
319-
@staticmethod
320-
def _save_yolo_image(self, json_data, json_name, image_dir_path, target_dir):
321-
img_name = json_name.replace('.json', '.png')
322-
img_path = os.path.join(image_dir_path, target_dir, img_name)
323-
324-
if not os.path.exists(img_path):
325-
img = img_b64_to_arr(json_data['imageData'])
326-
PIL.Image.fromarray(img).save(img_path)
327-
328-
return img_path
329-
330297
def _save_dataset_yaml(self):
331298
yaml_path = os.path.join(
332299
self._json_dir, 'YOLODataset/', 'dataset.yaml')

0 commit comments

Comments
 (0)