文章目录[隐藏]
在做目标检测时,我个人比较喜欢VOC格式的数据集,所以遇到COCO格式的数据集习惯转为VOC的,再进行处理。
coco转voc格式
需要修改的只有路径以及jsonFileName 这个列表,都已经标明了比较清晰的注释。
'''
Author: TuZhou
Version: 1.0
Date: 2021-08-29 16:32:52
LastEditTime: 2021-08-29 17:44:57
LastEditors: TuZhou
Description:
FilePath: \My_Yolo\datasets\coco_to_voc.py
'''
from pycocotools.coco import \
COCO # 这个包可以从git上下载https://github.com/cocodataset/cocoapi/tree/master/PythonAPI,也可以直接用修改后的coco.py
import os, cv2, shutil
from lxml import etree, objectify
from tqdm import tqdm
from PIL import Image
#要生成的voc格式图片路径
image_dir = './datasets/RoadSignsPascalVOC_Voc/images'
#要生成的voc格式xml标注路径
anno_dir = './datasets/RoadSignsPascalVOC_Voc/annotations'
#---------------------------------------------#
#你的coco格式的json类型和文件名,前者表示是train类型的json,后者表示该json文件的名字,类型名最好是与你的对应类型图片保存文件夹名一致
#我的json目录只有一个train类型,如果你有测试集的json文件,则可写成[['train', 'instance_train'], ['test', 'instance_test']]
jsonFileName = [['train', 'instance_train']]
#----------------------------------------------#
'''
Author: TuZhou
Description: 若模型保存文件夹不存在,创建模型保存文件夹,若存在,删除重建
param {*} path 文件夹路径
return {*}
'''
def mkr(path):
if os.path.exists(path):
shutil.rmtree(path)
os.mkdir(path)
else:
os.mkdir(path)
'''
Author: TuZhou
Description: 保存xml文件
param {*} filename
param {*} objs
param {*} filepath
return {*}
'''
def save_annotations(filename, objs, filepath):
annopath = anno_dir + "/" + filename[:-3] + "xml" # 生成的xml文件保存路径
#print("filename", filename)
dst_path = image_dir + "/" + filename
img_path = filepath
img = cv2.imread(img_path)
#此处时对非RGB图像筛选,可注释
# im = Image.open(img_path)
# if im.mode != "RGB":
# print(filename + " not a RGB image")
# im.close()
# return
# im.close()
shutil.copy(img_path, dst_path) # 把原始图像复制到目标文件夹
E = objectify.ElementMaker(annotate=False)
anno_tree = E.annotation(
E.folder('1'),
E.filename(filename),
E.source(
E.database('CKdemo'),
E.annotation('VOC'),
E.image('CK')
),
E.size(
E.width(img.shape[1]),
E.height(img.shape[0]),
E.depth(img.shape[2])
),
E.segmented(0)
)
for obj in objs:
E2 = objectify.ElementMaker(annotate=False)
anno_tree2 = E2.object(
E.name(obj[0]),
E.pose(),
E.truncated("0"),
E.difficult(0),
E.bndbox(
E.xmin(obj[2]),
E.ymin(obj[3]),
E.xmax(obj[4]),
E.ymax(obj[5])
)
)
anno_tree.append(anno_tree2)
etree.ElementTree(anno_tree).write(annopath, pretty_print=True)
def showbycv(coco, dataType, img, classes, origin_image_dir, verbose=False):
filename = img['file_name']
#NOTE:dataType表示coco格式中训练集或者测试集的图片文件夹名,但是我所有图片都放在JPEGImages文件夹中,所以此处为空,有需要的可以修改
#dataType就是jsonFileName中的json类型,如果你的类型名和你的图片文件夹名一致,则可注释下行
dataType = ''
filepath = os.path.join(origin_image_dir, dataType, filename)
I = cv2.imread(filepath)
annIds = coco.getAnnIds(imgIds=img['id'], iscrowd=None)
anns = coco.loadAnns(annIds)
objs = []
for ann in anns:
name = classes[ann['category_id']]
if 'bbox' in ann:
bbox = ann['bbox']
xmin = (int)(bbox[0])
ymin = (int)(bbox[1])
xmax = (int)(bbox[2] + bbox[0])
ymax = (int)(bbox[3] + bbox[1])
obj = [name, 1.0, xmin, ymin, xmax, ymax]
objs.append(obj)
if verbose:
cv2.rectangle(I, (xmin, ymin), (xmax, ymax), (255, 0, 0))
cv2.putText(I, name, (xmin, ymin), 3, 1, (0, 0, 255))
save_annotations(filename, objs, filepath)
if verbose:
cv2.imshow("img", I)
cv2.waitKey(0)
def catid2name(coco): # 将名字和id号建立一个字典
classes = dict()
for cat in coco.dataset['categories']:
classes[cat['id']] = cat['name']
# print(str(cat['id'])+":"+cat['name'])
return classes
'''
Author: TuZhou
Description:
param {*} origin_anno_dir 原始coco的json文件目录
param {*} origin_image_dir 原始coco的图片保寸目录
param {*} verbose
return {*}
'''
def get_CK5(origin_anno_dir, origin_image_dir, verbose=False):
for dataType, annoName in jsonFileName:
#annFile = 'instances_{}.json'.format(dataType)
annFile = annoName + '.json'
annpath = os.path.join(origin_anno_dir, annFile)
coco = COCO(annpath)
classes = catid2name(coco)
imgIds = coco.getImgIds()
# imgIds=imgIds[0:1000]#测试用,抽取10张图片,看下存储效果
for imgId in tqdm(imgIds):
img = coco.loadImgs(imgId)[0]
showbycv(coco, dataType, img, classes, origin_image_dir, verbose=False)
def main():
base_dir = './datasets/RoadSignsPascalVOC_Voc' # step1 这里是一个新的文件夹,存放转换后的图片和xml标注
image_dir = os.path.join(base_dir, 'images') # 在上述文件夹中生成images,annotations两个子文件夹
anno_dir = os.path.join(base_dir, 'annotations')
mkr(image_dir)
mkr(anno_dir)
origin_image_dir = './datasets/RoadSignsPascalVOC/JPEGImages' # step 2原始的coco的图像存放位置
origin_anno_dir = './datasets/RoadSignsPascalVOC_Coco/Annotations' # step 3 原始的coco的标注存放位置
verbose = True # 是否需要看下标记是否正确的开关标记,若是true,就会把标记展示到图片上
get_CK5(origin_anno_dir, origin_image_dir, verbose)
if __name__ == "__main__":
main()
voc转coco格式
import xml.etree.ElementTree as ET
import os
import json
coco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []
category_set = dict()
image_set = set()
category_item_id = -1
image_id = 20210000000
annotation_id = 0
def addCatItem(name):
global category_item_id
category_item = dict()
category_item['supercategory'] = 'none'
category_item_id += 1
category_item['id'] = category_item_id
category_item['name'] = name
coco['categories'].append(category_item)
category_set[name] = category_item_id
return category_item_id
def addImgItem(file_name, size):
global image_id
if file_name is None:
raise Exception('Could not find filename tag in xml file.')
if size['width'] is None:
raise Exception('Could not find width tag in xml file.')
if size['height'] is None:
raise Exception('Could not find height tag in xml file.')
image_id += 1
image_item = dict()
image_item['id'] = image_id
image_item['file_name'] = file_name
image_item['width'] = size['width']
image_item['height'] = size['height']
coco['images'].append(image_item)
image_set.add(file_name)
return image_id
def addAnnoItem(object_name, image_id, category_id, bbox):
global annotation_id
annotation_item = dict()
annotation_item['segmentation'] = []
seg = []
# bbox[] is x,y,w,h
# left_top
seg.append(bbox[0])
seg.append(bbox[1])
# left_bottom
seg.append(bbox[0])
seg.append(bbox[1] + bbox[3])
# right_bottom
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1] + bbox[3])
# right_top
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1])
annotation_item['segmentation'].append(seg)
annotation_item['area'] = bbox[2] * bbox[3]
annotation_item['iscrowd'] = 0
annotation_item['ignore'] = 0
annotation_item['image_id'] = image_id
annotation_item['bbox'] = bbox
annotation_item['category_id'] = category_id
annotation_id += 1
annotation_item['id'] = annotation_id
coco['annotations'].append(annotation_item)
def parseXmlFiles(xml_path):
for f in os.listdir(xml_path):
if not f.endswith('.xml'):
continue
bndbox = dict()
size = dict()
current_image_id = None
current_category_id = None
file_name = None
size['width'] = None
size['height'] = None
size['depth'] = None
xml_file = os.path.join(xml_path, f)
print(xml_file)
tree = ET.parse(xml_file)
root = tree.getroot()
if root.tag != 'annotation':
raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))
# elem is <folder>, <filename>, <size>, <object>
for elem in root:
current_parent = elem.tag
current_sub = None
object_name = None
if elem.tag == 'folder':
continue
if elem.tag == 'filename':
file_name = elem.text
if file_name in category_set:
raise Exception('file_name duplicated')
# add img item only after parse <size> tag
elif current_image_id is None and file_name is not None and size['width'] is not None:
if file_name not in image_set:
current_image_id = addImgItem(file_name, size)
print('add image with {} and {}'.format(file_name, size))
else:
raise Exception('duplicated image: {}'.format(file_name))
# subelem is <width>, <height>, <depth>, <name>, <bndbox>
for subelem in elem:
bndbox['xmin'] = None
bndbox['xmax'] = None
bndbox['ymin'] = None
bndbox['ymax'] = None
current_sub = subelem.tag
if current_parent == 'object' and subelem.tag == 'name':
object_name = subelem.text
if object_name not in category_set:
current_category_id = addCatItem(object_name)
else:
current_category_id = category_set[object_name]
elif current_parent == 'size':
if size[subelem.tag] is not None:
raise Exception('xml structure broken at size tag.')
size[subelem.tag] = int(subelem.text)
# option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>
for option in subelem:
if current_sub == 'bndbox':
if bndbox[option.tag] is not None:
raise Exception('xml structure corrupted at bndbox tag.')
bndbox[option.tag] = int(option.text)
# only after parse the <object> tag
if bndbox['xmin'] is not None:
if object_name is None:
raise Exception('xml structure broken at bndbox tag')
if current_image_id is None:
raise Exception('xml structure broken at bndbox tag')
if current_category_id is None:
raise Exception('xml structure broken at bndbox tag')
bbox = []
# x
bbox.append(bndbox['xmin'])
# y
bbox.append(bndbox['ymin'])
# w
bbox.append(bndbox['xmax'] - bndbox['xmin'])
# h
bbox.append(bndbox['ymax'] - bndbox['ymin'])
print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,
bbox))
addAnnoItem(object_name, current_image_id, current_category_id, bbox)
if __name__ == '__main__':
xml_path = './datasets/RoadSignsPascalVOC/Annotations' # 这是xml文件所在的地址
json_file = './datasets/RoadSignsPascalVOC_Coco/Annotations/train.json' # 这是你用xml_path下的xml文件生成的json文件
parseXmlFiles(xml_path) # 只需要改动这两个参数就行了
json.dump(coco, open(json_file, 'w'))
转换好的coco格式的json文件我还未在训练中验证,但是我将转换后的json文件又通过第一份转voc的代码又转回voc格式,部署到训练中没有问题。
voc数据格式的处理
首先你的voc格式的数据集目录应该是这样的:
——annotations
——ImageSets
————Main
——images
其中annotations为你的xml标注文件,images为你的图片目录。
Main中保存划分数据集后的txt文件
来看看process_dataset.py中的代码:
'''
Author: TuZhou
Version: 1.0
Date: 2021-08-21 19:53:22
LastEditTime: 2021-08-29 17:05:35
LastEditors: TuZhou
Description: 划分数据集,将xml文件中的标注信息提取出与图片路径保存到新的txt文件中
FilePath: \My_Yolo\datasets\process_dataset.py
'''
from pathlib import Path
import yaml
import xml.etree.ElementTree as ET
from os import getcwd
import os
import random
random.seed()
#自定义数据集配置文件的路径
yaml_path = './cfg/dataset.yaml'
#----------------------------------------------------------------------#
# 想要增加测试集修改trainval_percent
# train_percent不需要修改
#----------------------------------------------------------------------#
trainval_percent = 0.9 #所有数据集中训练集+验证集的比例
train_percent = 1 #训练集+验证集中训练集的比例(可不管)默认1即可
'''
Author: TuZhou
Description: 读取数据集配置文件
param {*} yaml_path
return {*}返回配置文件中信息字典
'''
def read_dataset_yaml(yaml_path = './cfg/dataset.yaml'):
yaml_file = Path(yaml_path)
with open(yaml_file, encoding='utf-8') as f:
yaml_dict = yaml.safe_load(f)
return yaml_dict
'''
Author: TuZhou
Description: 从数据集中划分训练集,验证集,测试集,txt文件保存在ImageSets的Main文件夹中
param {*} xmlfilepath 数据集xml标注文件保存路径
param {*} saveSplitePath 数据集划分txt文件保存路径
return {*}
'''
def splite_dataset(xmlfilepath, saveSplitePath):
#读取所有xml文件,存入列表中
temp_xml = os.listdir(xmlfilepath)
total_xml = []
for xml in temp_xml:
if xml.endswith(".xml"):
total_xml.append(xml)
#图片总数
num = len(total_xml)
list = range(num)
numbers_tv = int(num * trainval_percent) #获取训练和验证集数量
numbers_train = int(numbers_tv * train_percent)
random.seed()
trainval = random.sample(list, numbers_tv) #从list中选取生成训练验证集的随机列表
random.seed()
train = random.sample(trainval, numbers_train) #从训练验证集中选取生成训练集的随机列表
print("train and val size: ", numbers_tv)
print("train size: ", numbers_train)
print("test size: ", num - numbers_tv)
ftrainval = open(os.path.join(saveSplitePath,'trainval.txt'), 'w')
ftest = open(os.path.join(saveSplitePath,'test.txt'), 'w')
ftrain = open(os.path.join(saveSplitePath,'train.txt'), 'w')
fval = open(os.path.join(saveSplitePath,'val.txt'), 'w')
for i in list:
name=total_xml[i][:-4]+'\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest .close()
def convert_annotation(xmlfilepath, image_id, list_file, classes):
#in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id), encoding='utf-8')
in_file = open(xmlfilepath + '%s.xml'%(image_id), encoding='utf-8')
tree=ET.parse(in_file)
root = tree.getroot()
for obj in root.iter('object'):
difficult = 0
if obj.find('difficult')!=None:
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult)==1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (int(float(xmlbox.find('xmin').text)), int(float(xmlbox.find('ymin').text)), int(float(xmlbox.find('xmax').text)), int(float(xmlbox.find('ymax').text)))
list_file.write(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id))
#print(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id))
def save_dataset_info(yaml_dict):
wd = getcwd()
sets = yaml_dict['sets']
saveSplitePath = yaml_dict['saveSplitePath']
xmlfilepath = yaml_dict['xmlfilepath']
processedPath = yaml_dict['DatasetPath']
ImagesDir = yaml_dict['ImagesDir']
classes = yaml_dict['classes']
image_format = yaml_dict['image_format']
for image_set in sets:
# image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set), encoding='utf-8').read().strip().split()
# list_file = open('%s_%s.txt'%(year, image_set), 'w', encoding='utf-8')
#读取划分后的图片名文件
image_ids = open(saveSplitePath + '%s.txt'%(image_set), encoding='utf-8').read().strip().split()
#创建要保存路径和标注的txt文件
list_file = open(processedPath + '%s.txt'%(image_set), 'w', encoding='utf-8')
for image_id in image_ids:
#list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg'%(wd, year, image_id))
list_file.write(wd + ImagesDir + image_id + image_format)
convert_annotation(xmlfilepath, image_id, list_file, classes)
list_file.write('\n')
list_file.close()
if __name__ == '__main__':
yaml_dict = read_dataset_yaml(yaml_path)
#划分数据集
xmlfilepath, saveSplitePath = yaml_dict['xmlfilepath'], yaml_dict['saveSplitePath']
splite_dataset(xmlfilepath, saveSplitePath)
#保存数据集信息,即图片路径以及标注信息
save_dataset_info(yaml_dict)
注意我对路径的一些配置保存在dataset.yaml文件中,你可先创建一个yaml文件保存一些配置。比如我的:
#数据集配置文件信息
#数据集xml标注文件保存路径
xmlfilepath: './datasets/RoadSignsPascalVOC_Voc/annotations/'
#数据集划分保存路径
saveSplitePath: './datasets/RoadSignsPascalVOC_Voc/ImageSets/Main/'
#数据集目录
DatasetPath: './datasets/RoadSignsPascalVOC_Voc/'
#图片路径,注意该路径开头前面要拼接根目录路径的,所以前面不要加'.'了
ImagesDir: '/datasets/RoadSignsPascalVOC_Voc/images/'
#图片的格式
image_format: '.png'
# 分类种类数量
numbers_classes: 4
# 分类名
classes: ["trafficlight", "stop", "speedlimit", "crosswalk"]
#classes: ["hero", "grass", "wild_monster", "dragon", "soldier", "tower", "buff", "crystal"]
#处理后的文件名,存放图片保存路径以及其对应的标注信息,可默认不修改
#sets: [('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
sets: ['train', 'val', 'test']
经过处理后你的数据集会被划分,并且xml文件中的内容会被提取出来。
Main文件夹中会生成这么几个文件:
里面保存的是划分后的图片文件名。
另外在你的数据集目录下会生成存储提取的xml信息的txt文件。
其中保存了每张图片的路径以及该图片的标注信息。
前面为图片路径,后面每五个数字为一组,表示图片中目标的左上角右下角x,y坐标以及对应的类别。
如果要处理的voc数据集中全部为测试集,可以更改process_dataset.py中的trainval_percent变量,将其赋值为0即可。
txt注释格式转coco
有的人拿到的数据集既不是voc,也不是coco格式,就直接就是处理好的txt格式,但是代码却是coco数据集或者voc数据集处理的形式,对于编码困难的可以试试以下转换方法,可以将txt转为coco,如果是voc格式,可以先转coco再通过上面的coco转voc再转换为voc格式。
注意你的txt注释文件形式是这样的:
annotations.txt:
图片文件名 x1 y1 x2 y2 label…
从左到右为图片文件名,目标左上角x坐标,目标左上角y坐标,目标右下角x坐标,目标右下角y坐标,目标所属类别
注意我的label是直接就是类别名,而不是int编号,为编号的直接category_id等于label就可
代码中几处需要修改的部分已经使用TODO中的NOTE标注出来了。
'''
Author: TuZhou
Version: 1.0
Date: 2021-09-11 16:50:47
LastEditTime: 2021-09-12 09:42:32
LastEditors: TuZhou
Description:
FilePath: \python_test\txt_to_coco.py
'''
import json
import cv2
import path
import os
#第一个coco json类型
bnd_id_start = 1
#NOTE:你的分类
class_map = {"tamper":0}
#你的图片id,可自定义
my_image_id = 20210000000
times = 0
json_dict = {
"images" : [],
"type" : "instances",
"annotations": [],
"categories" : []
}
'''
Author: TuZhou
Description:
param {*} L1:你的标注列表信息,注意只包含x1,y1,x2,y2,label,如[234,43,345,213,'person',34,54,23,34,'dog']
param {*} numbers:你要切分的长度,x1,y1,x2,y2,label长度为5
return {*}返回包含所有目标信息的二维列表
'''
def get_list_value(L1, numbers):
obj_list = []
for i in range(0, len(L1), numbers):
l2 = L1[i: i + numbers]
obj_list.append(l2)
return obj_list
# NOTE:这里是你的txt文件的读取
with open(r'E:\user\baidu_pan\CASIA_object_detection\annotations.txt','r') as f:
data = f.readlines()
bnd_id = bnd_id_start
#NOTE:这是你的图片格式,如果支持多种图片文件
images_format = ['.jpg', '.tif']
for d in data:
content = d.strip().split(" ")
print(content)
filename = content[0] #这里可能修改,txt文件每一行第一个属性是图片路径,通过split()函数把图像名分离出来就行
for image_format in images_format:
#NOTE:你的图片文件路径要改
image_path = 'E:\\user\\baidu_pan\\CASIA_object_detection\\CAISA_Train_Images\\' + content[0] + image_format
if os.path.exists(image_path):
break
img = cv2.imread(image_path)
print(image_path)
try:
height,width = img.shape[0],img.shape[1]
image_id = my_image_id
my_image_id += 1
except:
times +=1
print('file is error')
# type 已经填充
#定义image 填充到images里面
image = {
'file_name' : filename, #文件名
'height' : height, #图片的高
'width' : width, #图片的宽
'id' : image_id #图片的id,和图片名对应的
}
json_dict['images'].append(image)
#print(content[5])
# start_index = 1
# if start_index != len(content) - 1:
obj_lists = get_list_value(content[1:],5)
for obj_list in obj_lists:
#print(c)
#xmin,ymin,xmax,ymax,label = c.strip().split(" ")
xmin = int(obj_list[0])
ymin = int(obj_list[1])
xmax = int(obj_list[2])
ymax = int(obj_list[3])
o_width = abs(int(xmax) - int(xmin))
o_height = abs(int(ymax) - int(ymin))
area = o_width * o_height
category_id = class_map[obj_list[4]]
# #定义annotationhb
annotation = {
'area' : area, #
'iscrowd' : 0,
'image_id' : image_id, #图片的id
'bbox' :[xmin, ymin, o_width,o_height],
'category_id' : int(category_id), #类别的id 通过这个id去查找category里面的name
'id' : bnd_id, #唯一id ,可以理解为一个框一个Id
'ignore' : 0,
'segmentation' : []
}
print(category_id)
json_dict['annotations'].append(annotation)
bnd_id += 1
#
#定义categories
#你得类的名字(cid,cate)对应
classes = ['tamper']
for i in range(len(classes)):
cate = classes[i]
cid = i
category = {
'supercategory' : 'none',
'id' : cid, #类别的id ,一个索引,主键作用,和别的字段之间的桥梁
'name' : cate #类别的名字比如房子,船,汽车
}
json_dict['categories'].append(category)
json_fp = open("train.json",'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()
我知道还有的小伙伴的txt文件注释格式可以和我的不一样,是不是这样的?
image_path xmin,ymin,xmax,ymax,label …
首个是图片路径而不是图片名,坐标等信息时通过逗号分隔而不是空格。
问题不大,代码很好改。
'''
Author: TuZhou
Version: 1.0
Date: 2022-01-14 10:10:06
LastEditTime: 2022-01-14 10:58:49
LastEditors: TuZhou
Description:
FilePath: \My_Mobile_csp_Yolo2\datasets\txt_to_coco.py
'''
import json
import cv2
#第一个coco json类型
bnd_id_start = 1
times = 0
#分类部分在下面的代码
#你的图片id,可自定义
my_image_id = 20210000000
json_dict = {
"images" : [],
"type" : "instances",
"annotations": [],
"categories" : []
}
# 这里是你的txt文件的读取
with open(r'C:\Users\TuZhou\Desktop\desktop_code\My_Mobile_csp_Yolo2\datasets\RoadSignsPascalVOC\train.txt','r') as f:
data = f.readlines()
bnd_id = bnd_id_start
for d in data:
content = d.split(" ")
filename = content[0].split("/")[-1] #这里可能修改,txt文件每一行第一个属性是图片路径,通过split()函数把图像名分离出来就行
img = cv2.imread(content[0])
try:
height,width = img.shape[0],img.shape[1]
image_id = my_image_id
my_image_id += 1
except:
times +=1
print('file is error')
# type 已经填充
#定义image 填充到images里面
image = {
'file_name' : filename, #文件名
'height' : height, #图片的高
'width' : width, #图片的宽
'id' : image_id #图片的id,和图片名对应的
}
json_dict['images'].append(image)
#
for c in content[1:]:
#NOTE:注意这里你的坐标信息是通过逗号隔开,所以split(","),但是你也许是通过空格隔开,直接split(" ")就可。
xmin,ymin,xmax,ymax,label = c.strip().split(",")
xmin = int(xmin)
ymin = int(ymin)
xmax = int(xmax)
ymax = int(ymax)
o_width = abs(int(xmax) - int(xmin))
o_height = abs(int(ymax) - int(ymin))
area = o_width * o_height
category_id = label.strip()
# #定义annotationhb
annotation = {
'area' : area, #
'iscrowd' : 0,
'image_id' : image_id, #图片的id
'bbox' :[xmin, ymin, o_width,o_height],
'category_id' : int(category_id), #类别的id 通过这个id去查找category里面的name
'id' : bnd_id, #唯一id ,可以理解为一个框一个Id
'ignore' : 0,
'segmentation' : []
}
print(category_id)
json_dict['annotations'].append(annotation)
bnd_id += 1
#
#定义categories
#NOTE:你得类的名字(cid,cate)对应
# classes = ['0','1','2','3']
classes = ["trafficlight", "stop", "speedlimit", "crosswalk"]
for i in range(len(classes)):
cate = classes[i]
cid = i
category = {
'supercategory' : 'none',
'id' : cid, #类别的id ,一个索引,主键作用,和别的字段之间的桥梁
'name' : cate #类别的名字比如房子,船,汽车
}
json_dict['categories'].append(category)
json_fp = open(r"C:\Users\TuZhou\Desktop\desktop_code\My_Mobile_csp_Yolo2\datasets\RoadSignsPascalVOC\train.json",'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()
版权声明:本文为CSDN博主「良风抚旧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Arcofcosmos/article/details/119983270
暂无评论