首页 前端知识 目标检测-数据处理,YOLO2JSON、VOC2YOLO、YOLO2VOC、JSON2YOLO

目标检测-数据处理,YOLO2JSON、VOC2YOLO、YOLO2VOC、JSON2YOLO

2024-09-06 00:09:38 前端知识 前端哥 467 170 我要收藏

1、YOLO格式转JSON格式

2、 VOC格式转YOLO格式

3、YOLO格式转VOC格式

4、JSON格式转YOLO格式 


1、YOLO格式转JSON格式

"""

YOLO转JSON格式

"""

import os
import cv2
import json
import argparse
from tqdm import tqdm
import xml.etree.ElementTree as ET

COCO_DICT=['images','annotations','categories']
IMAGES_DICT=['file_name','height','width','id']

ANNOTATIONS_DICT=['image_id','iscrowd','area','bbox','category_id','id']

CATEGORIES_DICT=['id','name']

#自定义YOLO数据集类别
YOLO_CATEGORIES=['Cahua', 'Crazing']

parser=argparse.ArgumentParser(description='2COCO')
#需修改:图片所在路径
parser.add_argument('--image_path',type=str,default=r'D:\desk\defect_dataset\images\test/',help='config file')

#需修改:标签所在路径
parser.add_argument('--annotation_path',type=str,default=r'D:\desk\defect_dataset\labels\test/',help='config file')

parser.add_argument('--dataset',type=str,default='YOLO',help='config file')

#需修改:JSON文件保存位置
parser.add_argument('--save',type=str,default=r'D:\desk\defect_dataset\JASON/instances_test2017.json',help='config file')
args=parser.parse_args()
def load_json(path):
	with open(path,'r') as f:
		json_dict=json.load(f)
		for i in json_dict:
			print(i)
		print(json_dict['annotations'])
def save_json(dict,path):
	print('SAVE_JSON...')
	with open(path,'w') as f:
		json.dump(dict,f)
	print('SUCCESSFUL_SAVE_JSON:',path)
def load_image(path):
	img=cv2.imread(path)
	return img.shape[0],img.shape[1]
def generate_categories_dict(category):       #ANNOTATIONS_DICT=['image_id','iscrowd','area','bbox','category_id','id']
	print('GENERATE_CATEGORIES_DICT...')
	return [{CATEGORIES_DICT[0]:category.index(x)+1,CATEGORIES_DICT[1]:x} for x in category]  #CATEGORIES_DICT=['id','name']
def generate_images_dict(imagelist,image_path,start_image_id=11725):  #IMAGES_DICT=['file_name','height','width','id']
	print('GENERATE_IMAGES_DICT...')
	images_dict=[]
	with tqdm(total=len(imagelist)) as load_bar:
		for x in imagelist:  #x就是图片的名称
			#print(start_image_id)
			dict={IMAGES_DICT[0]:x,IMAGES_DICT[1]:load_image(image_path+x)[0],\
					IMAGES_DICT[2]:load_image(image_path+x)[1],IMAGES_DICT[3]:imagelist.index(x)+start_image_id}
			load_bar.update(1)
			images_dict.append(dict)
	return images_dict

def YOLO_Dataset(image_path,annotation_path,start_image_id=0,start_id=0):
	categories_dict=generate_categories_dict(YOLO_CATEGORIES)
	imgname=os.listdir(image_path)
	images_dict=generate_images_dict(imgname,image_path)
	print('GENERATE_ANNOTATIONS_DICT...')
	annotations_dict=[]
	id=start_id
	for i in images_dict:
		image_id=i['id']
		image_name=i['file_name']
		W,H=i['width'],i['height']
		annotation_txt=annotation_path+image_name.split('.')[0]+'.txt'
		txt=open(annotation_txt,'r')
		lines=txt.readlines()
		for j in lines:
			category_id=int(j.split(' ')[0])+1
			category=YOLO_CATEGORIES
			x=float(j.split(' ')[1])
			y=float(j.split(' ')[2])
			w=float(j.split(' ')[3])
			h=float(j.split(' ')[4])
			x_min=(x-w/2)*W
			y_min=(y-h/2)*H
			w=w*W
			h=h*H
			area=w*h
			bbox=[x_min,y_min,w,h]
			dict={'image_id':image_id,'iscrowd':0,'area':area,'bbox':bbox,'category_id':category_id,'id':id}
			annotations_dict.append(dict)
			id=id+1
	print('SUCCESSFUL_GENERATE_YOLO_JSON')
	return {COCO_DICT[0]:images_dict,COCO_DICT[1]:annotations_dict,COCO_DICT[2]:categories_dict}

