目标检测:将yolo标注的txt文本转为VOC标注的xml文件

news2024/11/30 9:42:59

1、准备工作

目标检测数据的标注分为两种格式:

  • xml 解释性标签,左上角+右下角的坐标
  • txt 记事本文件,类别+x,y中心坐标+w,h的相对值

需要准备的数据有:

其中images为图像数据,labels为txt文本信息

注意:这里仅仅支持图像格式为 jpg 格式!!!

需要转换数据格式,可以参考这章:PYTHON 自动化办公:更改图片后缀_改变文件夹里面图片后缀名的pytorch代码-CSDN博客

classes.txt 文件需要自行准备,没有的话,只能遍历出来看看目标框的是什么:

关于目标检测任务中,YOLO(txt格式)标注文件的可视化_yolo标注可视化-CSDN博客

2、代码

如下:

import os
from PIL import Image
import shutil
from tqdm import tqdm


def main(IMG,LAB,CLS):
    images = [i.split('.jpg')[0] for i in os.listdir(IMG)]  # 数据

    if os.path.exists('VOCdevkit'):
        shutil.rmtree('VOCdevkit')
    os.makedirs('VOCdevkit')
    os.makedirs('VOCdevkit/VOC2007')
    os.makedirs('VOCdevkit/VOC2007/JPEGImages')
    os.makedirs('VOCdevkit/VOC2007/Annotations')

    for img in tqdm(images):
        with open(os.path.join('VOCdevkit/VOC2007/Annotations',img+'.xml'), 'w') as xml_files:
            shutil.copy(os.path.join(IMG, img + '.jpg'),'VOCdevkit/VOC2007/JPEGImages')
            image = Image.open(os.path.join(IMG, img + '.jpg'))
            img_w, img_h = image.size
            xml_files.write('<annotation>\n')
            xml_files.write('   <folder>folder</folder>\n')
            xml_files.write(f'   <filename>{img}.jpg</filename>\n')
            xml_files.write('   <source>\n')
            xml_files.write('   <database>Unknown</database>\n')
            xml_files.write('   </source>\n')
            xml_files.write('   <size>\n')
            xml_files.write(f'     <width>{img_w}</width>\n')
            xml_files.write(f'     <height>{img_h}</height>\n')
            xml_files.write(f'     <depth>3</depth>\n')
            xml_files.write('   </size>\n')
            xml_files.write('   <segmented>0</segmented>\n')
            with open(os.path.join(LAB,img + '.txt'), 'r') as f:
                # 以列表形式返回每一行
                lines = f.read().splitlines()
                for each_line in lines:
                    line = each_line.split(' ')
                    xml_files.write('   <object>\n')
                    xml_files.write(f'      <name>{CLS[int(line[0])]}</name>\n')
                    xml_files.write('      <pose>Unspecified</pose>\n')
                    xml_files.write('      <truncated>0</truncated>\n')
                    xml_files.write('      <difficult>0</difficult>\n')
                    xml_files.write('      <bndbox>\n')
                    center_x = round(float(line[1]) * img_w)
                    center_y = round(float(line[2]) * img_h)
                    bbox_w = round(float(line[3]) * img_w)
                    bbox_h = round(float(line[4]) * img_h)
                    xmin = str(int(center_x - bbox_w / 2))
                    ymin = str(int(center_y - bbox_h / 2))
                    xmax = str(int(center_x + bbox_w / 2))
                    ymax = str(int(center_y + bbox_h / 2))
                    xml_files.write(f'         <xmin>{xmin}</xmin>\n')
                    xml_files.write(f'         <ymin>{ymin}</ymin>\n')
                    xml_files.write(f'         <xmax>{xmax}</xmax>\n')
                    xml_files.write(f'         <ymax>{ymax}</ymax>\n')
                    xml_files.write('      </bndbox>\n')
                    xml_files.write('   </object>\n')
            xml_files.write('</annotation>')


if __name__ == '__main__':
    # images 需要是 jpg格式
    yoloImages = 'yolodata/images'
    yoloLabels = 'yolodata/labels'
    classTxt = 'classes.txt'

    txt = open(classTxt, 'r')
    txt = txt.read().splitlines()
    print(txt)

    main(IMG=yoloImages,LAB=yoloLabels,CLS=txt)

效果如下:

3、其他代码

可视化代码可以参考:

from lxml import etree
import cv2


# 读取 xml 文件信息,并返回字典形式
def parse_xml_to_dict(xml):
    if len(xml) == 0:  # 遍历到底层,直接返回 tag对应的信息
        return {xml.tag: xml.text}

    result = {}
    for child in xml:
        child_result = parse_xml_to_dict(child)  # 递归遍历标签信息
        if child.tag != 'object':
            result[child.tag] = child_result[child.tag]
        else:
            if child.tag not in result:  # 因为object可能有多个,所以需要放入列表里
                result[child.tag] = []
            result[child.tag].append(child_result[child.tag])
    return {xml.tag: result}


