当前位置:   article > 正文

ISAT制作YOLOv5实例分割数据集_isat with seg

isat with seg

1.软件安装与使用

ISAT为segment anything衍生的半自动分割标注软件,github地址:https://github.com/yatengLG/ISAT_with_segment_anything.git

按照作者的readme安装好相应的依赖以及对应的权重,软件界面如下:

使用过程:

1.选取图片文件夹

2.确定标签保存文件夹

3.点击SAM,选择下载好的模型(完成标注前的准备工作)

快捷键:

Q:开始标注

E:完成标注

S:保存标签

Z:返回上一步

A:上一张图片

D:下一张图片

鼠标左键:选取感兴趣区域

鼠标右键:选取不感兴趣区域

标注实例:

选取对勾完成标注,按S保存标签,标签文件为json格式,但与COCO格式不相同,软件自带ISAT转成COCO格式,但有bug,没用;

2.数据类型转换

以下为另一个GitHub地址:GitHub - mushroom-x/SegConvert: 实例分割标注文件格式转换脚本工具集

针对ISAT转COCO格式,另外也包括直接转成YOLO格式。

将下面代码中的路径改成前面的图片路径和标签路径,将标签名和序号改为自己的类别名。

ISAT2COCO:

  1. import json
  2. import os
  3. import numpy as np
  4. from collections import defaultdict
  5. # ISAT标注数据路径
  6. ISAT_FOLDER = "./annotations"
  7. # 图像所在的路径
  8. IMAGE_FOLDER = "./images"
  9. # COCO格式的JSON文件存放路径
  10. # 可以自己指定,这里是直接定义在图像文件夹下
  11. COCO_PATH = os.path.join(IMAGE_FOLDER, "coco.json")
  12. # 定义类别名称与ID号的映射
  13. # 需要注意的是,不需要按照ISAT的classesition.txt里面的定义来
  14. # 可以选择部分自己需要的类别, ID序号也可以重新填写(从0开始)
  15. category_mapping = {"color_block": 0}
  16. # 定义COCO格式的字典
  17. # - "info"/"description" 里面写一下,你这个是什么的数据集
  18. coco = {
  19. "info": {
  20. "description": "Color Block Segmentation",
  21. "version": "1.0",
  22. "year": 2023,
  23. "contributor": "",
  24. "date_created": ""
  25. },
  26. "images": [],
  27. "annotations": [],
  28. "categories": []
  29. }
  30. # 填写annotations栏目
  31. for class_id, class_name in category_mapping.items():
  32. coco["categories"].append({"id": class_id, "name": class_name, "supercategory": "object"})
  33. # 图像序号
  34. image_id = 1
  35. # 遍历所有的ISAT文件夹
  36. for filename in os.listdir(ISAT_FOLDER):
  37. # 判断是否为ISAT格式数据
  38. if not filename.endswith(".json"):
  39. continue
  40. # 载入ISAT数据
  41. with open(os.path.join(ISAT_FOLDER, filename), "r") as f:
  42. isat = json.load(f)
  43. # 获取图像名称
  44. image_filename = isat["info"]["name"]
  45. # 填写文件路径
  46. image_path = os.path.join(IMAGE_FOLDER, image_filename)
  47. image_info = {
  48. "id": image_id,
  49. "file_name": image_filename,
  50. "width": isat["info"]["width"],
  51. "height": isat["info"]["height"]
  52. }
  53. image_id += 1
  54. # 添加图像信息
  55. coco["images"].append(image_info)
  56. # 标注序号
  57. annotation_id = 1
  58. # 遍历标注信息
  59. for annotation in isat["objects"]:
  60. # 获取类别名称
  61. category_name = annotation["category"]
  62. # 位置类别名称(选择跳过)
  63. if category_name not in category_mapping:
  64. # print(f"未知类别名称: {category_name}")
  65. continue
  66. # 获取类别ID
  67. category_id = category_mapping[category_name]
  68. # 提取分割信息
  69. segmentation = annotation["segmentation"]
  70. segmentation = np.uint32(segmentation)
  71. # 转换为一行的形式 [[x1, y1, x2, y2, ..., xn, yn]]
  72. segmentation = [(segmentation.reshape(-1)).tolist()]
  73. # 提取面积信息
  74. area = annotation["area"]
  75. # 定义标注信息
  76. annotation_info = {
  77. "id": annotation_id,
  78. "image_id": image_id,
  79. "category_id": category_id,
  80. "segmentation": segmentation,
  81. "area": area,
  82. "iscrowd": 0
  83. }
  84. # 追加到annotations列表
  85. coco["annotations"].append(annotation_info)
  86. # 标注编号自增1
  87. annotation_id += 1
  88. # 保存coco格式
  89. with open(COCO_PATH, "w") as f:
  90. json.dump(coco, f)

