YOLOv8教程系列:三、使用YOLOv8模型进行自定义数据集半自动标注

news2024/11/15 16:48:58

YOLOv8半自动标注

目标检测半自动标注的优点包括:

1.提高标注效率:算法能够自动标注部分数据,减少了人工标注的工作量,节省时间和资源。
2.降低成本:自动标注可以减少人工标注的成本,特别是对于大规模数据集来说,人工标注成本非常昂贵。
3.提高标注的一致性和准确性:计算机算法可以提供相对准确的初始标注,人工验证和修正后,可以确保标注的一致性和准确性。
4.改善数据集的质量:通过自动标注和人工验证,可以更全面地标注数据集,提高数据集的质量和丰富性。

具体而言:

1.根据现有数据集,训练一个YOLOv8 模型;
2.使用 YOLOv8 模型对图片进行目标检测,得到目标检测的结果;
3.将目标检测的结果转换为 XML 文件格式,保存预测好的 XML 文件。

新建一个名为generateXml.py文件

import os
import cv2
import datetime


class GenerateJpgAndXml:
    """
    参数名含义:
    parentName:存放jpg和xml上一级文件夹名字,如person

    """
    def __init__(self, parentName, labelDict):
        self.parentName = parentName
        # 存放所有文件的主文件夹路径
        self.parentPath = "./JpgAndXml"
        self.midPath = os.path.join(self.parentPath, self.parentName)
        # 存放jpg文件夹名字
        self.jpgName = "images"
        # 存放xml文件夹名字
        self.xmlName = "Annotations"
        # 存放标签的字典
        self.labelDict = labelDict
        # 第一次进来,需要判断下文件夹是否存在
        self.isExist()

    def isExist(self):
        # 存放jpg文件的文件夹
        self.jpgPath = os.path.join(self.midPath, self.jpgName)
        # 存放xml文件的文件夹
        self.xmlPath = os.path.join(self.midPath, self.xmlName)
        # 判断jpg和xml文件夹是否存在,不存在则创建
        for perPath in [self.jpgPath, self.xmlPath]:
            # 判断所在目录下是否有该文件名的文件夹
            if not os.path.exists(perPath):
                # 创建多级目录用mkdirs
                # print(f"创建成功,已创建文件夹{perPath}")
                os.makedirs(perPath)
            # else:
                # print(f"创建失败,已存在文件夹{perPath}"


    def generatr_xml(self, frame, result):
        # print('开始写xml')
        # 获取当前时间戳
        xmlPrefix = datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")
        # print(xmlPrefix)
        hwc = frame.shape
        # jpg名字
        jpgName = xmlPrefix + ".jpg"
        # jpg路径
        jpgPath = os.path.join(self.jpgPath, jpgName)
        # 写图片
        cv2.imwrite(jpgPath, frame)
        # xml路径
        xmlPath = os.path.join(self.xmlPath, xmlPrefix + ".xml")
        with open(xmlPath, 'w') as xml_file:
            xml_file.write('<annotation>\n')
            xml_file.write('\t<folder>' + self.parentName +'</folder>\n')
            xml_file.write('\t<filename>' + jpgName + '</filename>\n')
            xml_file.write('\t<path>' + jpgPath + '</path>\n')
            xml_file.write('\t<source>\n')
            xml_file.write('\t\t<database>' + 'Unknown' + '</database>\n')
            xml_file.write('\t</source>\n')
            xml_file.write('\t<size>\n')
            xml_file.write('\t\t<width>' + str(hwc[1]) + '</width>\n')
            xml_file.write('\t\t<height>' + str(hwc[0]) + '</height>\n')
            xml_file.write('\t\t<depth>'+str(hwc[2])+'</depth>\n')
            xml_file.write('\t</size>\n')
            xml_file.write('\t<segmented>0</segmented>\n')

            for re in result:
                ObjName = self.labelDict[re[0]]
                # [[0, 0.8, 110, 25, 150, 60], [1, 0.5, 40, 10, 50, 90]]
                xmin = int(re[2])
                ymin = int(re[3])
                xmax = int(re[4])
                ymax = int(re[5])

                xml_file.write('\t<object>\n')
                xml_file.write('\t\t<name>' + ObjName + '</name>\n')
                xml_file.write('\t\t<pose>Unspecified</pose>\n')
                xml_file.write('\t\t<truncated>0</truncated>\n')
                xml_file.write('\t\t<difficult>0</difficult>\n')
                xml_file.write('\t\t<bndbox>\n')
                xml_file.write('\t\t\t<xmin>' + str(xmin) + '</xmin>\n')
                xml_file.write('\t\t\t<ymin>' + str(ymin) + '</ymin>\n')
                xml_file.write('\t\t\t<xmax>' + str(xmax) + '</xmax>\n')
                xml_file.write('\t\t\t<ymax>' + str(ymax) + '</ymax>\n')
                # xml_file.write('\t\t\t<angle>' + str(4) + '</angle>\n')
                xml_file.write('\t\t</bndbox>\n')
                # xml_file.write('\t\t<extra/>\n')
                xml_file.write('\t</object>\n')
            xml_file.write('</annotation>')
        # customPrint(f"{jpgPath}的jpg和xml已写入")

