python标注制作_使用labelme软件标注并制作自己的数据集

最近在做图像语义分割方面的学习,前期已经在本地电脑完整地训练了ADEChallengeData2016数据,下一阶段准备使用自己的数据集完成一些任务。下面整理一下我在使用labelme进行标注,实现自己数据集的制作。主要分为以下五部分:

图像手动标注

图像标注使用专门的图像标签制作软件labelme。

该软件的WINDOWS操作系统下的安装包我已经上传,无偿奉送,点击链接自取。

界面简洁易上手,一般使用红框里的这四个按钮。下面简单介绍:

【Open Dir】打开文件夹,将该文件下的所有文件路径均会以列表形式显示在界面右下角的“File List”容器内,标注且保存过的图片其路径前的复选框会被勾选;

【Save】保存标注文件,个人建议和原图放在同一个文件夹下,这样即使没有标注完该文件夹下的所有文件,关闭后再次打开被标注的图片其名称前依旧会被checked。

【Create Polygons】绘制多边形,可以在绘图区用鼠标绘制闭合的区域,当鼠标最后一个点接近第一个点图形会自动闭合,并弹出窗体提示用户输入该多边形的标签(半角英文标签哦!),点击“Save”按钮保存到指定路径下,标注的文件扩展名为.json。

【Next Image】显示下一个未标注的图片,继续画多边形,输入标签,保存,就这样像木得感情的机器循环往复如此而已。

温馨提示: 此过程需要耗费大量的时间和精力,标注时一定要睁大眼睛,眼药水备用,尽量保证标注尽可能的完美,不然会影响接下来的训练结果,注意眼部休息

标注好的标签文件,除扩展名为json外名,其余原图保持一致。

JSON文件批量转换

有了json文件就离我们的标签图片进了一大步,接下来就是研究怎么把json转换成图片格式(这里转为png)。我们先来看看人家的数据集长什么样。

我在网上查找到了相关代码,但只不过是逐个进行转换,需要手动修改每个图片的路径,着实麻烦,我就根据自己的需求对文件夹下的所有json文件进行了批量转换。代码如下:

import json

import os

import os.path as osp

import warnings

import PIL.Image

import yaml

from labelme import utils

import base64

def JSON_to_IMG(json_file, save_file):

"""

将指定目录下的json标注文件全部转换为以下文件:①jpg原图文件、 ②png标签文件

③其他相关说明文件 。存储在指定路径下

:param json_file: Json格式所在文件夹

:param save_file: 转换后的文件存储文件夹

"""

#如果存储路径不存在就创建文件目录

if not osp.exists(save_file):

os.mkdir(save_file)

#文件目录下的所有json文件名称

count = os.listdir(json_file)

#遍历目录下的所有json文件

for i in range(0, len(count)):

#获取json文件全路径名称

path = os.path.join(json_file, count[i])

#如果是imagedata格式文件进行读取

if os.path.isfile(path):

#打开json文件

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)

#将图片中背景赋值为0

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)

#获取json文件名并将.json改为_json用作文件夹目录

#out_dir = osp.basename(count[i]).replace('.json', '.png')

out_pic_name = str(i) + ".jpg"#原图

out_label_name = str(i) + ".png"#标签图

out_label_viz_name = str(i) + "_label_viz.png"#带标注的图片

out_labeltxt_name = str(i) + "_label_names.txt"#标签名对应值

out_info_name = str(i) + "_info.yaml"

#在目标文件夹下保存原始图片

PIL.Image.fromarray(img).save(osp.join(save_file, out_pic_name))

#保存标签图片

utils.lblsave(osp.join(save_file, out_label_name), lbl)

#保存带标注的可视化图片

PIL.Image.fromarray(lbl_viz).save(osp.join(save_file, out_label_viz_name))

