记录yolov8_obb训练自己的数据集

一.数据集制作

1.标注软件:roLabelImg

roLabelImg是基于labelImg改进的,是用来标注为VOC格式的数据,但是在labelImg的基础上增加了能够使标注的框进行旋转的功能。

2.数据格式转换

2.1 xml转txt

# 文件名称   :roxml_to_dota.py
# 功能描述   :把rolabelimg标注的xml文件转换成dota能识别的xml文件,
#             再转换成dota格式的txt文件
#            把旋转框 cx,cy,w,h,angle,或者矩形框cx,cy,w,h,转换成四点坐标x1,y1,x2,y2,x3,y3,x4,y4
import os
import xml.etree.ElementTree as ET
import math

cls_list=['mouse']
def edit_xml(xml_file, dotaxml_file):
    """
    修改xml文件
    :param xml_file:xml文件的路径
    :return:
    """


    #dxml_file = open(xml_file,encoding='gbk')
    #tree = ET.parse(dxml_file).getroot()

    tree = ET.parse(xml_file)
    objs = tree.findall('object')
    for ix, obj in enumerate(objs):
        x0 = ET.Element("x0")  # 创建节点
        y0 = ET.Element("y0")
        x1 = ET.Element("x1")
        y1 = ET.Element("y1")
        x2 = ET.Element("x2")
        y2 = ET.Element("y2")
        x3 = ET.Element("x3")
        y3 = ET.Element("y3")
        # obj_type = obj.find('bndbox')
        # type = obj_type.text
        # print(xml_file)

        if (obj.find('robndbox') == None):
            obj_bnd = obj.find('bndbox')
            obj_xmin = obj_bnd.find('xmin')
            obj_ymin = obj_bnd.find('ymin')
            obj_xmax = obj_bnd.find('xmax')
            obj_ymax = obj_bnd.find('ymax')
            #以防有负值坐标
            xmin = max(float(obj_xmin.text),0)
            ymin = max(float(obj_ymin.text),0)
            xmax = max(float(obj_xmax.text),0)
            ymax = max(float(obj_ymax.text),0)
            obj_bnd.remove(obj_xmin)  # 删除节点
            obj_bnd.remove(obj_ymin)
            obj_bnd.remove(obj_xmax)
            obj_bnd.remove(obj_ymax)
            x0.text = str(xmin)
            y0.text = str(ymax)
            x1.text = str(xmax)
            y1.text = str(ymax)
            x2.text = str(xmax)
            y2.text = str(ymin)
            x3.text = str(xmin)
            y3.text = str(ymin)
        else:
            obj_bnd = obj.find('robndbox')
            obj_bnd.tag = 'bndbox'  # 修改节点名
            obj_cx = obj_bnd.find('cx')
            obj_cy = obj_bnd.find('cy')
            obj_w = obj_bnd.find('w')
            obj_h = obj_bnd.find('h')
            obj_angle = obj_bnd.find('angle')
            cx = float(obj_cx.text)
            cy = float(obj_cy.text)
            w = float(obj_w.text)
            h = float(obj_h.text)
            angle = float(obj_angle.text)
            obj_bnd.remove(obj_cx)  # 删除节点
            obj_bnd.remove(obj_cy)
            obj_bnd.remove(obj_w)
            obj_bnd.remove(obj_h)
            obj_bnd.remove(obj_angle)

            x0.text, y0.text = rotatePoint(cx, cy, cx - w / 2, cy - h / 2, -angle)
            x1.text, y1.text = rotatePoint(cx, cy, cx + w / 2, cy - h / 2, -angle)
            x2.text, y2.text = rotatePoint(cx, cy, cx + w / 2, cy + h / 2, -angle)
            x3.text, y3.text = rotatePoint(cx, cy, cx - w / 2, cy + h / 2, -angle)


        # obj.remove(obj_type)  # 删除节点
        obj_bnd.append(x0)  # 新增节点
        obj_bnd.append(y0)
        obj_bnd.append(x1)
        obj_bnd.append(y1)
        obj_bnd.append(x2)
        obj_bnd.append(y2)
        obj_bnd.append(x3)
        obj_bnd.append(y3)

        tree.write(dotaxml_file, method='xml', encoding='utf-8')  # 更新xml文件


