labelme标注数据转mask(用于mmsegmentation)

news2024/10/21 5:13:54

mmsegmentation原本支持的数据格式主要有以下几种:

mmsegmentation
├── mmseg
├── tools
├── configs
├── data
│   ├── cityscapes
│   │   ├── leftImg8bit
│   │   │   ├── train
│   │   │   ├── val
│   │   ├── gtFine
│   │   │   ├── train
│   │   │   ├── val
│   ├── VOCdevkit
│   │   ├── VOC2012
│   │   │   ├── JPEGImages
│   │   │   ├── SegmentationClass
│   │   │   ├── ImageSets
│   │   │   │   ├── Segmentation
│   │   ├── VOC2010
│   │   │   ├── JPEGImages
│   │   │   ├── SegmentationClassContext
│   │   │   ├── ImageSets
│   │   │   │   ├── SegmentationContext
│   │   │   │   │   ├── train.txt
│   │   │   │   │   ├── val.txt
│   │   │   ├── trainval_merged.json
│   │   ├── VOCaug
│   │   │   ├── dataset
│   │   │   │   ├── cls
│   ├── ade
│   │   ├── ADEChallengeData2016
│   │   │   ├── annotations
│   │   │   │   ├── training
│   │   │   │   ├── validation
│   │   │   ├── images
│   │   │   │   ├── training
│   │   │   │   ├── validation
│   ├── coco_stuff10k
│   │   ├── images
│   │   │   ├── train2014
│   │   │   ├── test2014
│   │   ├── annotations
│   │   │   ├── train2014
│   │   │   ├── test2014
│   │   ├── imagesLists
│   │   │   ├── train.txt
│   │   │   ├── test.txt
│   │   │   ├── all.txt
│   ├── coco_stuff164k
│   │   ├── images
│   │   │   ├── train2017
│   │   │   ├── val2017
│   │   ├── annotations
│   │   │   ├── train2017
│   │   │   ├── val2017
│   ├── CHASE_DB1
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation
│   ├── DRIVE
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation
│   ├── HRF
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation
│   ├── STARE
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation
|   ├── dark_zurich
|   │   ├── gps
|   │   │   ├── val
|   │   │   └── val_ref
|   │   ├── gt
|   │   │   └── val
|   │   ├── LICENSE.txt
|   │   ├── lists_file_names
|   │   │   ├── val_filenames.txt
|   │   │   └── val_ref_filenames.txt
|   │   ├── README.md
|   │   └── rgb_anon
||   ├── val
||   └── val_ref
|   ├── NighttimeDrivingTest
|   |   ├── gtCoarse_daytime_trainvaltest
|   |   │   └── test
|   |   │       └── night
|   |   └── leftImg8bit
|   |   |   └── test
|   |   |       └── night
│   ├── loveDA
│   │   ├── img_dir
│   │   │   ├── train
│   │   │   ├── val
│   │   │   ├── test
│   │   ├── ann_dir
│   │   │   ├── train
│   │   │   ├── val
│   ├── potsdam
│   │   ├── img_dir
│   │   │   ├── train
│   │   │   ├── val
│   │   ├── ann_dir
│   │   │   ├── train
│   │   │   ├── val
│   ├── vaihingen
│   │   ├── img_dir
│   │   │   ├── train
│   │   │   ├── val
│   │   ├── ann_dir
│   │   │   ├── train
│   │   │   ├── val
│   ├── iSAID
│   │   ├── img_dir
│   │   │   ├── train
│   │   │   ├── val
│   │   │   ├── test
│   │   ├── ann_dir
│   │   │   ├── train
│   │   │   ├── val
│   ├── synapse
│   │   ├── img_dir
│   │   │   ├── train
│   │   │   ├── val
│   │   ├── ann_dir
│   │   │   ├── train
│   │   │   ├── val
│   ├── REFUGE
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   │   ├── test
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation
│   │   │   ├── test
│   ├── mapillary
│   │   ├── training
│   │   │   ├── images
│   │   │   ├── v1.2
|   │   │   │   ├── instances
|   │   │   │   ├── labels
|   │   │   │   └── panoptic
│   │   │   ├── v2.0
|   │   │   │   ├── instances
|   │   │   │   ├── labels
|   │   │   │   ├── panoptic
|   │   │   │   └── polygons
│   │   ├── validation
│   │   │   ├── images
|   │   │   ├── v1.2
|   │   │   │   ├── instances
|   │   │   │   ├── labels
|   │   │   │   └── panoptic
│   │   │   ├── v2.0
|   │   │   │   ├── instances
|   │   │   │   ├── labels
|   │   │   │   ├── panoptic
|   │   │   │   └── polygons
│   ├── bdd100k
│   │   ├── images
│   │   │   └── 10k
|   │   │   │   ├── test
|   │   │   │   ├── train
|   │   │   │   └── val
│   │   └── labels
│   │   │   └── sem_seg
|   │   │   │   ├── colormaps
|   │   │   │   │   ├──train
|   │   │   │   │   └──val
|   │   │   │   ├── masks
|   │   │   │   │   ├──train
|   │   │   │   │   └──val
|   │   │   │   ├── polygons
|   │   │   │   │   ├──sem_seg_train.json
|   │   │   │   │   └──sem_seg_val.json
|   │   │   │   └── rles
|   │   │   │   │   ├──sem_seg_train.json
|   │   │   │   │   └──sem_seg_val.json
│   ├── nyu
│   │   ├── images
│   │   │   ├── train
│   │   │   ├── test
│   │   ├── annotations
│   │   │   ├── train
│   │   │   ├── test
│   ├── HSIDrive20
│   │   ├── images
│   │   │   ├── train
│   │   │   ├── validation
│   │   │   ├── test
│   │   ├── annotations
│   │   │   ├── train
│   │   │   ├── validation
│   │   │   ├── test

