文章目录[隐藏]
![]()
准备数据
将需要标注的数据放到同一个文件夹中
下载并安装labelme
安装labelme,用于对数据进行标注
pip install labelme
下载labelme,转换格式时需要使用到其中的文件:
git clone https://github.com/wkentaro/labelme.git
转COCO格式需要用到这个文件:labelme2coco.py
转VOC格式需要用到这个文件:labelme2voc.py
本篇以COCO格式为例,VOC同理
创建一个labels.txt
参考labelme实例分割的labels.txt创建一个labels.txt文件
__ignore__
_background_
类别1
类别2
前面两行即使没有标注,也是需要的
注意:这里的类别1,类别2在实际应用的时候最好不要使用中文,否则可能会出现转换失败的情况
标注数据
使用安装好的labelme进行标注,为每个图片创建一个json文件
labelme --labels=labels.txt
这个命令会启动labelme并使用指定的labels.txt文件
File >> Open Dir找到前面存放图片的文件夹并打开,接着可以开始进行标注
标注的原则是对感兴趣的目标根据实际应用的需求尽可能地准确
转换格式
python ./labelme2coco.py <labelled_data_folder> <out_folder> --labels labels.txt
<labelled_data_folder>就是存放标注数据json文件的文件夹
 <out_folder>就是输出的路径,不存在的话会自动创建,存在的话会强制对出程序