新建名为yolov8_infer.py的文件,修改模型、标签名以及图片文件夹即可

from ultralytics import YOLO
from generateXml import GenerateJpgAndXml
import numpy as np
import os
import cv2

# 加载yolov8模型
model = YOLO('runs/detect/train23/weights/best.pt',)
# 修改为自己的标签名
label_dict = {0: 'gray', 1: 'line', 2: 'black', 3: 'big_black'}
parent_name = label_dict[0]

yolov8_xml = GenerateJpgAndXml(parent_name, label_dict)


# 指定图片所在文件夹的路径
image_folder_path = 'data/images'

# 获取文件夹中所有的文件名
file_names = os.listdir(image_folder_path)

# 遍历每个文件
for file_name in file_names:
    # 判断是否是图片文件
    if file_name.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
        # 图片的完整路径
        image_path = os.path.join(image_folder_path, file_name)

        # 使用OpenCV读取图片
        img = cv2.imread(image_path)

        # Perform object detection on an image using the model
        results = model.predict(source=img,
                                conf=0.1,
                                max_det=300,
                                iou=0.4,
                                half=True,
                                imgsz=640
                                )

        # print(results)
        for result in results:
            xyxy = result.to("cpu").numpy().boxes.xyxy
            print(result)
            # 假设 xyxy, conf 和 cls 分别是三个 NumPy 数组
            conf = result.to("cpu").numpy().boxes.conf
            cls = result.to("cpu").numpy().boxes.cls
            conf_expanded = np.expand_dims(conf, axis=1)  # 在轴 1 上扩充
            cls_expanded = np.expand_dims(cls, axis=1)    # 在轴 1 上扩充
            xyxy = xyxy.astype(np.int32)

            # 使用 numpy.concatenate() 在轴 1 上拼接数组
            concatenated_array = np.concatenate((cls_expanded, conf_expanded, xyxy), axis=1)
            print(concatenated_array)
            
            yolov8_xml.generatr_xml(img, concatenated_array)
            print(concatenated_array)

    print('-'*50)


运行过程截图
在这里插入图片描述

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

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

相关文章

如何在线制作闪图?手把手教你快速生成GIF闪图

网上那种卟玲卟领的闪动GIF图片效果非常的炫丽&#xff0c;这种GIF闪图是怎么制作的呢&#xff1f;很简单&#xff0c;只需要使用专业的gif制作&#xff08;https://www.gif.cn/&#xff09;工具-GIF中文网&#xff0c;上传多张颜色、大小不同&#xff0c;内容相同的jpg、png格…

ORB-SLAM3数据集配置与评价

在ORB-SLAM3运行EuRoC和TUM-VI数据集并作以评价。EuRoC利用微型飞行器(MAV ) 收集的视觉惯性数据集&#xff0c;TUM-VI 是由实验人员手持视觉-惯性传感器收集的数据集。这两个是在视觉SLAM中比较常用的公开数据集&#xff0c;所以测试并加以记录。 文章目录 一、EuRoC数据集测…

音频转文字软件免费版让你快速完成转换

音频转文字技术是一种将音频文件转换为文本形式的技术&#xff0c;它可以帮助人们更方便地获取和处理音频信息。在实际生活和工作中&#xff0c;我们可能会遇到需要将音频转换为文字的情况&#xff0c;比如听取会议录音、收听讲座、学习外语等等。那么&#xff0c;你知道音频转…

Tinkercad 建模21个小技巧

21个Tinkercad 建模小技巧 原文 参考文章&#xff1a;在 Tinkercad 中加快设计的 22 个技巧 一起来了解一下21个Tinkercad 3D建模小技巧&#xff0c;让你快人一步。 技巧1 Copy & Paste 文件&#xff0c;整合设计 想把文件A里面的模型拷贝到文件B里面&#xff1f; 很容…

【Linux命令200例】mren一个用于重命名文件或目录的命令行工具

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

msvcr100.dll丢失怎样修复?最新的三个修复方法可解决

最近我遇到了一个问题&#xff0c;电脑提示我缺少了msvcr100.dll文件&#xff0c;导致某些程序无法正常运行。这让我意识到了计算机中的一些系统文件的重要性&#xff0c;也让我体会到了修复这类问题的必要性。msvcr100.dll文件是Windows系统中重要的文件&#xff0c;这是一个动…

docker容器的安装(windows、linux本地安装和在线安装)

目录 一、Docker发行版本&#xff1a; 1、Windows安装Docker&#xff08;作为了解&#xff09; 2、Linux安装Docker 二、安装前准备&#xff1a; 三、默认的yum安装 四、安装docker-ce 五、阿里云镜像加速器 Docker支持在主流的操作系统平台上使用&#xff0c;包括Windo…

飞致云开源社区月度动态报告(2023年7月)

自2023年6月起&#xff0c;中国领先的开源软件公司FIT2CLOUD飞致云将以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大…

