目录
数据集类型介绍
voc
coco
yolo
图像数据标注工具介绍
①labelimg
②labelme
③Coovally
④百度飞桨BMI
⑤GeoLabel
VOC 数据集由五个部分构成:JPEGImages,Annotations,ImageSets,SegmentationClass 以及 SegmentationObject.
voc 数据集的标签主要以 xml 文件形式进行存放。
xml 文件的标注格式如下:
17 # 图片所处文件夹
77258.bmp # 图片名
~/frcnn-image/61/ADAS/image/frcnn-image/17/77258.bmp
#图片尺寸
640
480
3
0 #是否有分割label
COCO 数据集现在有 3 种标注类型,分别是:
这 3 种类型共享这些基本类型:info、image、license,使用 JSON 文件存储。
json 文件的标注格式如下:
以 Object Instance 为例,这种格式的文件从头至尾按照顺序分为以下段落:
{
"info": info, # dict
"licenses": [license], # list,内部是dict
"images": [image], # list,内部是dict
"annotations": [annotation],# list,内部是dict
"categories": [category] # list,内部是dict
}
info{ # 数据集信息描述
"year": int, # 数据集年份
"version": str, # 数据集版本
"description": str, # 数据集描述
"contributor": str, # 数据集提供者
"url": str, # 数据集下载链接
"date_created": datetime, # 数据集创建日期
}
license{
"id": int,
"name": str,
"url": str,
}
image{ # images是一个list,存放所有图片(dict)信息。image是一个dict,存放单张图片信息
"id": int, # 图片的ID编号(每张图片ID唯一)
"width": int, # 图片宽
"height": int, # 图片高
"file_name": str, # 图片名字
"license": int, # 协议
"flickr_url": str, # flickr链接地址
"coco_url": str, # 网络连接地址
"date_captured": datetime, # 数据集获取日期
}
annotation{ # annotations是一个list,存放所有标注(dict)信息。annotation是一个dict,存放单个目标标注信息。
"id": int, # 目标对象ID(每个对象ID唯一),每张图片可能有多个目标
"image_id": int, # 对应图片ID
"category_id": int, # 对应类别ID,与categories中的ID对应
"segmentation": RLE or [polygon], # 实例分割,对象的边界点坐标[x1,y1,x2,y2,....,xn,yn]
"area": float, # 对象区域面积
"bbox": [xmin,ymin,width,height], # 目标检测,对象定位边框[x,y,w,h]
"iscrowd": 0 or 1, # 表示是否是人群
}
categories{ # 类别描述
"id": int, # 类别对应的ID(0默认为背景)
"name": str, # 子类别名字
"supercategory": str, # 主类别名字
}
yolo 数据集标注格式主要是 U 版本 yolov5 项目需要用到。
标签使用 txt 文本进行保存。
yolo 标注格式如下所示:
例如:
0 0.412500 0.318981 0.358333 0.636111
推荐程度:☆☆☆☆☆
简单易上手,面向新手友好,支持文件夹批量打开图片、保存图片,支持voc、coco、creatML三种数据集格式
利用 labelimg 制作自己的深度学习目标检测数据集
推荐程度:☆☆☆
貌似只能逐一手动保存???有点坑&不便捷
深度学习图像标签标注软件 labelme 超详细教程
【Coovally】强大工具:一键转换 voc、coco、yolo、csv 等格式的数据集
吊打 labelme,它才是图像标注界的 yyds
GeoLabel处理数据集格式转换、可视化与编辑更新
目标检测中数据集格式之间的相互转换 --coco、voc、yolo
# 作 者:Leo
# 时 间:2022/11/15 19:12
import xml.etree.ElementTree as ET
import os
from tqdm import tqdm
import cv2
'''
base_xml_dir为xml文件夹路径
kitti_saved_dir为要保存的kitti文件夹的路径,转化前,先把输出文件夹创建好
'''
base_xml_dir = "E:\\PyProject\\tools\\ba\\a\\xml\\"
xml_list = os.listdir(base_xml_dir)
kitti_saved_dir = "E:\\PyProject\\tools\\ba\\a\\kitti\\"
clslist = []
def convert_annotation(file_name):
#print('********')
#print(base_xml_dir,file_name)
in_file = open(base_xml_dir + file_name, 'rb')
tree = ET.parse(in_file)
root = tree.getroot()
with open(kitti_saved_dir + file_name[:-4] + '.txt', 'w') as f:
for obj in root.iter('object'):
cls = obj.find('name').text
# if cls not in object_class_list:
# object_class_list.append(cls)
xmlbox = obj.find('bndbox')
"""
第5~8这4个数:物体的2维边界框
xmin,ymin,xmax,ymax
"""
xmin, ymin, xmax, ymax = xmlbox.find('xmin').text, xmlbox.find('ymin').text, \
xmlbox.find('xmax').text, xmlbox.find('ymax').text
a = int(xmin)
b = int(ymin)
c = int(xmax)
d = int(ymax)
#print(xmin, ymin, xmax, ymax)
#print(type(float(xmin)))
#cv2.rectangle(image, (xmlbox.find('xmin').text, xmlbox.find('ymin').text), (xmlbox.find('xmax').text, xmlbox.find('ymax').text), (0, 0, 255), 2)
#cv2.rectangle(image, (0, 55), (224, 263), (0, 0, 255), 2)
#print(cls)
if cls == 'Peel_the_fruit':
#print('******1*******')
#print(cls)
cls = 'banane'
#cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
#print('香蕉皮')
#print(cls)
#print('******2*******')
elif cls == 'pop_top_can':
#print(cls)
cls = 'bottle'
#cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
#print('瓶子1')
elif cls == 'drink_bottle':
cls = 'bottle'
#cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
#print('瓶子2')
elif cls == 'carton_carton':
#print(cls)
cls = 'CARDBOARD'
#cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
#print('纸箱')
elif cls == 'Drink_box':
cls = 'CARDBOARD'
#cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
else:
pass
if cls == 'banane' or cls == 'bottle' or cls == 'CARDBOARD':
f.write(cls + " " + '0.00' + " " + '0' + " " + '0.0' + " " + str(xmin) + " "
+ str(ymin) + " " + str(xmax) + " " + str(ymax) + " " +
'0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + '\n')
# object_class_list = [] # ['trafficsignal', 'car', 'person', 'trafficlight', 'bicycle', 'motorbike', 'bus']
for i in tqdm(range(len(xml_list))):
#image_name = xml_list[i].replace('xml', 'jpg')
#image = cv2.imread(image_name)
#cv2.rectangle(image, (0, 55), (224, 263), (0, 0, 255), 2)
convert_annotation(xml_list[i])
#cv2.imwrite(image_name.replace('.jpg', '-box.jpg'), image)
#print('原始',xml_list[i])
#print('最后', image_name, xml_list[i])
# print(i)
#print(clslist)
# print(object_class_list)
# 作 者:Leo
# 时 间:2022/11/21 21:14
import os
from tqdm import tqdm
import cv2
'''
base_img_dir为未打框图片的文件夹路径
base_label_dir为kitti标签格式的文件夹路径
op_img_dir为打框后的图片输出的文件夹路径,需要在输出钱创建好
'''
base_img_dir = "E:\\PyProject\\tools\\t1\\image_comb\\"
base_label_dir = "E:\\PyProject\\tools\\t1\\kitti_img\\"
op_img_dir = "E:\\PyProject\\tools\\t1\\img-box\\"
img_list = os.listdir(base_img_dir)
label_list = os.listdir(base_label_dir)
def draw_imgbox(image, label):
for line in open(label, "r", encoding='UTF-8'):
line_list = []
line_list = line.split(' ')
line_list = line_list[0:1] + line_list[4:8]
print(line_list)
cv2.rectangle(img_file, (int(line_list[1]), int(line_list[2])), (int(line_list[3]), int(line_list[4])), (0, 0, 255), 2)
for i in tqdm(range(len(img_list))):
print('第' + str(i) + '张')
img_file = cv2.imread(base_img_dir + img_list[i])
label_file = label_list[i]
draw_imgbox(img_file, base_label_dir + label_file)
cv2.imwrite(op_img_dir + img_list[i].replace('.jpg', '-box.jpg'), img_file)