YOLOv8训练自己的数据集,通过LabelImg

记录下labelImg标注数据到YOLOv8训练的过程,其中容易遇到labelImg的坑

数据集处理

首先在mydata下创建4个文件夹

在这里插入图片描述
images文件夹下存放着所有的图片,包括训练集和测试集等。后续会根据代码进行划分。
json文件夹里存放的是labelImg标注的所有数据。需要注意的是,json文件的命名应与images文件夹中的图片一一对应。labels文件夹是空的,后续会根据代码将json转化为YOLOv8支持的训练数据集。接下来需要创建一个 split_train_val.py 文件,放在mydata目录下,用于将images文件夹中的图片划分为训练集和测试集。代码如下:

import os
import json
import random
import argparse

class DatasetSplitter:
    def __init__(self, json_path, txt_path):
        self.json_path = json_path
        self.txt_path = txt_path
        self.trainval_percent = 1.0
        self.train_percent = 0.9

        self.total_json = os.listdir(json_path)
        self.num = len(self.total_json)
        self.list_index = list(range(self.num))

        if not os.path.exists(txt_path):
            os.makedirs(txt_path)

    def split_dataset(self):
        tv = int(self.num * self.trainval_percent)
        tr = int(tv * self.train_percent)
        trainval = random.sample(self.list_index, tv)
        train = random.sample(trainval, tr)

        file_trainval = open(os.path.join(self.txt_path, 'trainval.txt'), 'w')
        file_test = open(os.path.join(self.txt_path, 'test.txt'), 'w')
        file_train = open(os.path.join(self.txt_path, 'train.txt'), 'w')
        file_val = open(os.path.join(self.txt_path, 'val.txt'), 'w')

        for i in self.list_index:
            name = self.total_json[i][:-5] + '\n'  # Assuming filenames end with '.json'
            if i in trainval:
                file_trainval.write(name)
                if i in train:
                    file_train.write(name)
                else:
                    file_val.write(name)
            else:
                file_test.write(name)

        file_trainval.close()
        file_train.close()
        file_val.close()
        file_test.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--json_path', default='json', type=str, help='input json label path')
    parser.add_argument('--txt_path', default='dataSet', type=str, help='output txt label path')
    opt = parser.parse_args()

    dataset_splitter = DatasetSplitter(opt.json_path, opt.txt_path)
    dataset_splitter.split_dataset()

运行后会在dataSet生成四个文件.
如图所示
然后前往mydata目录的上一级目录,例如我这里是test目录下,创建voc_label.py文件.用于将labelImg标注的json数据转化为txt文本数据.

请注意,YULO的标注框中的x和y表示矩形框的左上角,而labelImg中的(x,y,w,h)可能表示矩形框的中心点坐标。在使用时需要确认,以免训练出来的YOLO存在偏差。
可以通过以下代码draw_picture_by_json.py进行绘图测试,以下我是默认labelImg的格式是(x_center,y_center,w,h)的格式进行绘制.

from typing import Dict
from PIL import Image, ImageDraw
import json

def draw_pic_by_raw_data(image_path:str, output_path:str, json_data: Dict):
    data = json_data
    img = Image.open(image_path)
    draw = ImageDraw.Draw(img)
    # Load JSON file with bounding box information
    # Iterate through bounding boxes and draw them on the image
    annotations = data[0]["annotations"]
    for bbox in annotations:
        label = bbox["label"]
        x_center, y_center, width, height = (
            bbox["coordinates"]["x"],
            bbox["coordinates"]["y"],
            bbox["coordinates"]["width"],
            bbox["coordinates"]["height"]
        )
        #FIXME TODO 从中心坐标x,y LabelImg 计算左上角坐标
        x, y = x_center - width / 2, y_center - height / 2

        # Draw bounding box
        draw.rectangle([x, y, x+width, y+height], outline="red", width=2)


        # Draw label
        draw.text((x, y-15), label, fill="red")

    # Save the result
    img.save(output_path)
    img.show()

if __name__ == "__main__":
    test_img_path = "3157.jpg"
    test_json_path = "3157.json"
    output_path = "out.jpg"

    with open(test_json_path, 'r') as f:
        data = json.load(f)

    draw_pic_by_raw_data(test_img_path, output_path, data)

通过以上代码,如果矩形框正确,则验证了labelImg的x、y、w和h坐标应该是x_center、y_center、w和h的情况。需要在将json转换为txt文本时进行处理。这里给出voc_label.py的代码如下:请注意修改classes中的类别,修改为和mydata.yaml的顺序一致,否则会导致标签错误。

代码运行前请在mydata目录的上一级,也就是我这里的test目录下创建一个paper_data文件夹,用于等会在mydata.yaml中指定路径.

import os
import json
from os import getcwd