# 转换成四点坐标
def rotatePoint(xc, yc, xp, yp, theta):
    xoff = xp - xc;
    yoff = yp - yc;
    cosTheta = math.cos(theta)
    sinTheta = math.sin(theta)
    pResx = cosTheta * xoff + sinTheta * yoff
    pResy = - sinTheta * xoff + cosTheta * yoff
    return str(int(xc + pResx)), str(int(yc + pResy))


def totxt(xml_path, out_path):
    # 想要生成的txt文件保存的路径,这里可以自己修改

    files = os.listdir(xml_path)
    i=0
    for file in files:

        tree = ET.parse(xml_path + os.sep + file)
        root = tree.getroot()

        name = file.split('.')[0]

        output = out_path +'\\'+name + '.txt'
        file = open(output, 'w')
        i=i+1
        objs = tree.findall('object')
        for obj in objs:
            cls = obj.find('name').text
            box = obj.find('bndbox')
            x0 = int(float(box.find('x0').text))
            y0 = int(float(box.find('y0').text))
            x1 = int(float(box.find('x1').text))
            y1 = int(float(box.find('y1').text))
            x2 = int(float(box.find('x2').text))
            y2 = int(float(box.find('y2').text))
            x3 = int(float(box.find('x3').text))
            y3 = int(float(box.find('y3').text))
            if x0<0:
                x0=0
            if x1<0:
                x1=0
            if x2<0:
                x2=0
            if x3<0:
                x3=0
            if y0<0:
                y0=0
            if y1<0:
                y1=0
            if y2<0:
                y2=0
            if y3<0:
                y3=0
            for cls_index,cls_name in enumerate(cls_list):
                if cls==cls_name:
                    file.write("{} {} {} {} {} {} {} {} {} {}\n".format(x0, y0, x1, y1, x2, y2, x3, y3, cls,cls_index))
        file.close()
        # print(output)
        print(i)

if __name__ == '__main__':
    # -----**** 第一步:把xml文件统一转换成旋转框的xml文件 ****-----
    roxml_path = 'data_mouse_ro_1/org_xml' 
    dotaxml_path = 'data_mouse_ro_1/dotaxml'  
    out_path = 'data_mouse_ro_1/dotatxt'   
    filelist = os.listdir(roxml_path)
    for file in filelist:
        edit_xml(os.path.join(roxml_path, file), os.path.join(dotaxml_path, file))

    # -----**** 第二步:把旋转框xml文件转换成txt格式 ****-----
    totxt(dotaxml_path, out_path)

2.2 dota_to_yolo_obb

dota数据格式:937.0 913.0 921.0 912.0 923.0 874.0 940.0 875.0 small-vehicle 0

yolo_obb格式:class_index, x1, y1, x2, y2, x3, y3, x4, y4

sys.path.append('/path/to/ultralytics')
from ultralytics.data.converter import convert_dota_to_yolo_obb
convert_dota_to_yolo_obb('/home/fut/project/ultralytics-main/ultralytics/datasets_ro')

跳转到convert_dota_to_yolo_obb.py函数,对class_mapping进行修改 

2.3 分割数据集

数据集文件分布格式如下:

datasets
	--images
		--train
		--val
	--labelTxt
		--trian
		--val

分割代码:

import os
import random
import shutil

# 设置随机数种子
random.seed(42)

# 数据集文件夹路径和输出文件夹路径
data_folder = 'data_mouse_ro_1'
img_folder = 'data_mouse_ro_1/dataset/images'
label_folder = 'data_mouse_ro_1/dataset/labels'

# 计算每个子集的大小
total_files = len(os.listdir(os.path.join(data_folder, 'img')))
train_size = int(total_files * 0.9)
test_size = int(total_files - train_size)

# 获取所有图像文件的文件名列表
image_files = os.listdir(os.path.join(data_folder, 'img'))
random.shuffle(image_files)

# 复制图像和标注文件到相应的子集文件夹中
for i, image_file in enumerate(image_files):
    base_file_name = os.path.splitext(image_file)[0]
    image_path = os.path.join(data_folder, 'img', image_file)
    label_path = os.path.join(data_folder, 'dotatxt', base_file_name + '.txt')

    if i < train_size:
        print(image_path)
        #print(os.path.join(img_folder, 'train'))
        shutil.copy(image_path, os.path.join(img_folder, 'train'))
        shutil.copy(label_path, os.path.join(label_folder, 'train_original'))
    else:
        shutil.copy(image_path, os.path.join(img_folder, 'val'))
        shutil.copy(label_path, os.path.join(label_folder, 'val_original'))

