当前位置: 首页 > article >正文

科普之使用Lableme图像标注—盲道分割与目标检测

使用Lableme图像标注—盲道分割与目标检测

数据集格式

在介绍使用Lableme软件进行数据集的标注之前,首先先对计算机视觉领域最知名的两个数据集的格式来进行简单的复习或者说是重新的学习。

在读研之后自己最常用的几个数据集进行存在在磁盘中跑代码的时候在拿出来使用。VOC2012 COCO2017和MOT17等数据集,在标注数据的时候还是先介绍一下目前一些成熟的数据集结构。也就是voc和coco的结构

VOC数据集

我自己之前做目标检测的时候使用的是Pascal VOC2012的数据集。

官网地址:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/

在这里插入图片描述
PASCAL VOC挑战赛 (The PASCAL Visual Object Classes )是一个世界级的计算机视觉挑战赛,PASCAL全称:Pattern Analysis, Statical Modeling and Computational Learning,是一个由欧盟资助的网络组织。PASCAL VOC挑战赛主要包括以下几类:图像分类(Object Classification),目标检测(Object Detection),目标分割(Object Segmentation),行为识别(Action Classification) 等。

因为标注的盲道分割的任务属于是计算机视觉中的分割任务。我只对这个任务进行一定的说明

  • 分割任务,注意,图像分割一般包括语义分割实例分割全景分割,实例分割是要把每个单独的目标用一种颜色表示(下图中间的图像),而语义分割只是把同一类别的所有目标用同一颜色表示(下图右侧的图片)

在这里插入图片描述