labelme标注得到的数据是jpg(或者png)、json混合在一个文件夹里的。如果用于语义分割,通常需要将json数据转为mask图像。mmseg支持的数据集类型比较多,对应的也有自己的数据集结构。对此,我选择的是按照DRIVE,CHASE-DB1这些数据的格式来做的,即:

│   ├── DRIVE
│   │   ├── images
│   │   │   ├── training
│   │   │   ├── validation
│   │   ├── annotations
│   │   │   ├── training
│   │   │   ├── validation

代码参考了https://github.com/TommyZihao/Label2Everything/tree/main/labelme2mask,
整体代码如下:

import os
import json
import numpy as np
import cv2
import glob
import shutil
from tqdm import tqdm
from sklearn.model_selection import train_test_split


def labelme2mask_single_img(img_path, labelme_json_path):
    '''
    输入原始图像路径和labelme标注路径,输出 mask
    '''

    img_bgr = cv2.imread(img_path)
    # 创建空白图像 0-背景
    img_mask = np.zeros(img_bgr.shape[:2])

    with open(labelme_json_path, 'r', encoding='utf-8') as f:
        labelme = json.load(f)

    # 按顺序遍历每一个类别
    for one_class in class_info:
        # 遍历所有标注,找到属于当前类别的标注
        for each in labelme['shapes']:
            if each['label'] == one_class['label']:
                # polygon 多段线标注
                if one_class['type'] == 'polygon':
                    # 获取点的坐标
                    points = [np.array(each['points'], dtype=np.int32).reshape((-1, 1, 2))]
                    # 在空白图上画 mask(闭合区域)
                    img_mask = cv2.fillPoly(img_mask, points, color=one_class['color'])

                # line 或者 linestrip 线段标注
                elif one_class['type'] == 'line' or one_class['type'] == 'linestrip':
                    # 获取点的坐标
                    points = [np.array(each['points'], dtype=np.int32).reshape((-1, 1, 2))]
                    # 在空白图上画 mask(非闭合区域)
                    img_mask = cv2.polylines(img_mask, points, isClosed=False, color=one_class['color'],
                                             thickness=one_class['thickness'])

                # circle 圆形标注
                elif one_class['type'] == 'circle':
                    points = np.array(each['points'], dtype=np.int32)
                    center_x, center_y = points[0][0], points[0][1]  # 圆心点坐标
                    edge_x, edge_y = points[1][0], points[1][1]  # 圆周点坐标
                    radius = np.linalg.norm(np.array([center_x, center_y] - np.array([edge_x, edge_y]))).astype(
                        'uint32')  # 半径
                    img_mask = cv2.circle(img_mask, (center_x, center_y), radius, one_class['color'],
                                          one_class['thickness'])

                else:
                    print('未知标注类型', one_class['type'])

    return img_mask


