手把手实战教学!语义分割从0到1:一、数据集制作

2023-11-01

本篇博客,是《手把手实战教学!语义分割从0到1》系列的第一篇实战教学,将重点介绍语义分割相关数据集,以及如何制作自己的数据集。

本系列总的介绍,以及其他章节的汇总,见:https://blog.csdn.net/oYeZhou/article/details/115123589

目录

1、公开数据集

2、制作自己的语义分割数据集

2.1、准备标注工具

2.2、准备待标注的原始数据

2.3、开始标注

2.4、标注界面

2.5、转为VOC格式

3、写在后面


1、公开数据集

常用的语义分割数据集有COCO、VOC、Cityscapes、ADE20K等,作为入门,建议从VOC和COCO开始了解,而大多数开源框架也会支持这两种数据集。

由于数据集下载通常比较困难,我就把这两种常用的数据集放到了百度网盘,这里放出VOC和COCO数据集的百度网盘链接:

VOC2012:

链接:https://pan.baidu.com/s/1v6xZ7CQZjdgeHlPcfcKDrg 
提取码:gf3h 

COCO2017: 链接:https://pan.baidu.com/s/1Yii91h2GKBwTVgHYPJg8Mg 
提取码:bku9 

 

 

 

 

2、制作自己的语义分割数据集

2.1、准备标注工具

这里需要用到一个标注工具:labelme,该工具的安装可以参考:https://github.com/wkentaro/labelme

在Python虚拟环境中,可以用pip直接安装:

pip install labelme

安装成功后,通过一下命令查看帮助:

labelme -h

显示如下内容表示安装成功:

usage: labelme [-h] [--version] [--reset-config]
               [--logger-level {debug,info,warning,fatal,error}]
               [--output OUTPUT] [--config CONFIG] [--nodata] [--autosave]
               [--nosortlabels] [--flags FLAGS] [--labelflags LABEL_FLAGS]
               [--labels LABELS] [--validatelabel {exact}] [--keep-prev]
               [--epsilon EPSILON]
               [filename]

positional arguments:
  filename              image or label filename

optional arguments:
  -h, --help            show this help message and exit
  --version, -V         show version
  --reset-config        reset qt config
  --logger-level {debug,info,warning,fatal,error}
                        logger level
  --output OUTPUT, -O OUTPUT, -o OUTPUT
                        output file or directory (if it ends with .json it is
                        recognized as file, else as directory)
  --config CONFIG       config file or yaml-format string (default:
                        C:\Users\Administrator\.labelmerc)
  --nodata              stop storing image data to JSON file
  --autosave            auto save
  --nosortlabels        stop sorting labels
  --flags FLAGS         comma separated list of flags OR file containing flags
  --labelflags LABEL_FLAGS
                        yaml string of label specific flags OR file containing
                        json string of label specific flags (ex. {person-\d+:
                        [male, tall], dog-\d+: [black, brown, white], .*:
                        [occluded]})
  --labels LABELS       comma separated list of labels OR file containing
                        labels
  --validatelabel {exact}
                        label validation types
  --keep-prev           keep annotation of previous frame
  --epsilon EPSILON     epsilon to find nearest vertex on canvas

2.2、准备待标注的原始数据

原始数据应当是图片格式,建议放在一个统一的文件夹中,如名为“imgs”的文件夹;然后,建议新建一个文件夹用于存放各个图片对应的label,也即json文件;最后,应当新建一个TXT文档(labels.txt)用于指明标注的类别。

最终的目录形如:

图1、数据存放目录

其中,labels.txt中的内容形如:

__ignore__
_background_
classA
classB
classC

前两项是必须的,后面几项根据你的类别来设定,有几类就写明几类。labels.txt提前设定好的目的,是为了在标注时让工具已经知道有这些类别,我们只需选择就完了。

2.3、开始标注

先进入到图1所示的目录下:

cd path/to/root_path_of_dataset

然后,启动labelme进行标注(各参数含义参见2.1节展示的帮助):

labelme imgs --output jsons --nodata --autosave --labels labels.txt

接着就是一张一张的标注了:按Ctrl+N,然后逐点勾勒出目标的轮廓,形成一个闭环即为完成一个实例的标注。

每标完一张图片,就会生成一个对应的json文件,其中存放着我们标注的轮廓上各个点的坐标,以及该图片的一些基本信息;该json文件会存放到我们所制定的名为“json”的文件夹中。

2.4、标注界面

标注界面和labelimg类似,如下图:

2.5、转为VOC格式

我们标注完毕后,得到的是一堆json格式文件 ,为了可以像VOC数据集那样每张原图对应一个png格式的mask图片,我们需要对标注完的数据集进行转换,从labelme到VOC。

labelme自带了一个脚本(labelme/examples/semantic_segmentation/labelme2voc.py),可以进行转换:

# It generates:
#   - data_dataset_voc/JPEGImages
#   - data_dataset_voc/SegmentationClass
#   - data_dataset_voc/SegmentationClassVisualization
./labelme2voc.py data_annotated data_dataset_voc --labels labels.txt

