os.path.abspath(path) | 返回绝对路径 |
os.path.basename(path) | 返回文件名 |
os.path.dirname(path) | 返回文件路径 |
os.path.exists(path) | 如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。 |
os.path.join(path1[, path2[, ...]]) | 把目录和文件名合成一个路径 |
os.path.normcase(path) | 转换path的大小写和斜杠 |
os.path.normpath(path) | 规范path字符串形式 |
os.path.realpath(path) | 返回path的真实路径 |
os.path.split(path) | 把路径分割成 dirname 和 basename,返回一个元组 |
os.path.splitext(path) | 分割路径,返回路径名和文件扩展名的元组 |
print( os.path.basename('/root/runoob.txt') ) # 返回文件名
print( os.path.dirname('/root/runoob.txt') ) # 返回目录路径
print( os.path.split('/root/runoob.txt') ) # 分割文件名与路径
print( os.path.join('root','test','runoob.txt') ) # 将目录和文件名合成一个路径
执行以上程序输出结果为:
runoob.txt /root ('/root', 'runoob.txt') root/test/runoob.txt
shutil.copy() 模块具体用法 shutil.copy(source, destination)(这种复制形式使用的前提是必须要有 os.chdir(你要处理的路径)) source/destination 都是字符串形式的路劲,其中destination是: 1、可以是一个文件的名称,则将source文件复制为新名称的destination 2、可以是一个文件夹,则将source文件复制到destination中 3、若这个文件夹不存在,则将source目标文件内的内容复制到destination中 shutil.copytree() 模块具体用法 shutil.copytree(source, destination)(这种复制形式无需 os.chdir() 便可操作) source 、 destination 可以是不同的文件夹、不同的硬盘空间, 可以更为方便的实现文件的备份
目标检测数据集的格式一般有.json(coco)、.txt(yolo)、.xml(voc)
本博客主要总结不同数据集格式之间的转换。
voc数据集格式介绍参考见VOC数据集格式介绍_望天边星宿的博客-CSDN博客_voc数据集格式
XML解析常用于ET.parse
常用操作:
tree = ET.parse(xml_path)
root = tree.getroot() # 获取根节点
node.tag # 获取节点名字,string
node…attrib # 获取节点全部属性,dict
要想遍历某一层节点下的子节点,貌似只可以一层一层,从根节点开始,慢慢遍历:
xml文件用上一篇的xml即可,写了小段实际操作代码 如下:
def xml_read(content):
tree = ET.parse('../../../../androidmanifest.xml')
root = tree.getroot()
for child in root:
if child.tag == 'application':
for child1 in child:
if child1.tag == 'activity':
for key, value in child1.attrib.items():
if value == content:
str_tag = ''
str_attrib = ''
for inter_child in child1:
if inter_child.tag == 'intent-filter':
for child2 in inter_child:
str_tag += child2.tag + '|'
for key, value in child2.attrib.items():
str_attrib += value + '|'
if 'action' in str_tag and 'category' in str_tag and len(inter_child) == 2 and 'android.intent.action.MAIN' in str_attrib and 'android.intent.category.LAUNCHER' in str_attrib:
return True
else:
return False
代码的主要意思就是:
1.先通过根节点获取application节点,再在application中遍历tag名称为activity的标签
2.获取activity节点的属性,,若其中有和content相同的话,那么我们继续遍历activity节下的子节点(跳到步骤3),如果没有和content相同的话,就不用理会;
3. 先判断有没有intent-filter节点,没有则后面判读会失败,如果有,则继续遍历intent-filter下所有节点中是不是有action和category,如果有,则继续判断这两个标签的属性值,是不是和下面的if条件中符合,符合则返回结果为true,不符合或者没有action\category其中任意一个子节点的话,都是返回false。
coco数据集格式介绍参考见coco数据集格式介绍_ Clear butterfly的博客-CSDN博客_coco数据集格式
1、xmin,ymin,width,height 转为 xmin,ymin,xmax,ymax
前2个坐标不需要动,只需要动后2个,规则如下:
xmax= xmin+width-1
ymax= ymin+height-1
[xmin, ymin, xmin+width-1, ymin+height-1]
2、xmin,ymin,xmax,ymax 转为 x,y,width,height
前2个坐标不需要动,只需要动后2个,规则如下:
width = xmax-xmin+1
height = ymax-ymin+1
[xmin, ymin, xmax-xmin+1, ymax-ymin+1]
关键词:VOC数据集和COCO数据集之间对应的关系。
voc2coco.py完整代码:
#实现voc数据集格式(.xml)-->coco数据集格式(.json)
import os
import shutil
import numpy as np
import json
import xml.etree.ElementTree as ET
# 检测框的ID起始值
START_BOUNDING_BOX_ID = 1
# 类别列表无必要预先创建,程序中会根据所有图像中包含的ID来创建并更新
PRE_DEFINE_CATEGORIES = {}
# If necessary, pre-define category and its id
PRE_DEFINE_CATEGORIES = {"crazing": 1, "inclusion": 2, "patches": 3, "pitted_surface": 4,
"rolled-in_scale":5, "scratches": 6}
#遍历xml树根的节点信息
def get(root, name):
vars = root.findall(name)
return vars
def get_and_check(root, name, length):
vars = root.findall(name)
if len(vars) == 0:
raise NotImplementedError('Can not find %s in %s.'%(name, root.tag))
if length > 0 and len(vars) != length:
raise NotImplementedError('The size of %s is supposed to be %d, but is %d.'%(name, length, len(vars)))
if length == 1:
vars = vars[0]
return vars
def convert(xml_list, xml_dir, json_file):
'''
:param xml_list: 需要转换的XML文件列表
:param xml_dir: XML的存储文件夹
:param json_file: 导出json文件的路径
:return: None
'''
list_fp = xml_list
image_id=0
# 标注json的基本结构
json_dict = {"images":[],
"type": "instances",
"annotations": [],
"categories": []}
categories = PRE_DEFINE_CATEGORIES
bnd_id = START_BOUNDING_BOX_ID
for line in list_fp:
line = line.strip()
print(" Processing {}".format(line))
# 解析XML
#使用root.find / root.findall()方法在xml中定位所需的信息;
#然后使用(.text)返回child/grandchild元素的值。
xml_f = os.path.join(xml_dir, line)
tree = ET.parse(xml_f)
root = tree.getroot()
filename = root.find('filename').text # 取出图片名字
image_id+=1
size = get_and_check(root, 'size', 1)
# 图片的基本信息
width = int(get_and_check(size, 'width', 1).text)
height = int(get_and_check(size, 'height', 1).text)
image = {'file_name': filename,
'height': height,
'width': width,
'id':image_id}
json_dict['images'].append(image)
# [循环嵌套]处理每个标注的检测框
for obj in get(root, 'object'):
# 取出检测框类别名称
category = get_and_check(obj, 'name', 1).text
# 更新类别ID字典
if category not in categories:
new_id = len(categories)
categories[category] = new_id+1
category_id = categories[category]
bndbox = get_and_check(obj, 'bndbox', 1)
xmin = int(get_and_check(bndbox, 'xmin', 1).text) - 1
ymin = int(get_and_check(bndbox, 'ymin', 1).text) - 1
xmax = int(get_and_check(bndbox, 'xmax', 1).text)
ymax = int(get_and_check(bndbox, 'ymax', 1).text)
assert(xmax > xmin)
assert(ymax > ymin)
o_width = abs(xmax - xmin)
o_height = abs(ymax - ymin)
annotation = dict()
annotation['area'] = o_width*o_height
annotation['iscrowd'] = 0
annotation['image_id'] = image_id
annotation['bbox'] = [xmin, ymin, o_width, o_height]
annotation['category_id'] = category_id
annotation['id'] = bnd_id
annotation['ignore'] = 0
# 设置分割数据,点的顺序为逆时针方向
annotation['segmentation'] = [[xmin,ymin,xmin,ymax,xmax,ymax,xmax,ymin]]
json_dict['annotations'].append(annotation)
bnd_id = bnd_id + 1
# 写入类别ID字典
for cate, cid in categories.items():
cat = {'supercategory': 'none', 'id': cid, 'name': cate}
json_dict['categories'].append(cat)
# 导出到json
#mmcv.dump(json_dict, json_file)????
#print(type(json_dict))
json_data = json.dumps(json_dict)
with open(json_file, 'w') as w:
w.write(json_data)
if __name__ == '__main__':
root_path = './'
#生成coco-2014格式
if not os.path.exists(os.path.join(root_path,'coco/annotations')):
os.makedirs(os.path.join(root_path,'coco/annotations'))
if not os.path.exists(os.path.join(root_path, 'coco/train')):
os.makedirs(os.path.join(root_path, 'coco/train'))
if not os.path.exists(os.path.join(root_path, 'coco/val')):
os.makedirs(os.path.join(root_path, 'coco/val'))
#####{可修改}xml文件地址
##注意分开xml和图片
xml_dir = os.path.join(root_path,'xml555') ##或:xml_dir = 'path'
##划分训练集和验证集
xml_labels = os.listdir(xml_dir)
np.random.shuffle(xml_labels)
#9:1划分
split_point = int(len(xml_labels)/10)
# validation data
xml_list = xml_labels[0:split_point]
json_file = os.path.join(root_path,'coco/annotations/instances_val.json')
convert(xml_list, xml_dir, json_file)
for xml_file in xml_list:
img_name = xml_file[:-4] + '.jpg'
#####{可修改}voc图片路径
shutil.copy(os.path.join(root_path, 'voc', img_name),
os.path.join(root_path, 'coco/val', img_name)) #复制文件(夹)
# train data
xml_list = xml_labels[split_point:]
json_file = os.path.join(root_path,'coco/annotations/instances_train.json')
convert(xml_list, xml_dir, json_file)
for xml_file in xml_list:
img_name = xml_file[:-4] + '.jpg'
#####{可修改}voc图片路径
shutil.copy(os.path.join(root_path, 'voc', img_name),
os.path.join(root_path, 'coco/train', img_name))
import json
import os
import xml.etree.ElementTree as ET
import cv2
# 标准化输出x, y, w, h格式
# 将x1, y1, x2, y2转换成yolov5所需要的x, y, w, h格式
def xyxy2xywh(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[2]) / 2 * dw
y = (box[1] + box[3]) / 2 * dh
w = (box[2] - box[0]) * dw
h = (box[3] - box[1]) * dh
return (x, y, w, h)
def json2txt(path):
#print(len(os.listdir(path)))
pic_path = 'E:/Desktop/pv/pic' # 原始图片路径
txt_out_path = './backgr' # 转换后txt保存路径
# 遍历每一个json文件
for file in os.listdir(path):
print(file)
if "json" in str(file):
with open(os.path.join(path, file), 'r') as f:
data = json.load(f)
#print(data)
points = data['shapes'][0]['points']
pic = file.split('.')[0]+'.png'
pic_name = os.path.join(pic_path, pic)
txt_name = file.split(".")[0] + ".txt"
imread = cv2.imread(pic_name)
h = imread.shape[0]
w = imread.shape[1]
print(imread.shape)
xmin = points[0][0]
ymin = points[0][1]
xmax = points[2][0]
ymax = points[2][1]
box = [float(xmin), float(ymin), float(xmax),
float(ymax)]
#print(box)
# # 将x1, y1, x2, y2转换成yolov5所需要的x, y, w, h格式
bbox = xyxy2xywh((w, h), box)
print(bbox)
# # 写入目标文件中,格式为 id x y w h
with open(os.path.join(txt_out_path, txt_name), 'w') as out_file:
out_file.write(str(1) + " " + " ".join(str(x) for x in bbox) + '\n')
out_file.close()
#exit()
if __name__ == '__main__':
# json格式数据路径
jsonpath = './json'
json2txt(jsonpath)
import os
import json
import cv2
import random
import time
from PIL import Image
coco_format_save_path='./' #要生成的标准coco格式标签所在文件夹
yolo_format_classes_path='./cls.txt' #类别文件,一行一个类
yolo_format_annotation_path='./pv-txt' #yolo格式标签所在文件夹
img_pathDir='./pv-agu' #图片所在文件夹
with open(yolo_format_classes_path,'r') as fr: #打开并读取类别文件
lines1=fr.readlines()
# print(lines1)
categories=[] #存储类别的列表
for j,label in enumerate(lines1):
label=label.strip()
categories.append({'id':j+1,'name':label,'supercategory':'None'}) #将类别信息添加到categories中
# print(categories)
write_json_context=dict() #写入.json文件的大字典
write_json_context['info']= {'description': '', 'url': '', 'version': '', 'year': 2022, 'contributor': '', 'date_created': '2022-10-24'}
write_json_context['licenses']=[{'id':1,'name':None,'url':None}]
write_json_context['categories']=categories
write_json_context['images']=[]
write_json_context['annotations']=[]
#接下来的代码主要添加'images'和'annotations'的key值
imageFileList=os.listdir(img_pathDir) #遍历该文件夹下的所有文件,并将所有文件名添加到列表中
for i,imageFile in enumerate(imageFileList):
imagePath = os.path.join(img_pathDir,imageFile) #获取图片的绝对路径
image = Image.open(imagePath) #读取图片,然后获取图片的宽和高
W, H = image.size
img_context={} #使用一个字典存储该图片信息
#img_name=os.path.basename(imagePath) #返回path最后的文件名。如果path以/或\结尾,那么就会返回空值
img_context['file_name']=imageFile
img_context['height']=H
img_context['width']=W
img_context['date_captured']='2022-10-24'
img_context['id']=i #该图片的id
img_context['license']=1
img_context['color_url']=''
img_context['flickr_url']=''
write_json_context['images'].append(img_context) #将该图片信息添加到'image'列表中
txtFile=imageFile[:18]+'.txt' #获取该图片获取的txt文件
with open(os.path.join(yolo_format_annotation_path,txtFile),'r') as fr:
lines=fr.readlines() #读取txt文件的每一行数据,lines2是一个列表,包含了一个图片的所有标注信息
for j,line in enumerate(lines):
bbox_dict = {} #将每一个bounding box信息存储在该字典中
# line = line.strip().split()
# print(line.strip().split(' '))
class_id,x,y,w,h=line.strip().split(' ') #获取每一个标注框的详细信息
class_id,x, y, w, h = int(class_id), float(x), float(y), float(w), float(h) #将字符串类型转为可计算的int和float类型
xmin=(x-w/2)*W #坐标转换
ymin=(y-h/2)*H
xmax=(x+w/2)*W
ymax=(y+h/2)*H
w=w*W
h=h*H
bbox_dict['id']=i #bounding box的坐标信息
bbox_dict['image_id']=i
bbox_dict['category_id']=class_id #注意目标类别要加一
bbox_dict['iscrowd']=0
height,width=abs(ymax-ymin),abs(xmax-xmin)
bbox_dict['area']=height*width
bbox_dict['bbox']=[xmin,ymin,w,h]
bbox_dict['segmentation']=[[xmin,ymin,xmax,ymin,xmax,ymax,xmin,ymax]]
write_json_context['annotations'].append(bbox_dict) #将每一个由字典存储的bounding box信息添加到'annotations'列表中
name = os.path.join(coco_format_save_path,"train"+ '.json')
with open(name,'w') as fw: #将字典信息写入.json文件中
json.dump(write_json_context,fw,indent=2)