if __name__ == '__main__':
    #  1.label设置:
    # 根据根据json文件中的shape情况,分别设置每个label的名称、类型、以及颜色,其中颜色要从1开始编号,因为背景为0
    class_info = [
        {'label': 'space', 'type': 'polygon', 'color': 1},  # polygon 多段线
        # {'label': 'condyl', 'type': 'polygon', 'color': 1},
        # {'label': 'fossa', 'type': 'polygon', 'color': 3},
        # {'label': 'bone marrow', 'type': 'polygon', 'color': 4},
        # {'label':'clock', 'type':'circle', 'color':11, 'thickness':-1},   # circle 圆形,-1表示填充
        # {'label':'lane', 'type':'line', 'color':12, 'thickness':5},       # line 两点线段,填充线宽
        # {'label':'sign', 'type':'linestrip', 'color':13, 'thickness':3}   # linestrip 多段线,填充线宽
    ]

    #  2.路径设置:
    # labelme文件路径
    labelme_path = r"F:\Data\doctor_research\Arthritis"
    # 储存文件路径,这边准备采用的是chase_db1的数据格式,为了减少代码修改量,我直接命名为CHASE_DB1
    saved_path = r"F:\Data\doctor_research\DRIVE_space"
    if not os.path.exists(saved_path):
        os.makedirs(saved_path)


    # 1.images文件路径:
    ## images路径:
    img_path = os.path.join(saved_path, 'images')
    ## training images路径:
    train_img_path = os.path.join(img_path, 'training')
    ## validation images路径:
    val_img_path = os.path.join(img_path, 'validation')

    # 创建文件夹
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    if not os.path.exists(train_img_path):
        os.makedirs(train_img_path)
    if not os.path.exists(val_img_path):
        os.makedirs(val_img_path)

    # 2.mask文件路径
    ## mask路径:
    mask_path = os.path.join(saved_path, 'annotations')
    ## training mask路径:
    train_annotation_path = os.path.join(mask_path, 'training')
    ## validation mask路径:
    val_annotation_path = os.path.join(mask_path, 'validation')
    print('reading...')

    #  创建文件夹
    if not os.path.exists(mask_path):
        os.makedirs(mask_path)
    if not os.path.exists(train_annotation_path):
        os.makedirs(train_annotation_path)
    if not os.path.exists(val_annotation_path):
        os.makedirs(val_annotation_path)

    # 获取images目录下所有的json文件列表
    json_list_path = glob.glob(labelme_path + "/*.json")
    print('数据集总量为:', len(json_list_path))

    # 划分训练集和验证集
    # 验证集和训练集比例为1:9,可以根据自己需要更改
    train_path, val_path = train_test_split(json_list_path, test_size=0.1, train_size=0.9)
    print("训练集数据量为:", len(train_path), '验证集数据量为:', len(val_path))

    # 依次对两个数据集进行转换:
    # 对训练集进行转换:
    for train_json in tqdm(train_path):
        try:
            # 1.将训练图像复制到images/training
            # 获取对应的图像文件地址
            train_img = os.path.join(train_json.split('.')[0] + '.png')

            # 分离文件名与路径
            path_1, img_name_1 = os.path.split(train_img)
            # 复制到新的文件夹
            tmp_img_path_1 = os.path.join(train_img_path, img_name_1)
            shutil.copy(train_img, tmp_img_path_1)

            # 2.将json文件转为mask图像
            train_img_mask = labelme2mask_single_img(train_img, train_json)
            # 将mask文件保存到annotations/training
            tmp_mask_path_1 = os.path.join(train_annotation_path, img_name_1)
            cv2.imwrite(tmp_mask_path_1, train_img_mask)

        except Exception as E:
            print(train_json, '转换失败', E)

    # 对测试集进行转换:
    for val_json in tqdm(val_path):
        try:
            # 1.将测试集图像复制到images/validation
            # 获取对应的图像文件地址
            val_img = os.path.join(val_json.split('.')[0] + '.png')

            # 分离文件名与路径
            path_2, img_name_2 = os.path.split(val_img)
            # 复制到新的文件夹
            tmp_img_path_2 = os.path.join(val_img_path, img_name_2)
            shutil.copy(val_img, tmp_img_path_2)

            # 2.将json文件转为mask图像
            val_img_mask = labelme2mask_single_img(val_img, val_json)
            # 将mask文件保存到annotations/validation
            tmp_mask_path_2 = os.path.join(val_annotation_path, img_name_2)
            cv2.imwrite(tmp_mask_path_2, val_img_mask)

        except Exception as E:
            print(val_json, '转换失败', E)