运行结果是生成一个json文件。

ISAT2YOLO:

  1. import json
  2. import os
  3. # 定义类别名称与ID号的映射
  4. # 需要注意的是,不需要按照ISAT的classesition.txt里面的定义来
  5. # 可以选择部分自己需要的类别, ID序号也可以重新填写(从0开始)
  6. category_mapping = {"color_block": 0}
  7. # ISAT格式的实例分割标注文件
  8. ISAT_FOLDER = "./annotations/"
  9. # YOLO格式的实例分割标注文件
  10. YOLO_FOLDER = "./labels"
  11. # 创建YoloV8标注的文件夹
  12. if not os.path.exists(YOLO_FOLDER):
  13. os.makedirs(YOLO_FOLDER)
  14. # 载入所有的ISAT的JSON文件
  15. for filename in os.listdir(ISAT_FOLDER):
  16. if not filename.endswith(".json"):
  17. # 不是json格式, 跳过
  18. continue
  19. # 载入ISAT的JSON文件
  20. with open(os.path.join(ISAT_FOLDER, filename), "r") as f:
  21. isat = json.load(f)
  22. # 提取文件名(不带文件后缀)
  23. image_name = filename.split(".")[0]
  24. # Yolo格式的标注文件名, 后缀是txt
  25. yolo_filename = f"{image_name}.txt"
  26. # 写入信息
  27. with open(os.path.join(YOLO_FOLDER, yolo_filename), "w") as f:
  28. # 获取图像信息
  29. # - 图像宽度
  30. image_width = isat["info"]["width"]
  31. # - 图像高度
  32. image_height = isat["info"]["height"]
  33. # 获取实例标注数据
  34. for annotation in isat["objects"]:
  35. # 获取类别名称
  36. category_name = annotation["category"]
  37. # 如果不在类别名称字典里面,跳过
  38. if category_name not in category_mapping:
  39. continue
  40. # 从字典里面查询类别ID
  41. category_id = category_mapping[category_name]
  42. # 提取分割信息
  43. segmentation = annotation["segmentation"]
  44. segmentation_yolo = []
  45. # 遍历所有的轮廓点
  46. for segment in segmentation:
  47. # 提取轮廓点的像素坐标 x, y
  48. x, y = segment
  49. # 归一化处理
  50. x_center = x/image_width
  51. y_center = y/image_height
  52. # 添加到segmentation_yolo里面
  53. segmentation_yolo.append(f"{x_center:.4f} {y_center:.4f}")
  54. segmentation_yolo_str = " ".join(segmentation_yolo)
  55. # 添加一行Yolo格式的实例分割数据
  56. # 格式如下: class_id x1 y1 x2 y2 ... xn yn\n
  57. f.write(f"{category_id} {segmentation_yolo_str}\n")

运行结果是所有标签对应的txt文件

第一个为标签编号,后面的数为标签点的归一化坐标。

