add output_format option
This commit is contained in:
parent
14b716e173
commit
1f31b4bae9
|
@ -1,3 +1,5 @@
|
||||||
|
dataset/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
|
|
@ -14,7 +14,7 @@ If you've already marked your segmentation dataset by LabelMe, it's easy to use
|
||||||
|
|
||||||
## New
|
## New
|
||||||
- export data as yolo polygon annotation (for YOLOv5 v7.0 segmentation)
|
- export data as yolo polygon annotation (for YOLOv5 v7.0 segmentation)
|
||||||
|
- Now you can choose the output format of the label text. The available options are `plygon` and `bbox`.
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```console
|
```console
|
||||||
|
@ -30,6 +30,8 @@ pip install labelme2yolo
|
||||||
|
|
||||||
**--json_name (Optional)** Convert single LabelMe JSON file.
|
**--json_name (Optional)** Convert single LabelMe JSON file.
|
||||||
|
|
||||||
|
**--output_format (Optional)** The output format of label.
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
|
|
||||||
### 1. Convert JSON files, split training, validation and test dataset by --val_size and --test_size
|
### 1. Convert JSON files, split training, validation and test dataset by --val_size and --test_size
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2022-present Wang Xin <xinwang614@gmail.com>
|
# SPDX-FileCopyrightText: 2023-present Wang Xin <xinwang614@gmail.com>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
__version__ = '0.0.8'
|
__version__ = '0.0.9'
|
||||||
|
|
|
@ -16,14 +16,14 @@ def run():
|
||||||
type=float,
|
type=float,
|
||||||
nargs="?",
|
nargs="?",
|
||||||
default=None,
|
default=None,
|
||||||
help="Please input the validation dataset size, for example 0.1 ",
|
help="Please input the validation dataset size, for example 0.1.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--test_size",
|
"--test_size",
|
||||||
type=float,
|
type=float,
|
||||||
nargs="?",
|
nargs="?",
|
||||||
default=None,
|
default=None,
|
||||||
help="Please input the validation dataset size, for example 0.1 ",
|
help="Please input the test dataset size, for example 0.1.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--json_name",
|
"--json_name",
|
||||||
|
@ -32,13 +32,21 @@ def run():
|
||||||
default=None,
|
default=None,
|
||||||
help="If you put json name, it would convert only one json file to YOLO.",
|
help="If you put json name, it would convert only one json file to YOLO.",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--output_format",
|
||||||
|
type=str,
|
||||||
|
default="polygon",
|
||||||
|
help='The default output format for labelme2yolo is "polygon".'
|
||||||
|
' However, you can choose to output in bbox format by specifying the "bbox" option.',
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if not args.json_dir:
|
if not args.json_dir:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
convertor = Labelme2YOLO(args.json_dir)
|
convertor = Labelme2YOLO(args.json_dir, args.output_format)
|
||||||
|
|
||||||
if args.json_name is None:
|
if args.json_name is None:
|
||||||
convertor.convert(val_size=args.val_size, test_size=args.test_size)
|
convertor.convert(val_size=args.val_size, test_size=args.test_size)
|
||||||
|
|
|
@ -93,27 +93,28 @@ def get_label_id_map(json_dir):
|
||||||
return OrderedDict([(label, label_id) for label_id, label in enumerate(label_set)])
|
return OrderedDict([(label, label_id) for label_id, label in enumerate(label_set)])
|
||||||
|
|
||||||
|
|
||||||
def extend_point_list(point_list):
|
def extend_point_list(point_list, format="polygon"):
|
||||||
xmin = min([float(point) for point in point_list[::2]])
|
xmin = min([float(point) for point in point_list[::2]])
|
||||||
xmax = max([float(point) for point in point_list[::2]])
|
xmax = max([float(point) for point in point_list[::2]])
|
||||||
ymin = min([float(point) for point in point_list[1::2]])
|
ymin = min([float(point) for point in point_list[1::2]])
|
||||||
ymax = max([float(point) for point in point_list[1::2]])
|
ymax = max([float(point) for point in point_list[1::2]])
|
||||||
|
|
||||||
return np.array([xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax])
|
if (format == "polygon"):
|
||||||
|
return np.array([xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax])
|
||||||
|
if (format == "bbox"):
|
||||||
|
return np.array([xmin, ymin, xmax - xmin, ymax - ymin])
|
||||||
|
|
||||||
|
|
||||||
def save_yolo_label(json_name, label_dir_path, target_dir, yolo_obj_list):
|
def save_yolo_label(json_name, label_dir_path, target_dir, yolo_obj_list):
|
||||||
txt_path = os.path.join(
|
txt_path = os.path.join(label_dir_path,
|
||||||
label_dir_path, target_dir, json_name.replace(".json", ".txt")
|
target_dir,
|
||||||
)
|
json_name.replace(".json", ".txt"))
|
||||||
|
|
||||||
with open(txt_path, "w+") as f:
|
with open(txt_path, "w+") as f:
|
||||||
for yolo_obj_idx, yolo_obj in enumerate(yolo_obj_list):
|
for yolo_obj in yolo_obj_list:
|
||||||
yolo_obj_line = (
|
label, points = yolo_obj
|
||||||
"%s %s %s %s %s\n" % yolo_obj
|
points = [str(item) for item in points]
|
||||||
if yolo_obj_idx + 1 != len(yolo_obj_list)
|
yolo_obj_line = f"{label} {' '.join(points)}\n"
|
||||||
else "%s %s %s %s %s" % yolo_obj
|
|
||||||
)
|
|
||||||
f.write(yolo_obj_line)
|
f.write(yolo_obj_line)
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,10 +131,11 @@ def save_yolo_image(json_data, json_name, image_dir_path, target_dir):
|
||||||
|
|
||||||
class Labelme2YOLO(object):
|
class Labelme2YOLO(object):
|
||||||
|
|
||||||
def __init__(self, json_dir):
|
def __init__(self, json_dir, output_format):
|
||||||
self._json_dir = json_dir
|
self._json_dir = json_dir
|
||||||
|
self._output_format = output_format
|
||||||
|
|
||||||
self._label_id_map = self._get_label_id_map(self._json_dir)
|
self._label_id_map = get_label_id_map(self._json_dir)
|
||||||
|
|
||||||
def _make_train_val_dir(self):
|
def _make_train_val_dir(self):
|
||||||
self._label_dir_path = os.path.join(self._json_dir,
|
self._label_dir_path = os.path.join(self._json_dir,
|
||||||
|
@ -152,20 +154,6 @@ class Labelme2YOLO(object):
|
||||||
|
|
||||||
os.makedirs(yolo_path)
|
os.makedirs(yolo_path)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _get_label_id_map(self, json_dir):
|
|
||||||
label_set = set()
|
|
||||||
|
|
||||||
for file_name in os.listdir(json_dir):
|
|
||||||
if file_name.endswith('json'):
|
|
||||||
json_path = os.path.join(json_dir, file_name)
|
|
||||||
data = json.load(open(json_path))
|
|
||||||
for shape in data['shapes']:
|
|
||||||
label_set.add(shape['label'])
|
|
||||||
|
|
||||||
return OrderedDict([(label, label_id)
|
|
||||||
for label_id, label in enumerate(label_set)])
|
|
||||||
|
|
||||||
def _train_test_split(self, folders, json_names, val_size, test_size):
|
def _train_test_split(self, folders, json_names, val_size, test_size):
|
||||||
if len(folders) > 0 and 'train' in folders and 'val' in folders and 'test' in folders:
|
if len(folders) > 0 and 'train' in folders and 'val' in folders and 'test' in folders:
|
||||||
train_folder = os.path.join(self._json_dir, 'train/')
|
train_folder = os.path.join(self._json_dir, 'train/')
|
||||||
|
@ -233,15 +221,15 @@ class Labelme2YOLO(object):
|
||||||
print('Converting %s for %s ...' %
|
print('Converting %s for %s ...' %
|
||||||
(json_name, target_dir.replace('/', '')))
|
(json_name, target_dir.replace('/', '')))
|
||||||
|
|
||||||
img_path = self._save_yolo_image(json_data,
|
img_path = save_yolo_image(json_data,
|
||||||
json_name,
|
json_name,
|
||||||
self._image_dir_path,
|
self._image_dir_path,
|
||||||
target_dir)
|
target_dir)
|
||||||
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
|
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
|
||||||
self._save_yolo_label(json_name,
|
save_yolo_label(json_name,
|
||||||
self._label_dir_path,
|
self._label_dir_path,
|
||||||
target_dir,
|
target_dir,
|
||||||
yolo_obj_list)
|
yolo_obj_list)
|
||||||
|
|
||||||
def convert_one(self, json_name):
|
def convert_one(self, json_name):
|
||||||
json_path = os.path.join(self._json_dir, json_name)
|
json_path = os.path.join(self._json_dir, json_name)
|
||||||
|
@ -249,12 +237,12 @@ class Labelme2YOLO(object):
|
||||||
|
|
||||||
print('Converting %s ...' % json_name)
|
print('Converting %s ...' % json_name)
|
||||||
|
|
||||||
img_path = self._save_yolo_image(json_data, json_name,
|
img_path = save_yolo_image(json_data, json_name,
|
||||||
self._json_dir, '')
|
self._json_dir, '')
|
||||||
|
|
||||||
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
|
yolo_obj_list = self._get_yolo_object_list(json_data, img_path)
|
||||||
self._save_yolo_label(json_name, self._json_dir,
|
save_yolo_label(json_name, self._json_dir,
|
||||||
'', yolo_obj_list)
|
'', yolo_obj_list)
|
||||||
|
|
||||||
def _get_yolo_object_list(self, json_data, img_path):
|
def _get_yolo_object_list(self, json_data, img_path):
|
||||||
yolo_obj_list = []
|
yolo_obj_list = []
|
||||||
|
@ -298,35 +286,14 @@ class Labelme2YOLO(object):
|
||||||
points[::2] = [float(point[0]) / img_w for point in point_list]
|
points[::2] = [float(point[0]) / img_w for point in point_list]
|
||||||
points[1::2] = [float(point[1]) / img_h for point in point_list]
|
points[1::2] = [float(point[1]) / img_h for point in point_list]
|
||||||
if len(points) == 4:
|
if len(points) == 4:
|
||||||
points = extend_point_list(points)
|
if self._output_format == "polygon":
|
||||||
|
points = extend_point_list(points)
|
||||||
|
if self._output_format == "bbox":
|
||||||
|
points = extend_point_list(points, "bbox")
|
||||||
label_id = self._label_id_map[shape['label']]
|
label_id = self._label_id_map[shape['label']]
|
||||||
|
|
||||||
return label_id, points.tolist()
|
return label_id, points.tolist()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _save_yolo_label(self, json_name, label_dir_path, target_dir, yolo_obj_list):
|
|
||||||
txt_path = os.path.join(label_dir_path,
|
|
||||||
target_dir,
|
|
||||||
json_name.replace('.json', '.txt'))
|
|
||||||
|
|
||||||
with open(txt_path, 'w+') as f:
|
|
||||||
for yolo_obj in yolo_obj_list:
|
|
||||||
label, points = yolo_obj
|
|
||||||
points = [str(item) for item in points]
|
|
||||||
yolo_obj_line = f"{label} {' '.join(points)}\n"
|
|
||||||
f.write(yolo_obj_line)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _save_yolo_image(self, json_data, json_name, image_dir_path, target_dir):
|
|
||||||
img_name = json_name.replace('.json', '.png')
|
|
||||||
img_path = os.path.join(image_dir_path, target_dir, img_name)
|
|
||||||
|
|
||||||
if not os.path.exists(img_path):
|
|
||||||
img = img_b64_to_arr(json_data['imageData'])
|
|
||||||
PIL.Image.fromarray(img).save(img_path)
|
|
||||||
|
|
||||||
return img_path
|
|
||||||
|
|
||||||
def _save_dataset_yaml(self):
|
def _save_dataset_yaml(self):
|
||||||
yaml_path = os.path.join(
|
yaml_path = os.path.join(
|
||||||
self._json_dir, 'YOLODataset/', 'dataset.yaml')
|
self._json_dir, 'YOLODataset/', 'dataset.yaml')
|
||||||
|
|
Loading…
Reference in New Issue