voc数据集镜像地址 数据集.
voc数据集中我们需要的文件为ImageSets、JPEGImages、SegmentationObject,因此我们先新建这三个文件夹。
1、安装anaconda,安装完成后打开conda prompt
2、安装labelme工具,命令pip intall labelme==3.16.2
安装完成以后用labelme命令就可以直接打开了
3、使用labelme对图片中的目标物体进行标注(标轮廓),标注完成后会生成一个json文件(json文件需要与图片存在同目录)
4、所有图片标注完成后,新建一个文件夹将json文件单独存放
5、批量转换json的同时,将同一个文件夹下类别标签的颜色固定。labelme的类别是随机给的,json_to_dataset.py里面有个用来把label映射成数字的字典,那个字典,在每次调用这个程序的时候,都会初始化一遍,所以每次调用它,都是不同的映射,最终造成了每张图的颜色和label不一致,因此,对该文件进行修改,先初始化一个映射字典,然后每次处理json的时候,都用这同一个字典。
cd E:\conda3gesaer\Lib\site-packages\labelme\cli(labelme的安装路径)找到json_to_dataset.py。
用下面的代码进行替换:
import argparse
import base64
import json
import os
import os.path as osp
import PIL.Image
import yaml
from labelme.logger import logger
from labelme import utils
path = "E:/gesaer/gesaer_data/Json"
dirs = os.listdir(path)
def label(json_file, out_dir, label_name_to_value):
data = json.load(open(json_file))
if data['imageData']:
imageData = data['imageData']
else:
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)
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] = name
lbl_viz = utils.draw_label(lbl, img, label_names)
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.warning('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)
logger.info('Saved to: {}'.format(out_dir))
def main():
logger.warning('This script is aimed to demonstrate how to convert the'
'JSON file to a single image dataset, and not to handle'
'multiple JSON files to generate a real-use dataset.')
parser = argparse.ArgumentParser()
parser.add_argument('json_file_dir')
parser.add_argument('-o', '--out', default=None)
args = parser.parse_args()
label_name_to_value = {'_background_': 0}
for json_file in dirs:
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)
label(json_file, out_dir, label_name_to_value)
if __name__ == '__main__':
main()
替换完成后cd 到存放json文件的目录下 run labelme_json_to_dataset 输出的目录
如果输出的目录找不到文件就到存放json文件的目录下找找,应该会有
每次转换的时候都要记得更改路径,不然会权限报错
上述代码在批量转换的同时,将同一个文件夹下类别标签的颜色固定,不需要重新填重颜色。
此时每个json文件夹中有5个文件,其中label.png就是做语义分割任务所需要的索引图了,将该图与voc中的索引图进行对比,我们发现二者的格式相同
6、整合label.png
每一个文件夹中都要一个png图而且名字都是label.png,我们需要将所有png图单独拿出来同时重新命名成与json文件对应的名字,代码如下:
import os
import shutil
inputdir = 'E:/gesaer/gesaer_data/tangkaJson'
outputdir = 'E:/gesaer/gesaer_data/tangkapng'
for dir in os.listdir(inputdir):
#设置旧文件名(就是路径+文件名)
oldname = inputdir + os.sep + dir + os.sep + 'label.png' # os.sep添加系统分隔符
#设置新文件名
newname = outputdir + os.sep + dir.split('_')[0] + '.png'
shutil.copyfile(oldname, newname) #用os模块中的rename方法对文件改名
print(oldname, '======>', newname)
代码如下:
from sklearn.model_selection import train_test_split
import os
imagedir = 'E:/gesaer/gesaer_data/tangkapng/'
outdir = 'E:/gesaer/gesaer_data/'
images = []
for file in os.listdir(imagedir):
filename = file.split('.')[0]
images.append(filename)
train, test = train_test_split(images, train_size=0.7, random_state=0)
val, test = train_test_split(test, train_size=0.2/0.3, random_state=0)
with open(outdir+"train.txt", 'w') as f:
f.write('\n'.join(train))
with open(outdir+"val.txt", 'w') as f:
f.write('\n'.join(val))
with open(outdir+"test.txt", 'w') as f:
f.write('\n'.join(test))