el-table点击表格某一行添加到URL参数,访问带参URL加载表格内容并滚动到选中行位置 [Vue3] [Element-plus 2.3]

写在最前 需求&#xff1a;有个表格列出了一些行数据&#xff0c;每个行数据点击后会加载出对应的详细数据&#xff0c;想要在点击了某一行后&#xff0c;能够将该点击反应到URL中&#xff0c;这样我复制这个URL发给其他人&#xff0c;他们打开时也能看到同样的行数据。 url会根…

app自动化测试之Appium问题分析及定位

使用 Appium 进行测试时&#xff0c;会产生大量日志&#xff0c;一旦运行过程中遇到报错&#xff0c;可以通过 Appium 服务端的日志以及客户端的日志分析排查问题。 Appium Server日志-开启服务 通过命令行的方式启动 Appium Server&#xff0c;下面来分析一下启动日志&#…

C# 模拟 Unity3d 协程

一、概述 由于 Unity3d 在开发游戏时使用的是单线程&#xff0c;为了给开发者提供异步相关的操作&#xff0c;于是开发者在 Unity3d 中加入了协程的概念&#xff0c;协程在 Unity3d 中用的非常多&#xff0c;也有些大佬觉得这玩意儿不好用&#xff0c;还不如用一些插件。 在 …

若依vue -【 44 ~ 53 】

44 服务监控讲解 1 需求 显示CPU、内存、服务器信息、Java虚拟机信息、磁盘状态的信息 2 前端 RuoYi-Vue\ruoyi-ui\src\views\monitor\server\index.vue <script> import { getServer } from "/api/monitor/server";export default {name: "Server&quo…

Linux 查看磁盘空间

1 查看当前目录的总大小 &#xff1a;du -sh ps&#xff1a;du(disk usage) 2 查看某个目录的总大小&#xff1a;du -sh 目录名 3 查找出/目录下占用空间最大的前10个文件或者文件夹&#xff1a;sudo du -a / | sort -n -r | head -n 10 4 查看磁盘信息:df -h

旧项目导入Eclipse时文件夹看起来乱七八糟,无从下手的解决办法(无main或webapp等文件夹)

首先&#xff0c;如果没有main或java/resource/webapp等文件夹&#xff0c;那就自己在src下面创建一个&#xff0c;只要对应关系与我下图左边红框一致即可&#xff0c;创建完之后java文件移到java文件夹下&#xff0c;资源文件例如.properties、老项目的数据源定义.INI文件、日…

Vue2 第十二节 Vue组件化编程(一)

1.模块与组件&#xff0c;模块化与组件化概念 2. 非单文件组件 3. 组件编写注意事项 4. 组件的嵌套 一. 模块与组件&#xff0c;模块化与组件化 传统方式编写存在的问题 &#xff08;1&#xff09;依赖关系混乱&#xff0c;不好维护 &#xff08;2&#xff09;代码的复用…

基于SWAT-MODFLOW地表水与地下水耦合

目录 第一讲 模型原理剖析 第二讲 QGIS高级操作 第三讲 QSWATMOD操作 第四讲 数据制备 第五讲 基于CUP的率定验证 第六讲 结果分析 第七讲 控制措施效果模拟 第八讲 土地变化情景模拟 第九讲 气候变化情景模拟 更多推荐 耦合模型被应用到很多科学和工程领域来改善模型…

谷歌: 安卓补丁漏洞让 N-days 与 0-days 同样危险

近日&#xff0c;谷歌发布了年度零日漏洞报告&#xff0c;展示了 2022 年的野外漏洞统计数据&#xff0c;并强调了 Android 平台中长期存在的问题&#xff0c;该问题在很长一段时间内提高了已披露漏洞的价值和使用。 更具体地说&#xff0c;谷歌的报告强调了安卓系统中的 &quo…

ChatGLM-6B VS 昆仑万维天工对比

下面进行昆仑万维天工与ChatGLM-6B内测结果进行对比&#xff0c;其中ChatGLM-6B的结果来自https://github.com/THUDM/ChatGLM-6B&#xff0c;假设ChatGLM-6B的结果是可靠的&#xff0c;那么为了公平&#xff0c;昆仑万维天工&#xff08;https://tiangong.kunlun.com/interlocu…

OSG3.6.5 + VS2017前期准备及编译

OSG3.6.5 VS2017前期准备及编译 1、前期准备 1.1、osg稳定版本源码 Stable releases (openscenegraph.com) 1.2、osg依赖项 Dependencies (openscenegraph.com) 1.3、osg测试及演示数据 Data Resources (openscenegraph.com) 1.4、安装doxygen和Graphviz&#xff08;用…

组件化、跨平台…未来前端框架将如何演进?

前端框架在过去几年间取得了显著的进步和演进。前端框架也将继续不断地演化&#xff0c;以满足日益复杂的业务需求和用户体验要求。从全球web发展角度看&#xff0c;框架竞争已经从第一阶段的前端框架之争&#xff08;比如Vue、React、Angular等&#xff09;&#xff0c;过渡到…