sets = ['train', 'val', 'test']
classes = ["A", "B", "C", "D", "E"]  # 请根据您的实际类别进行修改 对齐yaml文件中的names
abs_path = os.getcwd()
print(abs_path)


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(image_id):
    in_file = open('mydata/json/%s.json' % (image_id), 'r', encoding='UTF-8')
    out_file = open('mydata/labels/%s.txt' % (image_id), 'w')
    data = json.load(in_file)
    for obj in data[0]["annotations"]:
        w = obj["coordinates"]["width"]
        h = obj["coordinates"]["height"]
        difficult = 0  # JSON数据中没有difficult字段,设为0
        cls = obj["label"]
        if cls not in classes or difficult == 1:
            continue
        cls_id = classes.index(cls)
        ##注意:这里的box是左上角和右下角的坐标,而不是中心点坐标
        x_center = obj["coordinates"]["x"]
        y_center = obj["coordinates"]["y"]
        width = obj["coordinates"]["width"]
        height = obj["coordinates"]["height"]
        x, y = x_center - width / 2, y_center - height / 2
        b = x, x + width, y, y + height
        # b = obj["coordinates"]["x"], obj["coordinates"]["x"] + obj["coordinates"]["width"], \
        #     obj["coordinates"]["y"], obj["coordinates"]["y"] + obj["coordinates"]["height"]
        b1, b2, b3, b4 = b
        # 标注越界修正
        if b2 > w:
            b2 = w
        if b4 > h:
            b4 = h
        b = (b1, b2, b3, b4)
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


wd = getcwd()
for image_set in sets:
    if not os.path.exists('mydata/labels/'):
        os.makedirs('mydata/labels/')
    image_ids = open('mydata/dataSet/%s.txt' % (image_set)).read().strip().split()
    list_file = open('paper_data/%s.txt' % (image_set), 'w')
    for image_id in image_ids:
        list_file.write(abs_path + '/mydata/images/%s.jpg\n' % (image_id))
        convert_annotation(image_id)
    list_file.close()

yaml文件配置

截止到这里数据preprocess处理完毕.接下来进行训练前的yaml文件配置.
修改为刚才创建的paper_data的绝对路径
如上配置

并进行names的配置,注意顺序和数量需要与voc_label.py里面的列表顺序一致.

最后修改yolov8.yaml文件配置

yolov8.yaml的路径一般在ultralytics/ultralytics/cfg/models/v8目录下
修改nc为names中的类别数量
在这里插入图片描述

训练模型

yolo task=detect mode=train model=yolov8s.yaml data=mydata.yaml epochs=25 batch=16

这些模型可以支持多种尺寸,包括小(n)、中(s)、中大(m)、大(l)和超大(x)。模型的尺寸参数越大,所需的显存和训练时间也越多。要切换模型尺寸,只需在"model=yolov8"后面加上相应的尺寸参数(n、s、m、l、x),然后再加上.yaml即可。另外,epochs设置为25,batch大小为16。epochs表示训练的轮数, batch为每个批次的样本数量为16.

推理

训练结束后可以通过以下代码进行测试.

yolo predict model=xxxx/weights/best.pt source=xxxx/mydata/testvedio.mp4 imgsz=1280

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

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

相关文章

【王道数据结构】【chapter2线性表】【P43t15】

单链表有环&#xff0c;是指单链表的最后一个节点的指针指向了链表中的某个结点&#xff08;通常单链表的最后一个节点的指针域是空的&#xff09;。试编写算法判断单链表是否存在环。 #include <iostream>typedef struct node{int data;node* next; }node,*list;list I…

java web 职位推荐系系统Myeclipse开发mysql数据库协同过滤算法java编程计算机网页项目

一、源码特点 java Web职位推荐系统是一套完善的java web信息管理系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

AWTK 开源串口屏开发(8) - 系统设置

AWTK 开源串口屏开发 - 系统设置 系统设置只是一个普通应用程序&#xff0c;不过它会用 默认模型 中一些内置的属性和命令&#xff0c;所以这里专门来介绍一下。 1. 功能 在这个例子会用到 默认模型 中一些下列内置的属性和命令&#xff1a; 内置属性 属性类型说明rtc_yea…

基于深度学习的狗狗类别检测

探索狗狗识别技术 引言1. 数据集介绍1.1 语境1.2 内容1.3 致谢 2. 项目背景与意义3. 项目实现流程3.1 数据处理与准备3.2 环境准备与工具安装3.3 模型配置与训练3.4 模型评估与预测3.5 模型推理与部署 4. 总结 服务 引言 随着人工智能技术的不断发展&#xff0c;图像识别已成为…

详解矩阵的LDU分解

目录 一. 矩阵分解 二. 解方程 三. 例题说明 四. 矩阵的LDU分解 五. 矩阵三角分解的唯一性 一. 矩阵分解 其实我们可以把一个线性系统&#xff08;Linear System&#xff09;看成两个三角系统&#xff08;Triangular Systems&#xff09;&#xff0c;本文章将解释为什么可…

Ubuntu 22.04 apt 安装 ros1 ros Noetic Ninjemys

众所周知 ros2还有很多功能没有移植&#xff0c;而ros1官方不再支持 ubuntu 20.04 之后的版本。另一方面Ubuntu 22.04 更新了很多对新硬件的驱动&#xff0c;有更好的兼容性和体验&#xff0c;这就变的很纠结。 如果想在 22.04 使用最新版本的 ros noetic 只有自己编译一个办法…

