从图片到dataframe——语义分割数据集制作全流程
分享一下从原始图片,到标记图片,再到转换为python里的数据结构语义分割数据集制作全流程。
安装labelme
labelme 是一个图形界面的图像标注软件,可以很方便地划分出多边形边界。
下面在win10系统中使用anaconda安装labelme
// python3
conda create --name=labelme python=3.6
activate labelme
pip install labelme
anaconda会自动安装好labelme及其依赖包
通过conda list命令查看安装好的包:
在每次打开prompt或cmd激活labelme虚拟环境后,输入labelme
即可打开labelme
标注图片
打开labelme,在labelme中打开文件夹,在Edit中选择create polygons即可添加多边形标记框,标记完后输入标签名即可完成一片区域的标记。标记完成后保存为json文件
json文件转为数据集
labelme标签不一致问题
labelme库原有的labelme_json_to_dataset.py
脚本可以将json文件转换为原图(img)、掩码(mask)、原图和掩码的叠加(viz)和一个标签文件(txt)。默认情况下,导出掩码的像素值和在标注时标记的顺序有关,而不是和标签名对应。
这里参考了https://zhuanlan.zhihu.com/p/159837405的方法对labelme的 _json_to_dataset.py代码进行更改,使label可以自行配置,同时保证了标签的统一。
首先使用everything找到虚拟环境中labelme库的labelme_json_to_dataset.py
文件
注释掉部分源代码,加上自己的标签名称和对应编号(0,1,2,…),保存即可
import argparse
import base64
import json
import os
import os.path as ospimport imgviz
import PIL.Imagefrom labelme.logger import logger
from labelme import utilsdef main():logger.warning("This script is aimed to demonstrate how to convert the ""JSON file to a single image dataset.")logger.warning("It won't handle 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_fileif 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.outif not osp.exists(out_dir):os.mkdir(out_dir)data = json.load(open(json_file))imageData = data.get("imageData")if not imageData:imagePath = os.path.join(os.path.dirname(json_file), 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 sorted(data["shapes"], key=lambda x: x["label"]):# 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# lbl, _ = utils.shapes_to_label(# img.shape, data["shapes"], label_name_to_value# )# label_names = [None] * (max(label_name_to_value.values()) + 1)# for name, value in label_name_to_value.items():# label_names[value] = namelabel_name_to_value={'_background_': 0, 'E': 1, 'Esl': 2, 'Esc': 3, 'F1':4, 'F2':5, 'Fspread':6}lbl, _ = utils.shapes_to_label(img.shape, data["shapes"], label_name_to_value)label_names=['_background_', 'E', 'Esl', 'Esc','F1', 'F2', 'Fspread']# ########################### 结束修改 #############################lbl_viz = imgviz.label2rgb(label=lbl, img=imgviz.asgray(img), label_names=label_names, loc="rb")PIL.Image.fromarray(img).save(osp.join(out_dir, "img.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")logger.info("Saved to: {}".format(out_dir))if __name__ == "__main__":main()
批量转换json文件
labelme库原有的labelme_json_to_dataset
脚本一次只能转换一个json文件在此参考博主里先森的文章批量转换labelme标注json数据为图片,并将不同类型的图片分文件夹存储。
https://blog.csdn.net/sements/article/details/110135137
创建文件trans.py
# 调用labelme库中原有的 labelme_json_to_dataset 为核心
# 批量将文件夹中的json文件转换,并抽取对应图片至各自文件夹
# python trans.py -i ./ -r img -m mask -v viz
import os
import shutil
import argparsedef GetArgs():parser = argparse.ArgumentParser(description='将labelme标注后的json文件批量转换为图片')parser.add_argument('--input', '-i', required=True, help='json文件目录')parser.add_argument('--out-mask', '-m', required=True, help='mask图存储目录')parser.add_argument('--out-img', '-r', help='json文件中提取出的原图存储目录')parser.add_argument('--out-viz', '-v', help='mask与原图合并viz图存储目录')return parser.parse_args()if __name__ == '__main__':_args = GetArgs()_jsonFolder = _args.inputinput_files = os.listdir(_jsonFolder)for sfn in input_files: # single file nameif (os.path.splitext(sfn)[1] == ".json"): # 是否为json文件# 调用labelme_json_to_dataset执行转换,输出到 temp 文件夹os.system("labelme_json_to_dataset %s -o temp" % (_jsonFolder + '/' + sfn))# 复制json文件中提取出的原图到存储目录if _args.out_img:if not os.path.exists(_args.out_img): # 文件夹是否存在os.makedirs(_args.out_img)src_img = "temp\img.png"dst_img = _args.out_img + '/' + os.path.splitext(sfn)[0] + ".png"shutil.copyfile(src_img, dst_img)# 复制mask图到存储目录if _args.out_mask:if not os.path.exists(_args.out_mask): # 文件夹是否存在os.makedirs(_args.out_mask)src_mask = "temp\label.png"dst_mask = _args.out_mask + '/' + os.path.splitext(sfn)[0] + ".png"shutil.copyfile(src_mask, dst_mask)# 复制viz图到存储目录if _args.out_viz:if not os.path.exists(_args.out_viz): # 文件夹是否存在os.makedirs(_args.out_viz)src_viz = "temp\label_viz.png"dst_viz = _args.out_viz + '/' + os.path.splitext(sfn)[0] + ".png"shutil.copyfile(src_viz, dst_viz)
将其与待转换的json文件放入同一个文件夹中,命令行切换至该目录,执行
python trans.py -i ./ -r img -m mask -v viz
即可完成转换,生成所需的四个文件夹
读取图片并转换为dataframe格式
json文件转换得到的掩码(mask)是RGB三通道彩色图,而语义分割需要的掩码往往是灰度图。
可以使用cv2库中的imread
函数直接将三通道彩色图导入为灰度图,导入后查看六种不同标签的到灰度值如下(背景灰度值为0)
为了便于训练,我自己写了一个类似switch的字典用于将灰度值转换为0,1,2,3,4,5,6的标签值。
# labelconvert.py
def case0(): return 0
def case1(): return 1
def case2(): return 2
def case3(): return 3
def case4(): return 4
def case5(): return 5
def case6(): return 6
def default(): print('Error') return 255
switch = {38: case1, 75: case2,113: case3,14: case4,52: case5,89: case6,0: case0}
def labelconvert(img):for i in range (360):for j in range (400):img[i][j] = switch.get(int(img[i][j]), default)() return img
为了方便存储原图、掩码和文件名,使用pandas的dataframe进行存储,dataframe里的数据也可以转换为np数组或tensor张量。
from tensorflow.keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
import matplotlib.pyplot as plt
import cv2
import numpy as np
from labelconvert import labelconvert # 自定义函数,用于灰度标签转换为0-6
import os
import pandas as pd
import timemaskdf = pd.DataFrame(columns=('id', 'mask', 'Fspread'))
inputdf = pd.DataFrame(columns=(['input']))
mask_dir = 'D:\\OriginIonograms\\lyf50\\mask\\'
input_dir = 'D:\\OriginIonograms\\lyf50\\img\\'i = 1
tic1 = time.perf_counter()
# 导入mask数据
for filename in os.listdir(mask_dir):img = cv2.imread(mask_dir + "/" + filename, cv2.IMREAD_GRAYSCALE) #导入灰度图img = img_to_array(img)img = labelconvert(img) # 替换比较耗时Fspread = (img == 6).any() # Fspread = (img == 89).any() # 不做标签转换maskdf.loc[i] = [filename, img, Fspread]i = i + 1
tic2 = time.perf_counter()
print('导入', i-1,'组mask数据用时',tic2-tic1,'s' )# 导入input数据
i = 1
for filename in os.listdir(input_dir):img = cv2.imread(input_dir + "/" + filename, cv2.IMREAD_GRAYSCALE)img = img_to_array(img)inputdf.loc[i] = [img]i = i + 1
tic3 = time.perf_counter()
print('导入', i-1,'组input数据用时',tic3-tic2,'s' )df = pd.concat([maskdf, inputdf], axis=1)
print(df.columns)df2 = df.drop(df[df.Fspread == 1].index)
print('所有数据共', df.shape[0], '条')
从图片到dataframe——语义分割数据集制作全流程相关推荐
- 【语义分割数据集制作】使用labelme制作自己的U-net语义分割数据集
最近有一个工作需要使用Unet的语义分割结果作为上游任务,语义分割数据集需要自己制作,特此记录一下. 1.下载labelme 第一步当然是下载labelme工具,主要有两种方式: 1. 系 ...
- 快速制作自己的VOC语义分割数据集
语义分割数据集制作与转换方法 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 第一章 基于PS的语义分割标注 第二章 构建VOC语义分割数据集 文章目录 语义分割数据集制作与转换方法 ...
- 图像分割数据集制作matlab,制作自己的图像语义分割数据集
本文教你如何正确制作自己的图像语义分割数据集.假设我当前目录下有500张图片,命名从1.jpg开始,一直往上递增,我事先已经调整好了图像的大小. 首先下载Labelme工具:https://githu ...
- 自己制作语义分割语义分割数据集
最近在用deeplab,需要自己标注数据集,整理一下. 制作语义分割数据集大致需要 (1)使用labelme对数据进行标注,生成对应图片的json格式. (2)执行label下的labelme_jso ...
- 制作自定义语义分割数据集
自定义语义分割数据集(划分训练集与验证集).并且将一个文件夹下的所有图片的名字存到txt文件 我们可以借助Pytorch从文件夹中读取数据集,十分方便,但是Pytorch中没有提供数据集划分的操作,需 ...
- 无人驾驶常用数据集---图像语义分割数据集--Cityscapes数据集的解读(for 小白)
** 无人驾驶常用数据集–图像语义分割数据集–Cityscapes数据集的解读(for 小白) ** 一.什么是Cityscapes数据集? Cityscapes是关于城市街道场景的语义理解图片数据集 ...
- 憨批的语义分割6——制作语义分割数据标签
憨批的语义分割6--制作语义分割数据集 学习前言 制作工具Labelme Labelme的使用 标签文件内容 学习前言 有些小伙伴问怎么制作数据集,其实我也没有去制作过--所以也要学学啦, 制作工具L ...
- 4种语义分割数据集Cityscapes上SOTA方法总结
本文分享自华为云社区<语义分割数据集Cityscapes上SOTA方法总结>,原文作者:fdafad. 1 Cityscapes数据集介绍 Cityscapes评测数据集即城市景观数据集, ...
- 遥感影像语义分割数据集
遥感图像语义分割数据集 文章目录 遥感图像语义分割数据集 1.建筑 1.1 Aerial Image Segmentation Dataset 1.2 INRIA aerial image datas ...
最新文章
- Compiere去掉启动时的下面显示的进度条
- Git使用汇总之工作区、暂存区、版本库
- handler机制的原理_5分钟了解Handler错误使用场景
- 不得不看的17 个linux实用技巧
- Alfresco Community 批量导入指南
- 为什么 Web 开发人员需要学习一个 JavaScript 框架?
- 设计模式 之 单例模式
- 数据结构和算法练习网站_视频和练习介绍了10种常见数据结构
- linux课堂笔记(4)
- 蓝桥杯青少创意编程python组
- python3 compile_python3.2的pycompile
- 我是如何在自学编程9个月后找到工作的
- excel数据分析 - 17个计算统计类函数
- Python3截图识字工具
- maven报错:Failure to transfer xxx.jar from xxx was cached in the local repository.
- 高质量web前端后台模板
- 多合一音乐搜索器项目源码分享,支持播放,下载
- 解决浏览器看不到Flash文档(尤其某慕课)
- 北京三里屯苹果店悼念乔布斯:“黄牛”也献花
- 综合架构(备份部分)