3.训练集、验证集、测试集划分
代码:main函数的default内填入对应的自定义路径

  1. # 将图片和标注数据按比例切分为 训练集和测试集
  2. import shutil
  3. import random
  4. import os
  5. import argparse
  6. # 检查文件夹是否存在
  7. def mkdir(path):
  8. if not os.path.exists(path):
  9. os.makedirs(path)
  10. def main(image_dir, txt_dir, save_dir):
  11. # 创建文件夹
  12. mkdir(save_dir)
  13. images_dir = os.path.join(save_dir, 'images')
  14. labels_dir = os.path.join(save_dir, 'labels')
  15. img_train_path = os.path.join(images_dir, 'train')
  16. img_test_path = os.path.join(images_dir, 'test')
  17. img_val_path = os.path.join(images_dir, 'val')
  18. label_train_path = os.path.join(labels_dir, 'train')
  19. label_test_path = os.path.join(labels_dir, 'test')
  20. label_val_path = os.path.join(labels_dir, 'val')
  21. mkdir(images_dir);mkdir(labels_dir);mkdir(img_train_path);mkdir(img_test_path);mkdir(img_val_path);mkdir(label_train_path);mkdir(label_test_path);mkdir(label_val_path);
  22. # 数据集划分比例,训练集75%,验证集15%,测试集15%,按需修改
  23. train_percent = 0.8
  24. val_percent = 0.1
  25. test_percent = 0.1
  26. total_txt = os.listdir(txt_dir)
  27. num_txt = len(total_txt)
  28. list_all_txt = range(num_txt) # 范围 range(0, num)
  29. num_train = int(num_txt * train_percent)
  30. num_val = int(num_txt * val_percent)
  31. num_test = num_txt - num_train - num_val
  32. train = random.sample(list_all_txt, num_train)
  33. # 在全部数据集中取出train
  34. val_test = [i for i in list_all_txt if not i in train]
  35. # 再从val_test取出num_val个元素,val_test剩下的元素就是test
  36. val = random.sample(val_test, num_val)
  37. print("训练集数目:{}, 验证集数目:{},测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))
  38. for i in list_all_txt:
  39. name = total_txt[i][:-4]
  40. srcImage = os.path.join(image_dir, name+'.jpg')
  41. srcLabel = os.path.join(txt_dir, name + '.txt')
  42. if i in train:
  43. dst_train_Image = os.path.join(img_train_path, name + '.jpg')
  44. dst_train_Label = os.path.join(label_train_path, name + '.txt')
  45. shutil.copyfile(srcImage, dst_train_Image)
  46. shutil.copyfile(srcLabel, dst_train_Label)
  47. elif i in val:
  48. dst_val_Image = os.path.join(img_val_path, name + '.jpg')
  49. dst_val_Label = os.path.join(label_val_path, name + '.txt')
  50. shutil.copyfile(srcImage, dst_val_Image)
  51. shutil.copyfile(srcLabel, dst_val_Label)
  52. else:
  53. dst_test_Image = os.path.join(img_test_path, name + '.jpg')
  54. dst_test_Label = os.path.join(label_test_path, name + '.txt')
  55. shutil.copyfile(srcImage, dst_test_Image)
  56. shutil.copyfile(srcLabel, dst_test_Label)
  57. if __name__ == '__main__':
  58. """
  59. python split_datasets.py --image-dir my_datasets/color_rings/imgs --txt-dir my_datasets/color_rings/txts --save-dir my_datasets/color_rings/train_data
  60. """
  61. parser = argparse.ArgumentParser(description='split datasets to train,val,test params')
  62. parser.add_argument('--image-dir', default = '', type=str, help='image path dir')
  63. parser.add_argument('--txt-dir', default = '', type=str, help='txt path dir')
  64. parser.add_argument('--save-dir', default = '', type=str, help='save dir')
  65. args = parser.parse_args()
  66. image_dir = args.image_dir
  67. txt_dir = args.txt_dir
  68. save_dir = args.save_dir
  69. main(image_dir, txt_dir, save_dir)

完成数据集划分

4.yolov5模型训练

data文件夹里面有yaml文件,下面图片是data/coco128-seg.yaml的内容。

path:是上面--save-dir切分图片存放的路径;

train、val、test分别对于images里面的文件夹,按实际填入;

names:是类别名称和赋予的下标,跟上面转txt顺序相同

完成数据集的创建

训练:

python segment/train.py --epochs 300 --data coco128-seg.yaml --weights yolov5m-seg.pt --img 640 --cfg models/segment/yolov5m-seg.yaml --batch-size 16 --device 2

参考链接:YOLOv5-7.0实例分割训练自己的数据,切分mask图并摆正_yolov5图像分割_jin__9981的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/122408
推荐阅读
相关标签
  

闽ICP备14008679号