if __name__=='__main__':
	dataset=args.dataset   #数据集名字
	save=args.save  #json的保存路径
	image_path=args.image_path     #对于coco是图片的路径
	annotation_path=args.annotation_path   #coco的annotation路径
	if dataset=='YOLO':
		json_dict=YOLO_Dataset(image_path,annotation_path,0)
	save_json(json_dict,save)

 上述代码中仅需要修改以下部分,再运行即可完成YOLO格式转换为JSON格式。

23行
#自定义YOLO数据集类别
YOLO_CATEGORIES=['Cahua', 'Crazing']
27行
#需修改:图片所在路径
parser.add_argument('--image_path',type=str,default=r'D:\desk\defect_dataset\images\test/',help='config file')
30行
#需修改:标签所在路径
parser.add_argument('--annotation_path',type=str,default=r'D:\desk\defect_dataset\labels\test/',help='config file')
35行
parser.add_argument('--save',type=str,default=r'D:\desk\defect_dataset\JASON/instances_test2017.json',help='config file')

2、 VOC格式转YOLO格式

"""

VOC转YOLO格式

"""
import xml.etree.ElementTree as ET
import os, cv2
import numpy as np
from os import listdir
from os.path import join

#需修改,添加数据集的类别
classes = []

def convert(size, box):
    dw = 1. / (size[0])
    dh = 1. / (size[1])
    x = (box[0] + box[1]) / 2.0 - 1
    y = (box[2] + box[3]) / 2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def convert_annotation(xmlpath, xmlname):
    with open(xmlpath, "r", encoding='utf-8') as in_file:
        txtname = xmlname[:-4] + '.txt'
        txtfile = os.path.join(txtpath, txtname)
        tree = ET.parse(in_file)
        root = tree.getroot()
        filename = root.find('filename')
        img = cv2.imdecode(np.fromfile('{}/{}.{}'.format(imgpath, xmlname[:-4], postfix), np.uint8), cv2.IMREAD_COLOR)
        h, w = img.shape[:2]
        res = []
        for obj in root.iter('object'):
            cls = obj.find('name').text
            if cls not in classes:
                classes.append(cls)
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            bb = convert((w, h), b)
            res.append(str(cls_id) + " " + " ".join([str(a) for a in bb]))
        if len(res) != 0:
            with open(txtfile, 'w+') as f:
                f.write('\n'.join(res))


if __name__ == "__main__":
#确保图片后缀为统一的jpg格式
    postfix = 'jpg'

#需修改,改为自己的图片所在位置
    imgpath = r'D:\desk\defect_dataset\IMG'

#需修改,改为自己的VOC标签格式所在位置
    xmlpath = r'D:\desk\defect_dataset\VOC'

#需修改,改为自己的想保存YOLO标签格式所在位置
    txtpath = r'D:\desk\defect_dataset\TXT'
    
    if not os.path.exists(txtpath):
        os.makedirs(txtpath, exist_ok=True)
    
    list = os.listdir(xmlpath)
    error_file_list = []
    for i in range(0, len(list)):
        try:
            path = os.path.join(xmlpath, list[i])
            if ('.xml' in path) or ('.XML' in path):
                convert_annotation(path, list[i])
                print(f'file {list[i]} convert success.')
            else:
                print(f'file {list[i]} is not xml format.')
        except Exception as e:
            print(f'file {list[i]} convert error.')
            print(f'error message:\n{e}')
            error_file_list.append(list[i])
    print(f'this file convert failure\n{error_file_list}')
    print(f'Dataset Classes:{classes}')

 上述代码中仅需要修改以下部分,再运行即可完成VOC格式转换为YOLO格式 

7行
# 需修改,添加数据集的类别
classes = []
54行
# 需修改,改为自己的图片所在位置
imgpath = r'D:\desk\defect_dataset\IMG'

57行
# 需修改,改为自己的VOC标签格式所在位置
xmlpath = r'D:\desk\defect_dataset\VOC'

60行
# 需修改,改为自己的想保存YOLO标签格式所在位置
txtpath = r'D:\desk\defect_dataset\TXT'

 3、YOLO格式转VOC格式

"""

YOLO转VOC格式

"""

from xml.dom.minidom import Document
import os
import cv2

def makexml(picPath, txtPath, xmlPath):  # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径