# xml 标注文件的可视化
def xmlShow(img, xml, save=True):
    image = cv2.imread(img)
    with open(xml, encoding='gb18030', errors='ignore') as fid:  # 防止出现非法字符报错
        xml_str = fid.read()
    xml = etree.fromstring(xml_str)
    data = parse_xml_to_dict(xml)["annotation"]  # 读取 xml文件信息

    ob = []  # 存放目标信息
    for i in data['object']:  # 提取检测框
        name = str(i['name'])  # 检测的目标类别

        bbox = i['bndbox']
        xmin = int(bbox['xmin'])
        ymin = int(bbox['ymin'])
        xmax = int(bbox['xmax'])
        ymax = int(bbox['ymax'])

        tmp = [name, xmin, ymin, xmax, ymax]  # 单个检测框
        ob.append(tmp)

    # 绘制检测框
    for name, x1, y1, x2, y2 in ob:
        cv2.rectangle(image, (x1, y1), (x2, y2), color=(255, 0, 0), thickness=2)  # 绘制矩形框
        cv2.putText(image, name, (x1, y1 - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                    fontScale=0.5, thickness=1, color=(0, 0, 255))

    # 保存图像
    if save:
        cv2.imwrite('result.png', image)

    # 展示图像
    cv2.imshow('test', image)
    cv2.waitKey()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    import os
    import random

    img_path = r'.\VOCdevkit\VOC2007\JPEGImages'  # 传入图片
    image = [os.path.join(img_path, i) for i in os.listdir(img_path)]
    r = random.randint(0, len(image) - 1)  # 生成随机索引

    image_path = image[r]
    labels_path = image_path.replace('JPEGImages', 'Annotations')  # 自动获取对应的 xml 标注文件
    labels_path = labels_path.replace('.jpg', '.xml')

    xmlShow(img=image_path, xml=labels_path, save=True)

至于xml生成标签的json字典文件,参考:

目标检测篇:如何根据xml标注文件生成类别classes的json文件_将xml 根据注解 解读 成类-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1815312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】已解决报错:NameError: name ‘xxx‘ is not defined

【Python】已解决报错&#xff1a;NameError: name ‘xxx‘ is not defined &#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大…

C++学习笔记(23)——二叉树进阶

系列文章 http://t.csdnimg.cn/QDR3y 目录 系列文章[TOC](目录) 1. 二叉树的优势2. 二叉搜索树概念3. 二叉搜索树操作1. 二叉搜索树的查找2. 二叉搜索树的插入——地址链接重设3. 二叉搜索树的删除——地址链接重设 4. 二叉搜索树的应用——以key为载体&#xff0c;承载复杂信…

618家用智能投影仪推荐:这个高性价比品牌不容错过

随着科技的不断进步&#xff0c;家庭影院的概念已经从传统的大屏幕电视逐渐转向了更为灵活和便携的家用智能投影仪。随着618电商大促的到来&#xff0c;想要购买投影仪的用户们也开始摩拳擦掌了。本文将从投影仪的基础知识入手&#xff0c;为您推荐几款性价比很高的投影仪&…

QGroupbox,Grid Layout,button 水平延伸 布局

实验 sizePolicy水瓶延伸 拖入一个groupbox控件 在groupbox控件中拖入一个grid layout 控件 然后拖入3个pushButton 使其水平排列&#xff0c; 设置button3的 sizePolicy 水平延展 为1 效果

工程项目管理系统:高效、专业的工程管理软件

在当今快速发展的工程行业&#xff0c;有效的项目管理是确保项目成功的关键。鸿鹄工程项目管理系统&#xff0c;基于Spring Cloud、Spring Boot、Mybatis、Vue和ElementUI技术栈&#xff0c;提供了一个全面、高效的解决方案&#xff0c;以应对复杂的工程项目管理挑战。 项目背景…

精益思维在人工智能中的应用体现

随着AI技术的广泛应用&#xff0c;如何提高其效率、降低成本、优化性能&#xff0c;成为了业界关注的焦点。精益思维作为一种追求卓越、持续改进的管理理念&#xff0c;其在人工智能中的应用正逐渐展现出巨大的潜力。 一、数据精益化管理。数据是AI技术的核心&#xff0c;而数据…

JavaScript知识之函数

javascript函数 在JavaScript基础之上提供了部分函数,同时也可以自定义函数,JavaScript基础详见之前的文章javascript基础知识 自定义函数 //关键字 函数名 参数列表 函数体 function test(a,b,c){alert(a":"b":"c) }function test1(a,b){return a;//不…

一文读懂Samtec分离式线缆组件选型 | 快速攻略

【摘要/前言】 2023年&#xff0c;全球线缆组件市场规模大致在2100多亿美元。汽车和电信行业是线缆组件最大的两个市场&#xff0c;中国和北美是最大的两个制造地区。有趣的是&#xff0c;特定应用&#xff08;即定制&#xff09;和矩形组件是两个最大的产品组。 【Samtec产品…

huggingface_hub LocalEntryNotFoundErroringface

报错详细 LocalEntryNotFoundError: An error happened while trying to locate the file on the Hub and we cannot find the requested files in the local cache. Please check your connection and try again or make sure your Internet connection is on.问题说明 在…

肾合养生秘诀:告别手心热出汗的困扰

如果将我们的身体比作一支精心编排的交响乐团&#xff0c;那么各个器官便是乐团中不可或缺的乐器和乐手&#xff0c;而气血则如同乐团中的乐谱和指挥棒&#xff0c;引领着整个乐团的演奏。当乐谱缺失&#xff0c;指挥棒失灵&#xff0c;或者乐团的协作出现问题&#xff0c;某些…

CAN转PROFINET,轻松实现降本增效!AGV行业必备连接通信方案大揭秘!

随着工厂自动化发展以及柔性制造系统、自动化立体仓库的广泛应用&#xff0c;已作为管理离散型装配、物流、仓储等系统不可或缺的自动化搬运装卸工具&#xff0c;智能化AGV系统可根据ERP订单进行仓库配料、分料、产品装配以及出入库、包装物流等环节。 AGV由导航系统、传感器系…

超声波风速风向传感器

TH-WQX2随着科技的不断发展&#xff0c;气象监测设备也在不断创新和完善。其中&#xff0c;超声波风速风向传感器以其独特的设计优势&#xff0c;在气象监测领域中脱颖而出&#xff0c;成为越来越多用户的首选。本文将详细阐述超声波风速风向传感器的设计优势&#xff0c;以便读…

3d模型交易的哪个网站好?

推荐一个国内的优秀专为3D模型交易服务的网站&#xff1a;老子云模型服务平台。 老子云3D可视化与模型优化服务平台https://www.laozicloud.com/ 老子云是以AMRT核心自主引擎构建的一家3D全栈技术服务平台&#xff0c;集合3D模型云处理、模型交易、模型应用、开发者服务、3D技…

ant-design-vue 的modal.confirm突然无法自动关闭

这个是我当前的版本 &#xff0c;点击不能 关闭&#xff0c; 版本的问题 修改 &#xff1a; "vue": "~3.2.0", 重新下包就ok了 参考 &#xff1a; antdesign的modal.confirm突然无法自动关闭_antdesign confirm点击后不关闭-CSDN博客

深度遍历-求“岛屿数量”

一、问题描述 二、解题思路 1.设置一个对应的boolean二维数组 isfind[][] &#xff0c;用来标记已经遍历过的“岛屿” 2.使用双层循环遍历岛屿&#xff08;grid&#xff09;二维数组&#xff0c;当遇到 isfind[i][j]false 时表示遇到一个新岛屿 3.当遇到新岛屿时进行深度递归…

【设计模式】结构型-享元模式

在浮华世界中&#xff0c;享元犹如静水深流&#xff0c;细品每一片风景&#xff0c;留下岁月的深情。 文章目录 一、内存溢出问题二、享元模式三、享元模式的核心组成四、运用享元模式五、享元模式的应用场景六、小结推荐阅读 一、内存溢出问题 class Circle {private String…

实现AI口语练习的技术库

国内实现AI口语练习的第三方技术库比较多&#xff0c;以下是一些国内实现AI口语练习的第三方技术库。开发人员可以根据自己的需求选择合适的技术库进行开发。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 讯飞开放平台&#xff1a; …

C++基础7:STL六大组件

目录 一、标准容器 1、顺序容器 vector ​编辑 deque list 容器适配器 stack queue prority_queue: 关联容器 有序关联容器set、mutiset、map、mutimap 增删查O(log n) 无序关联容 unordered_set、unordered_mutiset、unordered_map、unordered_mutimap 增删…

牛客热题:旋转矩阵

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;旋转矩阵题目链接方法一&#x…

Exploring Performance and Cost Optimization with ASIC-Based CXL Memory——论文阅读

EuroSys 2024 Paper CXL论文阅读笔记整理 问题 随着内存密集型应用程序对内存需求的增加&#xff0c;受限于物理限制&#xff0c;如DDR DIMM插槽的可用性和发热问题&#xff0c;以及使用高密度DIMM的成本考虑&#xff0c;现代应用程序的内存需求很容易超过单机的内存容量[2&a…