with open(osp.join(save_file, out_labeltxt_name), '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(save_file, out_info_name), 'w') as f:

yaml.safe_dump(info, f, default_flow_style=False)

print('完成了对Json文件: %s的IMG格式转换!' % osp.basename(count[i]))

print("指定目录下的所有JSON文件完成转换!")

#程序主入口

if __name__ == '__main__':

json_file = r"C:\Users\梦了个梦\Desktop\打标签\json文件汇总"#这里json文件所在文件夹的全路径

save_file = r"C:\Users\梦了个梦\Desktop\打标签\JSON_PNG"#这里填写转换后文件保存的文件夹全路径

JSON_to_IMG(json_file, save_file)#调用上方定义的转换函数完成批量转换

提示:运行该脚本文件需要安装python编译器,导入相关库,在运行过程中,某些条件下系统一直提示如下错误:

去网上查找相关解释,是说安装的labelme库下没有这些脚本,可能是高版本(我一开始是4.0+版本),将labelme的版本降到3.16.2,就不再报错了。

代码成功运行完毕,每个json文件会生成下图所示的五个文件。

我只需要用到前两个图片,倒数第二个txt文件会指示最后一个图片标签中1所代表的具体实体语义,yaml我也没用到也不清楚就不管了。

标签转为单通道灰度图

运行到此,我以为成功近在咫尺,所以直接将目前的数据输入分割网络,但提示错误,说他们需要深度为1的标签图片,而到目前为止实现的标签图片是四个通道,这就需要进行通道数转换,转成只有一个通道的灰度图。怎么转灰度图呢,废话不多说直接上代码。

#批量图片转换:将RGB模式或P模式转换为L灰度拉伸值(可以自定义拉伸大小)

import numpy as np

from PIL import Image

import os

def Mode_P_to_L(img_file,stretch_value):

"""

将当前文件下的所有图片进行灰度值转换

:param img_file: 图片文件存放目录

:param stretch_value: 拉伸值, 图片原始值*stretch_value的结果理论上应该小于255

"""

##获取目录下所有文件名

file_name_list = os.listdir(img_file)

#遍历所有图片文件

for file in file_name_list:

#获取某个图片的全路径

img_path = os.path.join(img_file, file)

#打开图片

image = Image.open(img_path)

print(image.mode) #p模式

img_arry = Image.fromarray(np.uint8(image))

print(img_arry.mode)#L模式

img_L = img_arry.convert("L")

print(img_L.mode)

#灰度拉伸

img_end = Image.fromarray(np.uint8(img_L) * stretch_value)

print(img_end.mode)

#保存图片,并覆盖原图

img_end.save(img_path)

#提示

print("完成对图片:",file," 的转换!")

print("所有图片均已完成转换!")

#程序主入口

if __name__ == "__main__":

# 需要转换的图片所在文件目录

img_file = r""#自己输入上一步生成的png格式的标签图

stretch_value = 1#自定义拉伸值,但要注意,图片标签值*stretch_value的结果理论上应该小于255

Mode_P_to_L(img_file, stretch_value)#调用自定义的转换方法

下图即为标签图的原图(左)和转换后的灰度标签图(右)对比:

训练集批量扩充

由于数据集数量较少,而有监督的语义分割机器学习需要大量的训练数据集,图片扩充就呼之欲出,

废话不多说直接上代码(这里有90度、180度、270度顺时针旋转和水平,垂直镜像种扩充形式)

from PIL import Image

import os

def Expand_trainset_pic(img_file):

"""

对指定目录下的图片进行简单数据扩充,包括对原图

进行90°、180°,270°顺时针旋转

和水平镜像以及垂直镜像

:param img_file: 需要批量扩充的图片所在文件夹

"""

#获取文件目录下的所有文件名

file_name_list = os.listdir(img_file)

for file in file_name_list:

#获取图片文件全路径

img_path = os.path.join(img_file, file)

#打开图片

image = Image.open(img_path)

#获取文件名

filename= os.path.splitext(file)[0]

#获取扩展名

file_ext=os.path.splitext(file)[1]

#90、180、270顺时针旋转

img1 = image.transpose(Image.ROTATE_90) # 引用固定的常量值

img1_name=filename+"_90"+file_ext

img1_save_path=os.path.join(img_file, img1_name)

img1.save(img1_save_path)

img2 = image.transpose(Image.ROTATE_180) # 引用固定的常量值

img2_name=filename+"_180"+file_ext

img2_save_path=os.path.join(img_file, img2_name)

img2.save(img2_save_path)

img3 = image.transpose(Image.ROTATE_270) # 引用固定的常量值

img3_name=filename+"_270"+file_ext

img3_save_path=os.path.join(img_file, img3_name)

img3.save(img3_save_path)

img4 = image.transpose(Image.FLIP_LEFT_RIGHT) # 引用固定的常量值

img4_name=filename+"_x"+file_ext

img4_save_path=os.path.join(img_file, img4_name)

img4.save(img4_save_path)

img5 = image.transpose(Image.FLIP_TOP_BOTTOM) # 引用固定的常量值

img5_name=filename+"_y"+file_ext

img5_save_path=os.path.join(img_file, img5_name)

img5.save(img5_save_path)

print("完成对图片:", file, " 的扩充")

print("完成对所有图片的扩充!")

#程序主入口

if __name__ == "__main__":

img_file = r' ' #在此输入需要转换的图片所在文件夹

Expand_trainset_pic(img_file)#调用自定义扩充函数

FBI警告!

该扩充操作只能针对于训练集,否则会造成数据泄露,导致虽然最后训练集以及验证集的精度都很完美但实际上很垃圾。

pickle文件(以字典形式保存数据集路径)制作

使用过ADEchallenge数据集及其相关代码的同学请自行学习read_MITSceneParsingData.py脚本文件的read_dataset函数以及create_image_lists函数,我之前的帖子有关于该代码报错的解决说明。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值