2024不可不会的StableDiffusion(二)

1. 引言 这是我关于StableDiffusion学习系列的第二篇文章&#xff0c;如果第一篇你还没有阅读&#xff0c;强烈推荐大家翻看前篇内容。在本文中&#xff0c;我们将学习构成StableDiffusion的各个基础组件&#xff0c;并针对每个组件的功能进行阐述。 闲话少说&#xff0c;我们…

JavaEE 网络编程

JavaEE 网络编程 文章目录 JavaEE 网络编程引子1. 网络编程-相关概念1.1 基本概念1.2 发送端和接收端1.3 请求和响应1.4 客户端和服务端 2. Socket 套接字2.1 数据包套接字通信模型2.2 流套接字通信模型2.3 Socket编程注意事项 3. UDP数据报套接字编程3.1 DatagramSocket3.2 Da…

matplotlib多个子图共用一个colorbar

文章目录 colorbar共用colorbar布局colorbar colorbar matplotlib默认提供的功能是&#xff0c;在多个子图中分别生成colorbar&#xff0c;例如 import numpy as np import matplotlib.pyplot as pltfig plt.figure() for i in range(2):ax fig.add_subplot(2,1,i1)ax plt…

掌握HTTP协议:GET和POST请求之间的关键差异

掌握HTTP协议&#xff1a;GET和POST请求之间的关键差异 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是用于在Web浏览器和服务器之间传递信息的协议。在HTTP中&#xff0c;GET请求和POST请求是两种最基本的请求方法。HTTP的底层是TCP/IP&#xff0c;所以GET和POST…

数据库设计的一些原则

文章目录 数据库设计原则表之间的关系一对一关系&#xff08;了解&#xff09;一对多&#xff08;多对一&#xff09;多对多联合主键和复合主键 数据库设计准则-范式1、函数依赖2、完全函数依赖3、部分函数依赖4、传递函数依赖5、码 第一范式第二范式第三范式第三范式 数据库设…

Go 从标准输入读取数据

fmt.Scan系列 fmt.Scan函数定义如下&#xff1a; // Scan scans text read from standard input, storing successive space-separated values into successive arguments. // Newlines count as space. // It returns the number of items successfully scanned. // If tha…

JZ15 二进制中1的个数(牛客)(C语言)

个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 该题我为笨办法,与题解不同,如有疑问和见解,欢迎大家在评论区提出 题目链接: 二进制中1的个数_牛客题霸_牛客网 (now…

XSS靶场练习(pikachu和dvwa)

Pikachu靶场xss练习 反射型xss(get) 输入123发现被直接插入到了html中&#xff0c;而且输入框有字符长度限制 在url中构造payload:<script>alert(123)</script> 反射型xss(post) 查看源码发现登录界面没有任何机会&#xff1b;登录后输入123发现和xss(get)写入位…

Linux 驱动开发基础知识—— LED 驱动程序框架(四)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

联合 Maxlinear 迈凌 与 Elitestek 易灵思 - WPI 世平推出基于 FPGA 芯片的好用高效电源解决方案

近期 WPI 世平公司联合 Maxlinear 迈凌电源产品搭配 Elitestek 易灵思 FPGA 共同合作推出基于 FPGA 芯片的好用高效电源解决方案。 Elitestek 易灵思 FPGA 核心产品有 2 大系列 : Trion 系列与钛金系列。Trion 系列主要特点是 : 1. 40nm 工艺 2. 超低功耗 ( 可低至竞争对手的 …

极限【高数笔记】

【分类】分为了两大类&#xff0c;一个是数列的极限&#xff0c;一个是函数的极限 【数列的极限】 1.定义&#xff1a; 简单来讲&#xff0c;就是&#xff0c;当n无限趋近于无穷时&#xff0c;数列{an}无限趋近一个常数A&#xff0c;此时&#xff0c;常数A就是它们此时情况下的…

SQL注入:报错注入

SQL注入系列文章&#xff1a;初识SQL注入-CSDN博客 SQL注入&#xff1a;联合查询的三个绕过技巧-CSDN博客 目录 什么是报错注入&#xff1f; 报错注入常用的3个函数 UpdateXML ExtractValue Floor rand&#xff08;随机数&#xff09; floor&#xff08;向上取整&…

jenkins发布失败

今天用jenkins发布项目时失败了&#xff0c;而前几天还好好的。 云控制台看了下&#xff0c;发现根本就没打包。 报错如下&#xff1a; 从控制台可以看出&#xff0c;项目依赖没有下载下来&#xff0c;所以打包失败了。 根本原因是&#xff1a;在配置中给yarn指定的淘宝仓库…

WSL2+ubuntu 18+VsCode 配置C/C++开发环境 踩坑

1. 管理员模式打开cmd&#xff0c;或PowerShell &#xff0c;输入 wsl --install 可能出现的错误&#xff1a;无法解析服务器名称或地址 解决方式&#xff1a;科学上网 安装WSL时遇到“无法解析服务器名称或地址”的错误及解决方法 - 知乎 错误2&#xff1a;Error 0x8037…