#需修改,数据集类别,注意一一对应
    dic = {'0': "crazing",
           '1': "patches",
           '2' :'inclusion',
           '3': "pitted_surface",
           '4': "rolled-in_scale",
           '5': "scratches",
           }

    files = os.listdir(txtPath)
    for i, name in enumerate(files):
        xmlBuilder = Document()
        annotation = xmlBuilder.createElement("annotation")  # 创建annotation标签
        xmlBuilder.appendChild(annotation)
        txtFile = open(txtPath + name)
        txtList = txtFile.readlines()
        img = cv2.imread(picPath + name[0:-4] + ".jpg")
        Pheight, Pwidth, Pdepth = img.shape

        folder = xmlBuilder.createElement("folder")  # folder标签
        foldercontent = xmlBuilder.createTextNode("driving_annotation_dataset")
        folder.appendChild(foldercontent)
        annotation.appendChild(folder)  # folder标签结束

        filename = xmlBuilder.createElement("filename")  # filename标签
        filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg")
        filename.appendChild(filenamecontent)
        annotation.appendChild(filename)  # filename标签结束

        size = xmlBuilder.createElement("size")  # size标签
        width = xmlBuilder.createElement("width")  # size子标签width
        widthcontent = xmlBuilder.createTextNode(str(Pwidth))
        width.appendChild(widthcontent)
        size.appendChild(width)  # size子标签width结束

        height = xmlBuilder.createElement("height")  # size子标签height
        heightcontent = xmlBuilder.createTextNode(str(Pheight))
        height.appendChild(heightcontent)
        size.appendChild(height)  # size子标签height结束

        depth = xmlBuilder.createElement("depth")  # size子标签depth
        depthcontent = xmlBuilder.createTextNode(str(Pdepth))
        depth.appendChild(depthcontent)
        size.appendChild(depth)  # size子标签depth结束

        annotation.appendChild(size)  # size标签结束

        for j in txtList:
            oneline = j.strip().split(" ")
            object = xmlBuilder.createElement("object")  # object 标签
            picname = xmlBuilder.createElement("name")  # name标签
            namecontent = xmlBuilder.createTextNode(dic[oneline[0]])
            picname.appendChild(namecontent)
            object.appendChild(picname)  # name标签结束

            pose = xmlBuilder.createElement("pose")  # pose标签
            posecontent = xmlBuilder.createTextNode("Unspecified")
            pose.appendChild(posecontent)
            object.appendChild(pose)  # pose标签结束

            truncated = xmlBuilder.createElement("truncated")  # truncated标签
            truncatedContent = xmlBuilder.createTextNode("0")
            truncated.appendChild(truncatedContent)
            object.appendChild(truncated)  # truncated标签结束

            difficult = xmlBuilder.createElement("difficult")  # difficult标签
            difficultcontent = xmlBuilder.createTextNode("0")
            difficult.appendChild(difficultcontent)
            object.appendChild(difficult)  # difficult标签结束

            bndbox = xmlBuilder.createElement("bndbox")  # bndbox标签
            xmin = xmlBuilder.createElement("xmin")  # xmin标签
            mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth)
            xminContent = xmlBuilder.createTextNode(str(mathData))
            xmin.appendChild(xminContent)
            bndbox.appendChild(xmin)  # xmin标签结束

            ymin = xmlBuilder.createElement("ymin")  # ymin标签
            mathData = int(((float(oneline[2])) * Pheight + 1) - (float(oneline[4])) * 0.5 * Pheight)
            yminContent = xmlBuilder.createTextNode(str(mathData))
            ymin.appendChild(yminContent)
            bndbox.appendChild(ymin)  # ymin标签结束

            xmax = xmlBuilder.createElement("xmax")  # xmax标签
            mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth)
            xmaxContent = xmlBuilder.createTextNode(str(mathData))
            xmax.appendChild(xmaxContent)
            bndbox.appendChild(xmax)  # xmax标签结束

            ymax = xmlBuilder.createElement("ymax")  # ymax标签
            mathData = int(((float(oneline[2])) * Pheight + 1) + (float(oneline[4])) * 0.5 * Pheight)
            ymaxContent = xmlBuilder.createTextNode(str(mathData))
            ymax.appendChild(ymaxContent)
            bndbox.appendChild(ymax)  # ymax标签结束

            object.appendChild(bndbox)  # bndbox标签结束

            annotation.appendChild(object)  # object标签结束

        f = open(xmlPath + name[0:-4] + ".xml", 'w')
        xmlBuilder.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8')
        f.close()


if __name__ == "__main__":

	# 需修改,图片所在文件夹路径
    picPath = r"D:\desk\defect_dataset\IMG/"

	# 需修改,YOLO标签所在文件夹路径
    txtPath = r"D:\desk\defect_dataset\TXT/"

	# 需修改,VOC文件保存路径
    xmlPath = r"D:\desk\defect_dataset\VOC/"

    makexml(picPath, txtPath, xmlPath)

  上述代码中仅需要修改以下部分,再运行即可完成YOLO格式转换为VOC格式 