在Pascal VOC数据集中主要包含20个目标类别(目标检测的时候对这20个目标进行检测

{
	"background": 0,
    "aeroplane": 1,
    "bicycle": 2,
    "bird": 3,
    "boat": 4,
    "bottle": 5,
    "bus": 6,
    "car": 7,
    "cat": 8,
    "chair": 9,
    "cow": 10,
    "diningtable": 11,
    "dog": 12,
    "horse": 13,
    "motorbike": 14,
    "person": 15,
    "pottedplant": 16,
    "sheep": 17,
    "sofa": 18,
    "train": 19,
    "tvmonitor": 20
}

将VOC2011解压之后就可以看VOC数据集的完整结构了。 自己使用的VOC2011数据集是经过后期一部分删减的数据集

在这里插入图片描述

VOCdevkit
    └── VOC2012
         ├── Annotations               所有的图像标注信息(XML文件)
         ├── ImageSets    
         │   ├── Action                人的行为动作图像信息
         │   ├── Layout                人的各个部位图像信息
         │   │
         │   ├── Main                  目标检测分类图像信息
         │   │     ├── train.txt       训练集(5717)
         │   │     ├── val.txt         验证集(5823)
         │   │     └── trainval.txt    训练集+验证集(11540)
         │   │
         │   └── Segmentation          目标分割图像信息
         │         ├── train.txt       训练集(1464)
         │         ├── val.txt         验证集(1449)
         │         └── trainval.txt    训练集+验证集(2913)
         │ 
         ├── JPEGImages                所有图像文件
         ├── SegmentationClass         语义分割png图(基于类别)
         └── SegmentationObject        实例分割png图(基于目标)

注意,train.txt、val.txt和trainval.txt文件里记录的是对应标注文件的索引,每一行对应一个索引信息。如下图所示。

在这里插入图片描述

目标检测任务使用实例

  • 首先在Main文件中,读取对应的txt文件(注意,在Main文件夹里除了train.txt、val.txt和trainval.txt文件外,还有针对每个类别的文件,例如bus_train.txt、bus_val.txt和bus_trainval.txt)。比如使用train.txt中的数据进行训练,那么读取该txt文件,解析每一行。上面说了每一行对应一个标签文件的索引。
   ├── Main                  目标检测分类图像信息
   │     ├── train.txt       训练集(5717)
   │     ├── val.txt         验证集(5823)
   │     └── trainval.txt    训练集+验证集(11540)

接着通过索引在Annotations文件夹下找到对应的标注文件(.xml)。比如索引为2007_000032,那么在Annotations 文件夹中能够找到2007_000032.xml文件。如下图所示,在标注文件中包含了所有需要的信息。

在这里插入图片描述

接着通过在标注文件中的filename字段在JPEGImages 文件夹中找到对应的图片。比如在2007_000323.xml文件中的filename字段为2007_000323.jpg,那么在JPEGImages 文件夹中能够找到2007_000323.jpg文件。

语义分割任务使用实例

接下来简单介绍下如何使用该数据集中做语义分割的数据。

  └── Segmentation          目标分割图像信息
        ├── train.txt       训练集(1464)
        ├── val.txt         验证集(1449)
        └── trainval.txt    训练集+验证集(2913)
  1. 首先在Segmentarion文件中,读取对应的txt文件。比如使用train.txt中的数据进行训练,那么读取该txt文件,解析每一行,每一行对应一个图像的索引。

  2. 根据索引在JPEGImages文件夹中找到相应的图像(.png)。以2007_000032为例,可以找到2007_000032.png文件。

在这里插入图片描述

  1. 根据索引在SegmentationClass文件夹中找到相应的标注图像(.png)。还是以2007_000323为例,可以找到2007_000323.png文件。

在这里插入图片描述
注意,在语义分割中对应的标注图像(.png)用PIL的Image.open()函数读取时,默认是P模式,即一个单通道的图像。在背景处的像素值为0,目标边缘处用的像素值为255(训练时一般会忽略像素值为255的区域),目标区域内根据目标的类别索引信息进行填充,例如人对应的目标索引是15,所以目标区域的像素值用15填充。

在这里插入图片描述

MS COCO数据集

官网地址:https://cocodataset.org/

简介: MS COCO是一个非常大型且常用的数据集,其中包括了目标检测,分割,图像描述等。其主要特性如下:

  • Object segmentation: 目标级分割
  • Recognition in context: 图像情景识别
  • Superpixel stuff segmentation: 超像素分割
  • 330K images (>200K labeled): 超过33万张图像,标注过的图像超过20万张
  • 1.5 million object instances: 150万个对象实例
  • 80 object categories: 80个目标类别
  • 91 stuff categories: 91个材料类别
  • 5 captions per image: 每张图像有5段情景描述
  • 250,000 people with keypoints: 对25万个人进行了关键点标注.

我自己在做检测的时候使用过coco2017数据集

数据集结构

这里以下载coco2017数据集为例,主要下载三个文件:

  • 2017 Train images [118K/18GB]:训练过程中使用到的所有图像文件
  • 2017 Val images [5K/1GB]:验证过程中使用到的所有图像文件
  • 2017 Train/Val annotations [241MB]:对应训练集和验证集的标注json文件

下载后都解压到coco2017目录下,可以得到如下目录结构:

在这里插入图片描述

├── coco2017: 数据集根目录
     ├── train2017: 所有训练图像文件夹(118287张)
     ├── val2017: 所有验证图像文件夹(5000张)
     └── annotations: 对应标注文件夹
     		  ├── instances_train2017.json: 对应目标检测、分割任务的训练集标注文件
     		  ├── instances_val2017.json: 对应目标检测、分割任务的验证集标注文件
     		  ├── captions_train2017.json: 对应图像描述的训练集标注文件
     		  ├── captions_val2017.json: 对应图像描述的验证集标注文件
     		  ├── person_keypoints_train2017.json: 对应人体关键点检测的训练集标注文件
     		  └── person_keypoints_val2017.json: 对应人体关键点检测的验证集标注文件夹

通过代码读取数据集格式

因为官方的json文件定义为一行,看起来是比较麻烦的。所以使用断点调试结合代码来读取一下数据集的信息。

https://cocodataset.org/#format-data

在这里插入图片描述

import json

json_path = "datasets/coco/annotations/instances_val2017.json"
json_labels = json.load(open(json_path, "r"))
print(json_labels["info"])

在这里插入图片描述

  1. images是一个列表(元素个数对应图像的张数),列表中每个元素都是一个dict,对应一张图片的相关信息。包括对应图像名称、图像宽度、高度等信息。

在这里插入图片描述

  • annotations是一个列表(元素个数对应数据集中所有标注的目标个数,注意不是图像的张数),列表中每个元素都是一个dict对应一个目标的标注信息。包括目标的分割信息(polygons多边形)、目标边界框信息[x,y,width,height](左上角x,y坐标,以及宽高)、目标面积、对应图像id以及类别id等。iscrowd参数只有0或1两种情况,一般0代表单个对象,1代表对象集合。

在这里插入图片描述

对于coco的操作官方提供了一个api来进行实现。

  • Linux系统安装pycocotools:

pip install pycocotools

Windows系统安装pycocotools:

pip install pycocotools-windows

Labelme使用conda版

这里首先提供了Labelme的官网

官方的代码提供了一些标注数据转为coco格式或者voc格式的代码片段。最后如何有需要可以在改进。

在这里插入图片描述
官网中提供了python3如何使用label这个项目。

# python3
conda create --name=labelme python=3.6
conda activate labelme
pip install labelme

下载与使用

conda create -n labelme python=3.8
进入到对应的虚拟环境后输入下面命令安装即可。注意:安装的版本,建议安装3.16.7版本,其它版本的容易出错:
pip install labelme==3.16.7

打开labelme

在当前安装的虚拟环境下面直接使用命令:打开labelme

labelme
shortcuts:
close: Ctrl+W #关闭
open: Ctrl+O #打开
open_dir: Ctrl+U #打开文件夹
quit: Ctrl+Q #退出
save: Ctrl+S #保存
save_as: Ctrl+Shift+S #另存为
save_to: null
delete_file: Ctrl+Delete #删除文件
 
open_next: [D, Ctrl+Shift+D] #打开下一张图
open_prev: [A, Ctrl+Shift+A] #打开上一张图
 
zoom_in: [Ctrl++, Ctrl+=] #放大
zoom_out: Ctrl+- #缩小
zoom_to_original: Ctrl+0 #回到原尺寸
fit_window: Ctrl+F #图片适应窗口
fit_width: Ctrl+Shift+F #图片适应宽度
  
create_polygon: Ctrl+N #创建多边形(这个用的多,建议改了)
create_rectangle: Ctrl+R #创建圆
create_circle: null
create_line: null
create_point: null
create_linestrip: null
edit_polygon: Ctrl+J #编辑多边形(这个用的多,也是建议改了)
delete_polygon: Delete #删除
duplicate_polygon: Ctrl+D #等边行复制
copy_polygon: Ctrl+C #复制
paste_polygon: Ctrl+V #粘贴
undo: Ctrl+Z #重做
undo_last_point: Ctrl+Z #撤销上一个点
add_point_to_edge: Ctrl+Shift+P #增加一个点(用不到,直接在边界上点鼠标左键就能加点)
edit_label: Ctrl+E #编辑标签
toggle_keep_prev_mode: Ctrl+P
remove_selected_point: [Meta+H, Backspace] #删除选定的点

在这里插入图片描述

标注的过程比较简单准备直接在组会上演示一下不在写了

Json To Dataset

得到json文件之后,我们要将其转化成数据集使用,这里涉及到labelme源码的更改首先,找到labelme的json_to_dataset.py

D:\Enviroment\Anaconda\envs\label\Lib\site-packages\labelme\cli

import argparse
import json
import os
import os.path as osp
import warnings
 
import PIL.Image
import yaml
 
from labelme import utils
import base64
 
def main():
    warnings.warn("This script is aimed to demonstrate how to convert the\n"
                  "JSON file to a single image dataset, and not to handle\n"
                  "multiple JSON files to generate a real-use dataset.")
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()
 
    json_file = args.json_file
    if args.out is None:
        out_dir = osp.basename(json_file).replace('.', '_')
        out_dir = osp.join(osp.dirname(json_file), out_dir)
    else:
        out_dir = args.out
    if not osp.exists(out_dir):
        os.mkdir(out_dir)
 
    count = os.listdir(json_file) 
    for i in range(0, len(count)):
        path = os.path.join(json_file, count[i])
        if os.path.isfile(path):
            data = json.load(open(path))
            
            if data['imageData']:
                imageData = data['imageData']
            else:
                imagePath = os.path.join(os.path.dirname(path), data['imagePath'])
                with open(imagePath, 'rb') as f:
                    imageData = f.read()
                    imageData = base64.b64encode(imageData).decode('utf-8')
            img = utils.img_b64_to_arr(imageData)
            label_name_to_value = {'_background_': 0}
            for shape in data['shapes']:
                label_name = shape['label']
                if label_name in label_name_to_value:
                    label_value = label_name_to_value[label_name]
                else:
                    label_value = len(label_name_to_value)
                    label_name_to_value[label_name] = label_value
            
            # label_values must be dense
            label_values, label_names = [], []
            for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]):
                label_values.append(lv)
                label_names.append(ln)
            assert label_values == list(range(len(label_values)))
            
            lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)
            
            captions = ['{}: {}'.format(lv, ln)
                for ln, lv in label_name_to_value.items()]
            lbl_viz = utils.draw_label(lbl, img, captions)
            
            out_dir = osp.basename(count[i]).replace('.', '_')
            out_dir = osp.join(osp.dirname(count[i]), out_dir)
            if not osp.exists(out_dir):
                os.mkdir(out_dir)
 
            PIL.Image.fromarray(img).save(osp.join(out_dir, 'img.png'))
            #PIL.Image.fromarray(lbl).save(osp.join(out_dir, 'label.png'))
            utils.lblsave(osp.join(out_dir, 'label.png'), lbl)
            PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, 'label_viz.png'))
 
            with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
                for lbl_name in label_names:
                    f.write(lbl_name + '\n')
 
            warnings.warn('info.yaml is being replaced by label_names.txt')
            info = dict(label_names=label_names)
            with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
                yaml.safe_dump(info, f, default_flow_style=False)
 
            print('Saved to: %s' % out_dir)