不过其生成的目录和VOC稍有差别,我在该脚本基础上简单改了一下,可以生成与VOC一致的目录结构,并可以直接在Pycharm等IDE中直接执行,代码如下:

#!/usr/bin/env python

from __future__ import print_function

import argparse
import glob
import os
import os.path as osp
import sys

import imgviz
import numpy as np
import labelme


def main(args):

    if osp.exists(args.output_dir):
        print("Output directory already exists:", args.output_dir)
        sys.exit(1)
    os.makedirs(args.output_dir)
    os.makedirs(osp.join(args.output_dir, "JPEGImages"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClassnpy"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClass"))
    if not args.noviz:
        os.makedirs(
            osp.join(args.output_dir, "SegmentationClassVisualization")
        )
    print("Creating dataset:", args.output_dir)

    class_names = []
    class_name_to_id = {}
    for i, line in enumerate(open(args.labels).readlines()):
        class_id = i - 1  # starts with -1
        class_name = line.strip()
        class_name_to_id[class_name] = class_id
        if class_id == -1:
            assert class_name == "__ignore__"
            continue
        elif class_id == 0:
            assert class_name == "_background_"
        class_names.append(class_name)
    class_names = tuple(class_names)
    print("class_names:", class_names)
    out_class_names_file = osp.join(args.output_dir, "class_names.txt")
    with open(out_class_names_file, "w") as f:
        f.writelines("\n".join(class_names))
    print("Saved class_names:", out_class_names_file)

    for filename in glob.glob(osp.join(args.input_dir, "*.json")):
        print("Generating dataset from:", filename)

        label_file = labelme.LabelFile(filename=filename)

        base = osp.splitext(osp.basename(filename))[0]
        out_img_file = osp.join(args.output_dir, "JPEGImages", base + ".jpg")
        out_lbl_file = osp.join(
            args.output_dir, "SegmentationClassnpy", base + ".npy"
        )
        out_png_file = osp.join(
            args.output_dir, "SegmentationClass", base + ".png"
        )
        if not args.noviz:
            out_viz_file = osp.join(
                args.output_dir,
                "SegmentationClassVisualization",
                base + ".jpg",
            )

        with open(out_img_file, "wb") as f:
            f.write(label_file.imageData)
        img = labelme.utils.img_data_to_arr(label_file.imageData)

        lbl, _ = labelme.utils.shapes_to_label(
            img_shape=img.shape,
            shapes=label_file.shapes,
            label_name_to_value=class_name_to_id,
        )
        labelme.utils.lblsave(out_png_file, lbl)

        np.save(out_lbl_file, lbl)

        if not args.noviz:
            viz = imgviz.label2rgb(
                label=lbl,
#                img=imgviz.rgb2gray(img),
                img=img,
                font_size=15,
                label_names=class_names,
                loc="rb",
            )
            imgviz.io.imsave(out_viz_file, viz)


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--input_dir", default="../edge_fence_20210203/jsons", type=str, help="input annotated directory")
    parser.add_argument("--output_dir", default="../edge_fence_20210203_voc", type=str, help="output dataset directory")
    parser.add_argument("--labels", default="../edge_fence_20210203/labels.txt", type=str, help="labels file")
    parser.add_argument("--noviz", help="no visualization", action="store_true")
    args = parser.parse_args()
    return args


if __name__ == "__main__":
    args = get_args()
    main(args)

利用labelme/examples/semantic_segmentation/labelme2voc.py或者我上面贴出的代码,可以将标注完毕的数据集转化为VOC格式,其目录结构形如:

 其中,JPEGImages中存放的原图,SegmentationClass中存放的是png格式mask,SegmentationClassnpy存放的是numpy格式的mask,SegmentationClassVisualization是将mask叠加到原图得到的可视化结果,class_names.txt中存放的是类别名(包括背景和各个类)。

3、写在后面

至此,就完成了语义分割数据集的制作,然后,我们就可以利用这个转化后的数据集进行语义分割模型的训练了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手实战教学!语义分割从0到1:一、数据集制作 的相关文章

