最近在做图像中颗粒对象分割应用过程中,遇到如何将SAM-Tool工具或labelme标注的数据(json格式)转换为包含所有分割点的数据集(yolo格式),而不是只包含矩形坐标的数据(yolo格式),本次主要研究如何利用工具或自行编写转换代码,实现两种格式数据集的自动转换,对象标注主要基于SAM-Tool工具完成,然后利用该转换工具实现yolo格式数据生成,主要便于后续的yolov8x-seg模型使用。具体如下,供大家参考。
一、方式1:基于sam的ultralytics库的转换工具
需要事先在环境中安装ultralytics库,命令为:pip install ultralytics
然后下载ultralytics源码进入到根目录,执行如下命令,即可完成json格式数据集转换为yolo格式数据集。
# 目前这种方式在部分机器上不好使
python ultralytics/data/converter.py --source D:/xxx/annotations.json --output D:/xxx/yolo
二、方式2:自行实现json格式转换为yolo格式
分割为只包含矩形坐标的数据(yolo格式),SAM-Tool工具默认提供了对应的工具,详见json2yolo.py。
本次自行编写的转换代码详见下面的json2yolo_seg.py。执行完成后,最终将在数据目录下生成yolo文件夹,用于存放yolo格式的标注数据集。
# 自行实现转换 运行命令
python json2yolo_seg.py --json D:\xxx\annotations.json
json2yolo_seg转换工具代码如下
# json2yolo_seg.py
import argparse
import json
import os
def json2yolo_seg(json_path, output_path):
# 读取JSON文件
with open(json_path, 'r') as f:
data = json.load(f)
class_map=data['categories']
for item in data['images']:
image_width=item['width']
image_height=item['height']
image_id=item['id']
txt_filename=item['file_name'].split('\\')[1].replace('.jpg','.txt')
txt_path=os.path.join(output_path,txt_filename)
# 创建输出文件
with open(txt_path, 'w') as f:
# 处理每个标注对象
filtered_list = [item for item in data['annotations'] if item['image_id'] == image_id]
for shape in filtered_list:
# 获取类别名称和索引
class_id = shape['category_id']
# 获取多边形点
points = shape['segmentation'][0]
# 获取多边形面积
area = shape['area']
# 转换为YOLO格式
yolo_line = f"{class_id}"
for i in range(0, len(points), 2): # 注意这里是x,y成对出现,所以步长为2
x, y = points[i], points[i+1]
# 归一化坐标
x_norm = x / image_width
y_norm = y / image_height
yolo_line += f" {x_norm:.6f} {y_norm:.6f}"
f.write(yolo_line + '\n')
# 运行示例:python json2yolo_seg.py --json D:\xxx\annotations.json
if __name__ == '__main__':
# 设置路径
parser = argparse.ArgumentParser()
parser.add_argument('--json', default='D:\xxx\annotations.json', type=str, help='COCO annotations.json 路径')
args = parser.parse_args()
# 方式2:自定义实现格式转换,这里不适用传入的out参数。
json_path=args.json
# 获取output_path倒数第二个斜杠之前的字符串
# 去掉末尾多余的反斜杠,再按反斜杠切分,取倒数第二个斜杠之前的内容
output_path = "\\".join(json_path.rstrip("\\").split("\\")[:-1]) + '\\yolo\\'
json2yolo_seg(json_path, output_path)
print('完成coco2yolo_seg转换...')
三、转换效果
json格式示例数据(原始标注数据):其中一个标注的颗粒对象数据见下图的segmentation段。详见下图。
yolo格式示例数据(转换后数据):转换为yolo格式后的文件夹详见下图左侧文件,内容详见下图右侧,每一个标注颗粒对象以类别编号开始,后面跟随所有边界点数值。