二.开始训练

(1)下载预训练权重
(2)创建dota8-obb.yaml,修改相关参数
(3)修改yolov8-obb.yaml参数,修改nc
(4)训练

from ultralytics import YOLO
 
def main():
    model = YOLO('yolov8n-obb.yaml').load('yolov8n-obb.pt')  # build from YAML and transfer weights
    model.train(data='dota8-obb.yaml', epochs=100, imgsz=640, batch=4, workers=4)
if __name__ == '__main__':
    main()

参考:

全网首发!Yolov8_obb旋转框训练、测试、推理手把手教学(DOTA1.0数据集map50已达80%)

Yolov8_obb(prob loss) 基于anchor_free的旋转框目标检测,剪枝,跟踪(ByteTracker)

YOLOv8-OBB推理详解及部署实现

roLabelImg的使用

关于旋转框定义的一些理解和感想

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux | makefile简单教程 | Makefile的工作原理

前言 在学习完了Linux的基本操作之后&#xff0c;我们知道在linux中编写代码&#xff0c;编译代码都是要手动gcc命令&#xff0c;来执行这串代码的。 但是我们难道在以后运行代码的时候&#xff0c;难道都要自己敲gcc命令嘛&#xff1f;这是不是有点太烦了&#xff1f; 在vs中…

接口自动化测试:mock server之Moco工具

什么是mock server mock&#xff1a;英文可以翻译为模仿的&#xff0c;mock server是我们用来解除依赖&#xff08;耦合&#xff09;&#xff0c;假装实现的技术&#xff0c;比如说&#xff0c;前端需要使用某些api进行调试&#xff0c;但是服务端并没有开发完成这些api&#…

SAP 票据批导实现方法

增强结构定义 变量定义 调用bapi前处理相关变量

【JavaScript权威指南第七版】读书笔记速度

JavaScript权威指南第七版 序正文前言&#xff1a;图中笔记重点知识第1章 JavaScript简介第一章总结 第2章 词法结构注释字面量标识符和保留字Unicode可选的分号第二章总结 第3章 类型、值和变量【重要】原始类型特殊类型第三章总结 第4章 表达式与操作符表达式操作符条件式调用…

HTML-框架标签、实体、全局属性和元信息

HTML 1.框架标签 <iframe name"b站" src"https://www.bilibili.com" width"500" height"300" frameborder"0"></iframe>iframe 标签的实际应用&#xff1a; 在网页中嵌入广告。与超链接或表单的 target 配合&a…

林浩然的Java冒险:从单分支到多分支的奇趣编程之旅

林浩然的Java冒险&#xff1a;从单分支到多分支的奇趣编程之旅 Lin Haoran’s Java Adventure: A Whimsical Journey from Single Branch to Multiple Branches 在那个充满神秘色彩的Java编程世界里&#xff0c;林浩然是一位无畏的程序武士。他的江湖历险从单一的分支结构开始&…

链表的应用1--多项式求和

今天学数据结构学到的链表应用于多项式相加&#xff0c;但是书上的代码没看懂&#xff0c;在看了点资料和问ChatGPT以后想到的一个算法&#xff0c;后面有更好的想法在回来更新算法 1.链表相关结构&#xff1a; //链表结点结构 typedef struct linknode {int coef;//系数 int…

磁悬浮轴承行业调研:未来高端市场占比将有所提升

磁悬浮轴承是利用磁力作用将转子悬浮于空中&#xff0c;使转子与定子之间没有机械接触。其原理是磁感应线与磁浮线成垂直&#xff0c;轴芯与磁浮线是平行的&#xff0c;所以转子的重量就固定在运转的轨道上&#xff0c;利用几乎是无负载的轴芯往反磁浮线方向顶撑&#xff0c;形…

【C++修行之道】STL(初识pair、vector)

目录 一、pair 1.1pair的定义和结构 1.2pair的嵌套 1.3pair自带排序规则 1.4代码示例 二、vector 2.1vector的定义和特性 2.2vector的初始化 一维初始化&#xff1a; 2.3vector的常用函数 2.4vector排序去重 排序: 去重&#xff1a; 示例&#xff1a; 一、pair …

Argo CD 可观测性最佳实践