随机推荐

  • Fabric加密算法

    BCCSP Blockchain crypto provider 即区块链加密提供商 用于定义选择使用的密码学实现库 负责摘要生成 非对称密钥的签名与验证 根据证书查找私钥等 该模块提供了一系列的接口 这些接口定义了摘要的生成方法 签名 验
  • 负载均衡之Keepalived

    严格意义来说 Keepalived主要是通过虚拟路由冗余来实现高可用功能 但是其也可以借助IPVS实现负载均衡 所以也简要的学习了一下 简介 起初是设计来监控集群中各个节点的状态 根据TCP IP模型中网络层 ICMP控制消息请求 传输层
  • QFileInfo

    一 描述 QFileInfo 提供有关文件系统中文件的名称和位置 路径 访问权限 文件类型等信息 FileInfo 还可用于获取有关 Qt 资源的信息 这个类是隐式共享的 二 成员函数 2 1 判断函数 1 bool isAbsolute
  • python_sqlalchemy

    SQLAlchemy使用和踩坑记 知乎 2 长时间未请求连接自动断开 现象 长时间服务端没有连接数据库 数据库连接自动断开 原因 1 sqlalchemy在create engine时 使用连接池并没有指定连接池回收时间 则连接池的连接不会
  • 交互设计实用指南系列(1) – 操作入口明确

    链接 http ued taobao org blog 2009 12 the practice guidelines of interaction design clear operational entrance of effectiv
  • 微软 AD 已成过去式,这个身份领域国产化替代方案你了解吗?

    随着全球互联网和数字化浪潮的不断发展 信息安全已成为不可忽视的问题 并随着日益复杂的国内外市场格局 其重要性更加凸显 我国政府也相继印发和实施了 数字中国建设整体布局规划 全国一体化大数据体系建设指南 等一系列政策 将核心技术自主可控 安全
  • CSS学习————css的选择器(2)

    选择器的作用 用来查找要设置html样式的元素 css的选择器分为4大类 1 简单选择器 6种 1 1 通配符选择器 1 2 标签选择器 1 3 id选择器 1 4 属性选择器 1 5 类选择器 1 6 分组选择器
  • Mac OS X下Android系统华为手机无法连接问题之解决方案

    一般的android连接mac 很方便不用安装驱动就可以啦 可是不知道为什么特殊情况下有的android手机 小米2 华为等 就是连接不上 下来就说说特殊情况下如何连接 使用USB连接安卓手机后可以做2件事情 关于本机 gt 更多信息 gt
  • 模板的显示实例化与显示具体化

    显式实例化 C 中模板函数 类 的调用与定义分离时 需要使用显式实例化 否则就会出现链接错误 编译器对各个cpp分别编译的时候 模板函数必须被实例化编译 如果我们把调用与定义写在一个文件 在调用语句处有int a b cmp a b 那么编
  • UVM的phase机制(Ⅰ)

    uvm存在phase机制 每个phase完成对应的功能 将所有的程序分解在不同的phase中执行 保证了验证环境的验证代码的执行顺序 并且每个phase完成对应的功能 使验证环境运行仿真层次化 让各种组件的例化次序正确 环境的执行顺序正确
  • 万字长文分享,如何自学Java(方法+步骤)

    目录 收起 大家存在的问题 为什么我觉得方法很重要 五个步骤学习Java 第一阶段 揽全局 怎么办 你需要的是系统化学习 教程式笔记 我的大学 我准备从思想方法和具体的学习步骤上给大家聊一下我的做法 希望对大家有所帮助 看完本篇文章你会得到
  • C语言-商品销售管理系统

    C语言 商品销售管理系统 全部代码如下 include
  • jsp中的stl标签库

    catch标签 forEach标签 remove标签 param标签 set标签 url标签
  • ZooKeeper安装后无法启动JAVA_HOME is not set and java could not be found in PATH.

    JAVA HOME is not set and java could not be found in PATH 在安装后使用命令 zkServer sh start启动出现JAVA HOME找不到的提示 去查看 etc profile文件
  • Java网络编程相关知识

    网络编程 1 在网络通信协议下 不同 计算机上运行的程序 进行的数据传输 2 应用场景 即时通信 网游对战 金融证券 国际贸易 邮件等等 3 Java中可以使用java net包下的技术开发出常见的网络应用程序 4 常见的软件架构有CS和B
  • UE4_蓝图调试器

    蓝图调试器 在蓝图调式器里可以看到所有的断点和 watch this value 的值 下面这幅图可以取消所有的断点和watch this value 节点注释
  • opencv 直方图 CV::calcHist使用

    本文转自 http www xuebuyuan com 1014703 html 特别提醒读者 注意实例中数据成员很多都定义成数据 这是由于calcHist函数形参要求的 直方图在图形处理中很常用 直方图可以统计图像的像素特征分布 用于修改
  • jdk1.8 下 list stream转数组 map 循环 过滤等操作的常见写法

    Jdk1 8中 对于 list 有非常多的快捷操作方便我们处理数据 比如 list 转 map 对象操作 在开发过程我们有时会在for循环过程中查询另一个表的数据 我们可以提前把数据查询出来 转换成map 使用过程中通过map获取数据 避免
  • vue 3 第二十六章:样式(scoped、深度选择器、全局选择器、css modules、自定义注入名称、css中v-bind)

    文章目录 1 介绍 2 基本使用 3 scoped原理 4 深度选择器 5 插槽选择器 6 全局选择器 7 混合使用局部与全局样式 8 CSS Modules 9 自定义注入名称 10 CSS 中的 v bind 1 介绍 在 Vue 中
  • 手把手实战教学!语义分割从0到1:一、数据集制作

    本篇博客 是 手把手实战教学 语义分割从0到1 系列的第一篇实战教学 将重点介绍语义分割相关数据集 以及如何制作自己的数据集 本系列总的介绍 以及其他章节的汇总 见 https blog csdn net oYeZhou article d