这边需要修改的就是路径以及class_info。具体怎么使用mmseg训练自己的数据集,我另外一篇blog提到了。这里简单提一下,主要是修改几个地方:

1.修改num_classes

这个在config/base/models里找到自己想用的那个模型修改就好。要记得把自己的类别数量加1,因为背景也算1类。

2.修改路径

这个在config/base/datasets,找到自己想用的数据集格式,比如DRIVE,就在drive.py里面,改一下路径。

3.修改label种类

在mmseg/datasets中对应的数据集格式里:

class DRIVEDataset(BaseSegDataset):
    """DRIVE dataset.

    In segmentation map annotation for DRIVE, 0 stands for background, which is
    included in 2 categories. ``reduce_zero_label`` is fixed to False. The
    ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to
    '_manual1.png'.
    """
    METAINFO = dict(
        classes=('background', 'space'),
        palette=[[120, 120, 120], [6, 230, 230]])

    def __init__(self,
                 img_suffix='.png',
                 # seg_map_suffix='_manual1.png',
                 seg_map_suffix='.png',
                 reduce_zero_label=False,
                 **kwargs) -> None:
        super().__init__(
            img_suffix=img_suffix,
            seg_map_suffix=seg_map_suffix,
            reduce_zero_label=reduce_zero_label,
            **kwargs)
        assert fileio.exists(
            self.data_prefix['img_path'], backend_args=self.backend_args)

需要修改的有3处:
1.classes,把自己的label加上去就行
2.palette,对应label的颜色,别重复就行
3.seg_map_suffix,这个要注意改一下,是各个数据集自己用来识别是否为mask的一个文件拓展名,嫌麻烦就删掉了

4.修改训练参数

这方面看个人需求,主要在config/base/default_runtime.py和config/base/schedules/schedule_40k.py里修改,我主要是改一下学习率和迭代次数。单卡训练的话,0.01的学习率有点大,我一般改为0.0025,迭代次数从文件名就可以看出来,40K就是40000次,注意,这里是iteration,不是epoch。

目前就想到这么多,有什么不懂的可以问,后续我想起来也会继续更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

asyn驱动示例-int32driver

驱动程序源代码int32Driver.c&#xff1a; #include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <ctype.h>#include <cantProceed.h> #include <epicsStdio.h> #i…

官龙村捐赠图书整理有感

今天&#xff08;2024年10月20日&#xff09;&#xff0c;我有幸参加了在深圳南山区西丽官龙村举行的义工活动&#xff0c;主要任务是整理捐赠的图书&#xff0c;并根据小学和中学的需求进行分类打包。这次活动不仅让我体会到了劳动的辛苦&#xff0c;更让我感受到了助人为乐的…

【AIGC】第一性原理下的ChatGPT提示词Prompt设计:系统信息与用户信息的深度融合

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;第一性原理与ChatGPT提示词Prompt设计应用第一性原理于ChatGPT提示词Prompt设计系统信息和用户信息的融合实际应用结论 &#x1f4af;系统信息与用户信息的定义和重要性系…

鸿蒙中富文本编辑与展示

富文本在鸿蒙系统如何展示和编辑的&#xff1f;在文章开头我们提出这个疑问&#xff0c;带着疑问来阅读这篇文章。 富文本用途可以展示图文混排的内容&#xff0c;在日常App 中非常常见&#xff0c;比如微博的发布与展示&#xff0c;朋友圈的发布与展示&#xff0c;都在使用富文…

C++高阶:红黑树实现

目录 一.红黑树的概念 1.1红黑树的规则 1.2红黑树的效率 二.红黑树的实现 2.1红黑树的结构 2.2红黑树的插入 2.2.1插入的大致过程 2.2.2情况一&#xff1a;变色 ​编辑 2.2.3情况二&#xff1a;单旋变色 2.2.4情况三&#xff1a;双旋变色 2.3插入代码实现 2.4红黑树的…

【网络安全】简单P1:通过开发者工具解锁专业版和企业版功能

未经许可,不得转载。 文章目录 前言发现过程前言 在探索一个SaaS平台的过程中,我发现了一个漏洞,使得我能够在无需订阅的情况下解锁高级(专业/企业)功能。 发现过程 我使用一个没有任何高级功能的基本用户账户进行常规登录。在浏览平台时,我注意到某些按钮和功能上带有…

【C++STL】list的基本介绍与使用方式

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山冈&#xff01; &#x1f525; 所属专栏&#xff1a;C深入学习笔记 &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 一、list的介绍 文档内容以及大致翻…