因为标注数据时labelme已经将图片数据转为字节流数据保存到json文件中imageData字段,在转换时,会将字节流数据保存为jpg放到<out_folder>/JPEGImages下,会将标注数据可视化保存到<out_folder>/Visualization下,转换后的COCO格式的数据在<out_folder>/annotations.json
训练时,需要用到<out_folder>/JPEGImages和<out_folder>/annotations.json
如果不需要可视化结果可以在上面的命令后面添加--noviz
标注的json的格式:
名字和图片名字相同,后缀不同
文件中的内容简化后:
{
  "shapes": [
    {
      "label": "类别1",
      "points": [
        [
          217.57142857142858,
          621.6190476190477
        ],
        [
          479.4761904761905,
          621.6190476190477
        ],
        [
          460.42857142857144,
          802.5714285714287
        ],
        [
          203.2857142857143,
          788.2857142857144
        ]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
    {
      "label": "类别1",
      "points": [...],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
    {
      "label": "类别2",
      "points": [...],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
  ],
  "imagePath": "000593-1-202102020641225190-0000000.jpg",
  "imageData": "",
  "imageHeight": 2048,
  "imageWidth": 2448
}
转换之后的json的内容是:
{
    "info": {
        "description": null,
        "url": null,
        "version": null,
        "year": 2021,
        "contributor": null,
        "date_created": "2021-10-09 14:34:09.838583"
    },
    "licenses": [
        {
            "url": null,
            "id": 0,
            "name": null
        }
    ],
    "images": [
        {
            "license": 0,
            "url": null,
            "file_name": "JPEGImages\\000593-1-202102020641225190-0000000.jpg",
            "height": 2048,
            "width": 2448,
            "date_captured": null,
            "id": 0
        },
        {...
        }
    ],
    "type": "instances",
    "annotations": [
        {
            "id": 0,
            "image_id": 0,
            "category_id": 1,
            "segmentation": [
                [
                    384.23809523809524,
                    759.7142857142858,
                    684.2380952380953,
                    721.6190476190477,
                    569.952380952381,
                    935.9047619047619,
                    398.5238095238095,
                    1059.7142857142858,
                    236.61904761904762,
                    997.8095238095239,
                    327.09523809523813,
                    764.4761904761906
                ]
            ],
            "area": 87050.0,
            "bbox": [
                236.0,
                721.0,
                449.0,
                339.0
            ],
            "iscrowd": 0
        },
        {...
        },
        {...
        }
    ],
    "categories": [
        {
            "supercategory": null,
            "id": 0,
            "name": "_background_"
        },
        {
            "supercategory": null,
            "id": 1,
            "name": "classname1"
        },
        {
            "supercategory": null,
            "id": 2,
            "name": "classname2"
        }
    ]
}
images字段是一个存放每个图片的基本信息的列表,每个图片为列表的一项,其中的id是图片索引;
annotations字段是一个存放目标的列表,每个目标为列表的一项,其中的id是目标索引;因为一张图片可能有多个目标,所以通过image_id来对应images字段中的id;category_id是类别索引,在上面的labels.txt文件中第一行的__ignore__的索引为-1,依次递增;segmentation字段是一个存放标注范围的列表,一般只有一项,如果一个目标分为多块,则会有多项,(参考下面第1点)每一项的点分别按照xyxyxy排列;bbox字段为xywh
categories字段是类别名字与id的对应关系,也就是annotations字段中的category_id
其他
- 如果一个目标被其他目标遮挡或截断为多个部分,可以参考data_annotated/2011_000006.json中沙发的标注方式,为每个部分增加
group id 

- 如果有需要忽略的,可以参考data_annotated/2011_000003.json中桌子的标注方式,将不要的目标标注为
__ignore__类别 

额外代码
这部分代码可能不需要使用,但是我实际应用时用到了,有需要可以参考
复制json文件到单独文件夹
如果标注数据时,数据分散在目录下的不同子目录,无法一次性将所有文件全部转换,可以在标注之后将json复制到一个文件夹下,再进行转换,可以参考代码:
以下代码在jupyter中运行
遍历
import os, shutil
BASE_DIR = "标注数据的父目录"
DEST_DIR = "要存放的位置"
    
images = []
annas = []
anna_names = []
for root, dirs, files in os.walk(BASE_DIR, topdown=False):
    for name in files:
        print(os.path.join(root, name))
        if os.path.splitext(name)[1] == '.jpg':  
            images.append(os.path.join(root, name))
        if os.path.splitext(name)[1] == '.json':  
            annas.append(os.path.join(root, name))
            anna_names.append(name)
复制
if os.path.exists(DEST_DIR):
    print("Output directory already exists:", DEST_DIR)
    assert False, "Output directory already exists: %s" % DEST_DIR
os.makedirs(DEST_DIR)
for path, name in zip(annas, anna_names):
    shutil.copyfile(path, os.path.join(DEST_DIR, name))
print("结束")
这样就可以将所有json复制到DEST_DIR中
划分数据集
- 划分训练集和验证集
 - 分别转换训练集和验证集
 
划分数据集
import os, shutil
from sklearn.model_selection import train_test_split
BASE_DIR = r"json存放的文件夹路径"
json_names = os.listdir(BASE_DIR)
json_names = list([name for name in json_names if name.endswith('.json')])
# 分割数据集
X_train, X_test = train_test_split(json_names, test_size=0.3, random_state=42)
# 分别移动到train和val文件夹
for dest_fold in ['train', 'val']:
    DEST_DIR = os.path.join(BASE_DIR, dest_fold)
    if os.path.exists(DEST_DIR):
        print("文件夹已存在:", DEST_DIR)
        assert False, "文件夹已存在:%s" % DEST_DIR
    os.makedirs(DEST_DIR)
    
    if dest_fold == 'train':
        names = X_train
    elif dest_fold == 'val':
        names = X_test
    else:
        assert False, dest_fold
        
    for name in names:
        src = os.path.join(BASE_DIR, name)
        dest = os.path.join(DEST_DIR, name)
        shutil.move(src, dest)
    print("结束")
分别转换训练集和验证集
python .\examples\instance_segmentation\labelme2coco.py \path\to\train \path\to\train --labels \path\to\labels.txt
python .\examples\instance_segmentation\labelme2coco.py \path\to\val \path\to\val --labels \path\to\labels.txt
版权声明:本文为CSDN博主「ayiya_Oese」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ayiya_Oese/article/details/120671641
![]()

	  	
暂无评论