if __name__ == '__main__':
    main()

D:\Enviroment\Anaconda\envs\label\Scripts 在这个文件下面执行匹配的根据json生成图片的代码。

下面就可以进行json文件批量处理了,exe程序后边是之前的json单独建立的目录

labelme_json_to_dataset.exe E:\Paper\voc\Annotations

成功执行后结果如下图,其保存的地址为相对地址,就是在
在这里插入图片描述


http://www.kler.cn/a/379924.html

相关文章:

  • 参数失配(Mismatch)
  • 文件系统上云的挑战
  • 计算机启动过程中各个步骤
  • w018基于Springboot的母婴商城系统
  • NLP领域的经典算法和模型
  • 从0开始搭建一个生产级SpringBoot2.0.X项目(八)SpringBoot 使用Redis
  • Java面向对象 C语言字符串常量
  • CSS 超出一行省略号...,适用于纯数字、中英文
  • 百货零售行业信息化蓝图整体规划方案|165页PPT
  • 深度强化学习(DRL)发展历程
  • 分布式数据库:核心概念、架构设计及应用实践
  • 记录一次node节点异常的排查
  • ssm校园线上订餐系统的设计与实现+vue
  • Linux: network: 环境:网络burst的一个原因,虚拟机感染病毒导致,外部网络设备太忙
  • 个人对Numpy中transpose()函数的理解
  • 利用Stable Diffusion技术,StableVision能够自动生成高质量、高分辨率的图像,满足用户对于图像素材的多样化需求。
  • 从模糊搜索到语义搜索的进化之路——探索 Chroma 在大模型中的应用价值
  • 层次与网络的视觉对话:树图与力引导布局的双剑合璧
  • pt-archive
  • Fx-LMS 单片机