什么是 Argo CD&#xff1f; Argo CD 是一个开源的 CD&#xff08;Continuous Delivery&#xff09;工具&#xff0c;能够帮助您在 Kubernetes 环境中进行持续交付。Argo CD 的主要功能是将配置文件同步到 Kubernetes 集群中并确保应用程序正确运行。Argo CD 可以自动检测应用…

14.5 Flash查询和添加数据库数据

14.5 Flash查询和添加数据库数据 在Flash与数据库通讯的实际应用中&#xff0c;如何实现用户的登录与注册是经常遇到的一个问题。登录实际上就是ASP根据Flash提供的数据查询数据库的过程&#xff0c;而注册则是ASP将Flash提供的数据写入数据库的过程。 1.启动Access2003&…

代码随想录算法训练营29期|day31 任务以及具体安排

理论基础 关于贪心算法&#xff0c;你该了解这些&#xff01; 题目分类大纲如下&#xff1a; #算法公开课 《代码随想录》算法视频公开课 (opens new window)&#xff1a;贪心算法理论基础&#xff01; (opens new window),相信结合视频再看本篇题解&#xff0c;更有助于大家…

【构造方法】这或许是讲的最好的关于Java构造方法的文章!!

致读者 对于看到这篇博客的你们&#xff0c;其实不需要刻意的去记这些知识&#xff0c;可以收藏起来&#xff0c;有事没事翻开看看&#xff0c;这些其实看得多了&#xff0c;自然就烂熟于心了&#xff0c;如果你只是刻意的记忆了一遍&#xff0c;那其实你很快就会忘记&#xf…

仰暮计划|“以前老一辈农村人真的是穷极了……苦极了……”

仰暮计划|“以前老一辈农村人真的是穷极了……苦极了……” 回首往事&#xff0c;几十年的坎坷经历难以件件叙述&#xff0c;却又历历在目。以前老一辈农村人真的是穷极了……苦极了……我奶奶是1941年生人&#xff0c;用她的话说就是“命很硬”。我爷爷1940年生人&#xff0c;…

[TII 2023] 基于压缩感知的多级隐私保护方案

Multilevel Privacy Preservation Scheme Based on Compressed Sensing | IEEE Journals & Magazine | IEEE Xplore 摘要 物联网的广泛应用在给人们带来便利的同时&#xff0c;也引发了人们对数据采集、分析和共享过程中隐私泄露的担忧。本文提出了一种基于压缩感知的多级…

电商系统设计到开发03 引入Kafka异步削峰

一、前言 系统设计&#xff1a;电商系统设计到开发01 第一版设计到编码-CSDN博客 接着上篇文章&#xff1a;电商系统设计到开发02 单机性能压测-CSDN博客 本篇为大制作&#xff0c;内容有点多&#xff0c;也比较干货&#xff0c;希望可以耐心看看 已经开发的代码&#xff0…

【行业应用-智慧零售】东胜物联餐饮门店智能叫号解决方案,为企业智能化升级管理服务

随着科技的不断进步&#xff0c;物联网设备已经广泛应用于各行各业&#xff0c;包括餐饮业。在餐饮门店的线下运营过程中&#xff0c;叫号系统是一项重要的设备需求。传统的叫号方式往往会消耗大量的人力和时间&#xff0c;而物联网技术为餐饮行业提供了一种更高效、智能化的解…

幻兽帕鲁服务器数据备份

搭建幻兽帕鲁个人服务器&#xff0c;最近不少用户碰到内存不足、游戏坏档之类的问题。做好定时备份&#xff0c;才能轻松快速恢复游戏进度 这里讲一下如何定时将服务器数据备份到腾讯云轻量对象存储服务&#xff0c;以及如何在有需要的时候进行数据恢复。服务器中间的数据迁移…

【论文阅读】GraspNeRF: Multiview-based 6-DoF Grasp Detection

文章目录 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Using Generalizable NeRF针对痛点和贡献摘要和结论引言模型框架实验不足之处 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Us…

为什么TestNg会成为Java测试框架的首选?还犹豫什么,看它!

上一篇自动化测试我们大概了解了测试的目标、测试的技术选型以及搭建平台的目标及需求&#xff0c;也确定了自动化测试方案以testNg作为整个测试流程贯穿的基础支持框架&#xff0c;那么testNg究竟有什么特点&#xff1f;本篇开始我们来详细的学习testNg这个测试框架。 为什么要…