11行
#需修改,数据集类别,注意一一对应
    dic = {'0': "crazing",
           '1': "patches",
           '2' :'inclusion',
           '3': "pitted_surface",
           '4': "rolled-in_scale",
           '5': "scratches",
           }
117行
# 需修改,图片所在文件夹路径
   picPath = r"D:\desk\defect_dataset\IMG/"

120行
# 需修改,YOLO标签所在文件夹路径
   txtPath = r"D:\desk\defect_dataset\TXT/"

123行
# 需修改,VOC文件保存路径
   xmlPath = r"D:\desk\defect_dataset\VOC/"

4、JSON格式转YOLO格式 

# COCO 格式的数据集转化为 YOLO 格式的数据集
# --json_path 输入的json文件路径
# --save_path 保存的文件夹名字,默认为当前目录下的labels。

import os
import json
from tqdm import tqdm
import argparse

parser = argparse.ArgumentParser()
# 需修改,这里替换自己的json文件位置
parser.add_argument('--json_path',
                    default=r'D:\desk\asssssssssssssss\try\json\instances_val2017.json', type=str,
                    help="input: coco format(json)")

# 需修改,这里输出的txt文件保存位置
parser.add_argument('--save_path', default=r'D:\desk\asssssssssssssss\try\txt', type=str,
                    help="specify where to save the output dir of labels")

# 需修改,这里设置json标签对应的图片文件位置
parser.add_argument('--img_path', default=r'D:\desk\asssssssssssssss\try\img', type=str,
                    help="all img path")

arg = parser.parse_args()


def convert(size, box):
    dw = 1. / (size[0])
    dh = 1. / (size[1])
    x = box[0] + box[2] / 2.0
    y = box[1] + box[3] / 2.0
    w = box[2]
    h = box[3]
    # round函数确定(xmin, ymin, xmax, ymax)的小数位数
    x = round(x * dw, 6)
    w = round(w * dw, 6)
    y = round(y * dh, 6)
    h = round(h * dh, 6)
    return (x, y, w, h)


if __name__ == '__main__':
    json_file = arg.json_path  # COCO Object Instance 类型的标注
    ana_txt_save_path = arg.save_path  # 保存的路径

    data = json.load(open(json_file, 'r'))
    if not os.path.exists(ana_txt_save_path):
        os.makedirs(ana_txt_save_path)

    id_map = {}  # coco数据集的id不连续!重新映射一下再输出!
    with open(os.path.join(ana_txt_save_path, 'classes.txt'), 'w') as f:
        # 写入classes.txt
        for i, category in enumerate(data['categories']):
            f.write(f"{category['name']}\n")
            id_map[category['id']] = i
    # print(id_map)
    # 这里需要根据自己的需要,更改写入图像相对路径的文件位置。
    list_file = open(os.path.join(ana_txt_save_path, 'train2017.txt'), 'w')
    for img in tqdm(data['images']):
        filename = img["file_name"]
        img_width = img["width"]
        img_height = img["height"]
        img_id = img["id"]
        head, tail = os.path.splitext(filename)
        ana_txt_name = head + ".txt"  # 对应的txt名字,与jpg一致
        f_txt = open(os.path.join(ana_txt_save_path, ana_txt_name), 'w')
        for ann in data['annotations']:
            if ann['image_id'] == img_id:
                box = convert((img_width, img_height), ann["bbox"])
                f_txt.write("%s %s %s %s %s\n" % (id_map[ann["category_id"]], box[0], box[1], box[2], box[3]))
        f_txt.close()
        list_file.write(os.path.join(arg.img_path,r'%s.jpg\n') % (head))#修改

    list_file.close()

 上述代码中仅需要修改以下部分,再运行即可完成JSON格式转换为YOLO格式  

11行
# 需修改,这里替换自己的json文件位置
parser.add_argument('--json_path',
                    default=r'D:\desk\asssssssssssssss\try\json\instances_val2017.json', type=str,
                    help="input: coco format(json)")

16行
# 需修改,这里输出的txt文件保存位置
parser.add_argument('--save_path', default=r'D:\desk\asssssssssssssss\try\txt', type=str,
                    help="specify where to save the output dir of labels")

20行
# 需修改,这里设置json标签对应的图片文件位置
parser.add_argument('--img_path', default=r'D:\desk\asssssssssssssss\try\img', type=str,
                    help="all img path")

代码仅用于本人学习使用

转载请注明出处或者链接地址:https://www.qianduange.cn//article/17762.html
评论
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!