ROS笔记之kill掉所有ros节点rosnode

ROS笔记之kill掉所有ros节点rosnode 文章目录 ROS笔记之kill掉所有ros节点rosnode1. 杀死所有 ROS 节点&#xff08;不包括 rosmaster&#xff09;2. 杀死 rosmaster3. 验证所有节点和 rosmaster 是否已终止4. roscore 和 rosmaster 是同一个概念吗&#xff1f;5. 为什么执行 k…

【踩坑日记36】ModuleNotFoundError: No module named ‘taming‘

问题描述 ModuleNotFoundError: No module named ‘taming‘问题分析 未正确安装taming-transformers包 问题解决 从github网站中安装taming-transformers包&#xff1a; 从github网站中下载taming-transformers代码 git clone https://github.com/CompVis/taming-transfo…

微机原理与接口技术知识点总结——绪论

1.1、计算机发展概述 早期计算机的用途主要是用于算数&#xff0c;一直到20世纪电子领域基础研究的突破&#xff0c;也就是电子计算机的诞生&#xff0c;计算机才变得如此广泛。以微电子技术为基础制造的电子计算机已经完全取代了机械计算机和机电计算机&#xff0c;因此电子计…

第二十二届GOPS全球运维大会2024一日感

第二十二届GOPS全球运维大会将于2024年4月25-26日在南山区深圳湾万丽酒店召开。大会将为期2天&#xff0c;侧重大模型、AIOps、DevOps、可观测、SRE、云原生等热门技术领域。 GOPS是我一直关注的一场技术峰会&#xff0c;主要是它的侧重点在运维方面&#xff0c;这和我本身的职…

【C++干货篇】——类和对象的魅力(二)

【C干货篇】——类和对象的魅力&#xff08;二&#xff09; 1.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。 ⼀个类&#xff0c;我们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的…

从 Microsoft 官网下载 Windows 10

方法一&#xff1a; 打开 Microsoft 官网&#xff1a; 打开开发人员工具&#xff08;按 F12 或右键点击“检查”&#xff09;。 点击“电脑模拟手机”按钮&#xff0c;即下图&#xff1a; 点击后重新加载此网页&#xff0c;即可看到下载选项。

[k8s理论知识]3.docker基础(二)隔离技术

容器其实是一种沙盒技术&#xff0c;其核心是通过约束和修改进程的动态表现&#xff0c;为其创建一个边界。这个边界确保了应用与应用之间不会相互干扰&#xff0c;同时可以方便在不同的环境中迁移&#xff0c;这是PaaS最理想的状态。 程序是代码的可执行镜像&#xff0c;通常…

springboot项目get请求遇到:Message Request header is too large报错。

一、错误日志 HTTP Status 400 – Bad Request Type Exception ReportMessage Request header is too largeDescription The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, inva…

Django学习-ORM_常用字段及字段选项

字段选项&#xff1a; 注意&#xff1a;当我们新增数据的时候&#xff0c;如果没有新增设置了default的字段&#xff0c;此时会使用default设置的默认值填充到新增的数据中

数字后端零基础入门系列 | Innovus零基础LAB学习Day2

今天开始更新数字IC后端设计实现中Innovus零基础Lab学习后续内容。 数字后端零基础入门系列 | Innovus零基础LAB学习Day1 ####LAB5-2 这个章节的目标也很明确——学习掌握工具的一些常用快捷键。 这里只需要掌握以下几个快捷键即可。其他小编我也不会&#xff0c;也用不着。…

【初识数据库】

目录 一、数据库简介 1.什么是数据库 2.数据库与数据结构有啥关系 3.为什么要使用数据库 二、数据库服务器、数据库和表的关系 三、客户端与服务器的通讯方式 1.C/S架构 2.B/S架构 3.命令提示符 4.MySQL架构 一、数据库简介 1.什么是数据库 组织和保存数据的应用程序…

【JavaEE初阶】深入理解网络编程—使用UDP协议API实现回显服务器

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…

centors7安装docker启动ubuntu

在centors上升级glibc为2.18&#xff0c;使用yum最新源直接安装不行&#xff0c;使用源码安装还不行&#xff0c;因为必须使用2.18版本glic&#xff0c;采用先安装docker&#xff0c;在启动新的Ubuntu&#xff0c;在ubuntu里配置自己的环境 1. centors安装docker 查看docker的…