YoloV9实战:从Labelme到训练、验证、测试、模块解析

模型实战

训练COCO数据集

本次使用2017版本的COCO数据集作为例子,演示如何使用YoloV8训练和预测。

下载数据集

Images:

  • 2017 Train images [118K/18GB] :http://images.cocodataset.org/zips/train2017.zip
  • 2017 Val images [5K/1GB]:http://images.cocodataset.org/zips/val2017.zip
  • 2017 Test images [41K/6GB]:http://images.cocodataset.org/zips/unlabeled2017.zip

Annotations:

  • 2017 annotations_trainval2017 [241MB]:http://images.cocodataset.org/annotations/annotations_trainval2017.zip

COCO转yolo格式数据集(适用V4,V5,V6,V7,V8)

最初的研究论文中,COCO中有91个对象类别。然而,在2014年的第一次发布中,仅发布了80个标记和分割图像的对象类别。2014年发布之后,2017年发布了后续版本。详细的类别如下:

IDOBJECT (PAPER)OBJECT (2014 REL.)OBJECT (2017 REL.)SUPER CATEGORY
1personpersonpersonperson
2bicyclebicyclebicyclevehicle
3carcarcarvehicle
4motorcyclemotorcyclemotorcyclevehicle
5airplaneairplaneairplanevehicle
6busbusbusvehicle
7traintraintrainvehicle
8trucktrucktruckvehicle
9boatboatboatvehicle
10trafficlighttraffic lighttraffic lightoutdoor
11fire hydrantfire hydrantfire hydrantoutdoor
12streetsign--
13stop signstop signstop signoutdoor
14parking meterparking meterparking meteroutdoor
15benchbenchbenchoutdoor
16birdbirdbirdanimal
17catcatcatanimal
18dogdogdoganimal
19horsehorsehorseanimal
20sheepsheepsheepanimal
21cowcowcowanimal
22elephantelephantelephantanimal
23bearbearbearanimal
24zebrazebrazebraanimal
25giraffegiraffegiraffeanimal
26hat--accessory
27backpackbackpackbackpackaccessory
28umbrellaumbrellaumbrellaaccessory
29shoe--accessory
30eye glasses--accessory
31handbaghandbaghandbagaccessory
32tietietieaccessory
33suitcasesuitcasesuitcaseaccessory
34frisbeefrisbeefrisbeesports
35skisskisskissports
36snowboardsnowboardsnowboardsports
37sports ballsports ballsports ballsports
38kitekitekitesports
39baseball batbaseball batbaseball batsports
40baseball glovebaseball glovebaseball glovesports
41skateboardskateboardskateboardsports
42surfboardsurfboardsurfboardsports
43tennis rackettennis rackettennis racketsports
44bottlebottlebottlekitchen
45plate--kitchen
46wine glasswine glasswine glasskitchen
47cupcupcupkitchen
48forkforkforkkitchen
49knifeknifeknifekitchen
50spoonspoonspoonkitchen
51bowlbowlbowlkitchen
52bananabananabananafood
53appleappleapplefood
54sandwichsandwichsandwichfood
55orangeorangeorangefood
56broccolibroccolibroccolifood
57carrotcarrotcarrotfood
58hot doghot doghot dogfood
59pizzapizzapizzafood
60donutdonutdonutfood
61cakecakecakefood
62chairchairchairfurniture
63couchcouchcouchfurniture
64potted plantpotted plantpotted plantfurniture
65bedbedbedfurniture
66mirror--furniture
67dining tabledining tabledining tablefurniture
68window--furniture
69desk--furniture
70toilettoilettoiletfurniture
71door--furniture
72tvtvtvelectronic
73laptoplaptoplaptopelectronic
74mousemousemouseelectronic
75remoteremoteremoteelectronic
76keyboardkeyboardkeyboardelectronic
77cell phonecell phonecell phoneelectronic
78microwavemicrowavemicrowaveappliance
79ovenovenovenappliance
80toastertoastertoasterappliance
81sinksinksinkappliance
82refrigeratorrefrigeratorrefrigeratorappliance
83blender--appliance
84bookbookbookindoor
85clockclockclockindoor
86vasevasevaseindoor
87scissorsscissorsscissorsindoor
88teddy bearteddy bearteddy bearindoor
89hair drierhair drierhair drierindoor
90toothbrushtoothbrushtoothbrushindoor
91hair brush--indoor

可以看到,2014年和2017年发布的对象列表是相同的,它们是论文中最初91个对象类别中的80个对象。所以在转换的时候,要重新对类别做映射,映射函数如下:

def coco91_to_coco80_class():  # converts 80-index (val2014) to 91-index (paper)
    # https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/
    # a = np.loadtxt('data/coco.names', dtype='str', delimiter='\n')
    # b = np.loadtxt('data/coco_paper.names', dtype='str', delimiter='\n')
    # x1 = [list(a[i] == b).index(True) + 1 for i in range(80)]  # darknet to coco
    # x2 = [list(b[i] == a).index(True) if any(b[i] == a) else None for i in range(91)]  # coco to darknet
    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, None, 24, 25, None,
         None, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, None, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
         51, 52, 53, 54, 55, 56, 57, 58, 59, None, 60, None, None, 61, None, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
         None, 73, 74, 75, 76, 77, 78, 79, None]
    return x

接下来,开始格式转换,工程的目录如下:
在这里插入图片描述

  • coco:存放解压后的数据集。
    -out:保存输出结果。
    -coco2yolo.py:转换脚本。

转换代码如下:

import json
import glob
import os
import shutil
from pathlib import Path
import numpy as np
from tqdm import tqdm


def make_folders(path='../out/'):
    # Create folders

    if os.path.exists(path):
        shutil.rmtree(path)  # delete output folder
    os.makedirs(path)  # make new output folder
    os.makedirs(path + os.sep + 'labels')  # make new labels folder
    os.makedirs(path + os.sep + 'images')  # make new labels folder
    return path


def convert_coco_json(json_dir='./coco/annotations_trainval2017/annotations/'):
    jsons = glob.glob(json_dir + '*.json')
    coco80 = coco91_to_coco80_class()

    # Import json
    for json_file in sorted(jsons):
        fn = 'out/labels/%s/' % Path(json_file).stem.replace('instances_', '')  # folder name
        fn_images = 'out/images/%s/' % Path(json_file).stem.replace('instances_', '')  # folder name
        os.makedirs(fn,exist_ok=True)
        os.makedirs(fn_images,exist_ok=True)
        with open(json_file) as f:
            data = json.load(f)
        print(fn)
        # Create image dict
        images = {'%g' % x['id']: x for x in data['images']}

        # Write labels file
        for x in tqdm(data['annotations'], desc='Annotations %s' % json_file):
            if x['iscrowd']:
                continue

            img = images['%g' % x['image_id']]
            h, w, f = img['height'], img['width'], img['file_name']
            file_path='coco/'+fn.split('/')[-2]+"/"+f
            # The Labelbox bounding box format is [top left x, top left y, width, height]
            box = np.array(x['bbox'], dtype=np.float64)
            box[:2] += box[2:] / 2  # xy top-left corner to center
            box[[0, 2]] /= w  # normalize x
            box[[1, 3]] /= h  # normalize y

            if (box[2] > 0.) and (box[3] > 0.):  # if w > 0 and h > 0
                with open(fn + Path(f).stem + '.txt', 'a') as file:
                    file.write('%g %.6f %.6f %.6f %.6f\n' % (coco80[x['category_id'] - 1], *box))
            file_path_t=fn_images+f
            print(file_path,file_path_t)
            shutil.copy(file_path,file_path_t)


def coco91_to_coco80_class():  # converts 80-index (val2014) to 91-index (paper)
    # https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/
    # a = np.loadtxt('data/coco.names', dtype='str', delimiter='\n')
    # b = np.loadtxt('data/coco_paper.names', dtype='str', delimiter='\n')
    # x1 = [list(a[i] == b).index(True) + 1 for i in range(80)]  # darknet to coco
    # x2 = [list(b[i] == a).index(True) if any(b[i] == a) else None for i in range(91)]  # coco to darknet
    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, None, 24, 25, None,
         None, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, None, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
         51, 52, 53, 54, 55, 56, 57, 58, 59, None, 60, None, None, 61, None, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
         None, 73, 74, 75, 76, 77, 78, 79, None]
    return x

convert_coco_json()

开始运行:
在这里插入图片描述

转换完成后,验证转换的结果:

import cv2
import os

def draw_box_in_single_image(image_path, txt_path):
    # 读取图像
    image = cv2.imread(image_path)

    # 读取txt文件信息
    def read_list(txt_path):
        pos = []
        with open(txt_path, 'r') as file_to_read:
            while True:
                lines = file_to_read.readline()  # 整行读取数据
                if not lines:
                    break
                # 将整行数据分割处理,如果分割符是空格,括号里就不用传入参数,如果是逗号, 则传入‘,'字符。
                p_tmp = [float(i) for i in lines.split(' ')]
                pos.append(p_tmp)  # 添加新读取的数据
                # Efield.append(E_tmp)
                pass
        return pos


    # txt转换为box
    def convert(size, box):
        xmin = (box[1]-box[3]/2.)*size[1]
        xmax = (box[1]+box[3]/2.)*size[1]
        ymin = (box[2]-box[4]/2.)*size[0]
        ymax = (box[2]+box[4]/2.)*size[0]
        box = (int(xmin), int(ymin), int(xmax), int(ymax))
        return box

    pos = read_list(txt_path)
    print(pos)
    tl = int((image.shape[0]+image.shape[1])/2)
    lf = max(tl-1,1)
    for i in range(len(pos)):
        label = str(int(pos[i][0]))
        print('label is '+label)
        box = convert(image.shape, pos[i])
        image = cv2.rectangle(image,(box[0], box[1]),(box[2],box[3]),(0,0,255),2)
        cv2.putText(image,label,(box[0],box[1]-2), 0, 1, [0,0,255], thickness=2, lineType=cv2.LINE_AA)
        pass

    if pos:
        cv2.imwrite('./Data/see_images/{}.png'.format(image_path.split('\\')[-1][:-4]), image)
    else:
        print('None')



img_folder = "./out/images/val2017"
img_list = os.listdir(img_folder)
img_list.sort()

label_folder = "./out/labels/val2017"
label_list = os.listdir(label_folder)
label_list.sort()
if not os.path.exists('./Data/see_images'):
    os.makedirs('./Data/see_images')
for i in range(len(img_list)):
    image_path = img_folder + "\\" + img_list[i]
    txt_path = label_folder + "\\" + label_list[i]
    draw_box_in_single_image(image_path, txt_path)

结果展示:
在这里插入图片描述

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

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

相关文章

Python-VBA函数之旅-compile函数

目录 1、 compile函数: 1-1、Python: 1-2、VBA: 2、相关文章: 个人主页:https://blog.csdn.net/ygb_1024?spm1010.2135.3001.5421 compile函数在Python中有多个实际应用场景,它主要用于将字符串形式的…

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

🔥个人主页:Forcible Bug Maker 🔥专栏:C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容:类的6个默认成员函数中的拷贝构造函数…

matlab使用教程(45)—二维曲线图绘制进阶

1.绘制双y轴曲线图 此示例说明如何使用两个不同的 y 轴合并线图和条形图。此外,还演示如何自定义线条和条形。 使用 yyaxis 创建包含两个 y 轴的图表。图形函数以图表的活动侧为目标。使用 yyaxis 控制活动侧。使 用左侧的 y 轴绘制条形图。使用右侧的 y 轴绘制线…

PLC扩展更自由,钡铼IOy系列模块实现DI/DO/AI/AO任意组合

随着工业自动化的不断发展,PLC(可编程逻辑控制器)作为工业控制领域的核心设备,扮演着至关重要的角色。而钡铼IOy系列模块作为PLC的重要扩展设备,不仅实现了DI(数字输入)、DO(数字输出…

KNIME 国际化支持投票

你的投票也许能让 KNIME 中文化快一点点。 i18n 是个很搞笑的单词,它是英文 internationalization 国际化的缩写。18 指的是首字母i和末字母n中间有18个字母。另外还有什么 K8s 也是一样,中间省去了8个字母 ... 真是懒的可以。指北君还想起一个类似的笑话…

算法设计与分析实验报告c++实现(矩阵链相乘、投资问题、完全背包问题、数字三角形、最小生成树、背包问题)

一、实验目的 1.加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握; 2.提高学生利用课堂所学知识解决实际问题的能力; 3.提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 用动态…

懒人建站工具过时了?试试这6个WordPress主题,1小时实现高效建站

懒人建站工具,凭借简单易用、快速上手和个性化定制的特点,为不熟悉代码和程序的人提供了搭建美观实用网站的便捷途径。无需专业的前端开发知识,无需雇佣专业开发人员,用户便能轻松实现网站搭建,满足个人或企业需求。懒…

novel-plus文件部分

环境配置。windows下需要将application-dev.yml添加盘符,固定路径 在FileController中,存在任意文件上传,也就是在 存在问题,确实是任意文件上传,任意文件都可以上传,但是上传jsp等文件时,会…

windows编译xlnt,获取Excel表里的数据

用git拉取项目 这个文件是空的 要用git拉下来&#xff0c;使用终端编译xlnt库 点击解决方案 运行生成 然后新建项目&#xff0c;配置好库&#xff0c; #include <iostream> #include <xlnt/xlnt.hpp>int main() {// 打开 Excel 文件xlnt::workbook workbook;workb…

微信小程序scroll-view组件

一、介绍 当一个容器内容很多时&#xff0c;若容器无法显示完整内容&#xff0c;则可通过滚动操作查看所有内容 在微信小程序中scroll-view组件可以实现滚动效果 二、scroll-view组件的属性值 &#xff08;1&#xff09;scroll-x 【boolean型】 允许横向滚动条&#xff0c;默…

【C++】开始使用stack 与 queue

送给大家一句话&#xff1a; 忍受现实给予我们的苦难和幸福&#xff0c;无聊和平庸。 – 余华 《活着》 开始使用queue 与 stack 1 前言2 stack与queue2.1 stack 栈2.2 queue 队列2.3 使用手册 3 开始使用Leetcode 155.最小栈牛客 JZ31 栈的弹出压入序列Leetcode 150.逆波兰表达…

共享桌面,3分钟自己实现一个吧,还能听见麦克风声音哦

前言 关于【SSD系列】&#xff1a; 前端一些有意思的内容&#xff0c;旨在3-10分钟里&#xff0c; 500-1000字&#xff0c;有所获&#xff0c;又不为所累。 共享桌面程序&#xff0c;哇&#xff0c;高大尚耶&#xff01;其实不然&#xff0c;让我带你3分钟实现桌面共享程序&am…

【Entity Framework】你知道如何处理无键实体吗

【Entity Framework】你知道如何处理无键实体吗 文章目录 【Entity Framework】你知道如何处理无键实体吗一、概述二、定义无键实体类型数据注释 三、无键实体类型特征四、无键实体使用场景五、无键实体使用场景六、无键使用示例6.1 定义一个简单的Blog和Post模型&#xff1a;6…

sqlilabs靶场1—20题学习笔记(思路+解析+方法)

前几个题目较为简单&#xff0c;均尝试使用各种方法进行SQL注入 第一题 联合查询 1&#xff09;思路&#xff1a; 有回显值 1.判断有无注入点 2.猜解列名数量 3.判断回显点 4.利用注入点进行信息收集 爆用户权限&#xff0c;爆库&#xff0c;爆版本号 爆表&#xff0c;爆列&…

AI 领域精选高质量信息源分享

我在这篇 ChatGPT 发布一周年的总结文章中大模型时代&#xff0c;程序员如何实现自我成长&#xff1f;——一名普通开发者的 ChatGPT 一周年记&#xff0c;已经推荐了不少优质的信息源&#xff0c;但主要还是偏技术向&#xff0c;随着我自己的身份从纯研发角色转变为产品&#…

【Linux】服务器硬件及RAID配置实战

目录 一、服务器 1.服务器 2.查看服务器信息 二、RAID 磁盘阵列 三、软RAID的创建和使用 1.添加硬盘&#xff0c;fdisk分区&#xff0c;分区类型ID设置为 fd 2.使用mdadm创建软raid 3.格式化 4.挂载使用 5.mdadm 一、服务器 1.服务器 分类机架式居多 塔…

Qt | 事件第二节

Qt | 事件第一节书接上回 四、事件的接受和忽略 1、事件可以被接受或忽略,被接受的事件不会再传递给其他对象,被忽略的事件会被传递给其他对象处理,或者该事件被丢弃(即没有对象处理该事件) 2、使用 QEvent::accept()函数表示接受一个事件,使用 QEvent::ignore()函数表示…

牛客网刷题 | BC51 及格分数

描述 KiKi想知道他的考试分数是否通过&#xff0c;请帮他判断。从键盘任意输入一个整数表示的分数&#xff0c;编程判断该分数是否在及格范围内&#xff0c;如果及格&#xff0c;即&#xff1a;分数大于等于60分&#xff0c;是输出“Pass”&#xff0c;否则&#xff0c;输出“…

【Entity Framework】你必须要了解EF中数据查询之数据加载

【Entity Framework】你必须要了解EF中数据查询之数据加载 文章目录 【Entity Framework】你必须要了解EF中数据查询之数据加载一、概述二、预先加载2.1 包含多个层级2.2 经过筛选的包含 三、显示加载3.1查询关联实体 四、延时加载4.1 不使用代理进行延迟加载 一、概述 Entity…

数据分析(2)

数据分析&#xff08;2&#xff09; 本文介绍pandas的另一种数据类型DataFrame,中文叫数据框 DataFrame 定义&#xff1a; DataFrame是一个二维的矩阵数据表&#xff0c;通过行和列&#xff0c;可以定位一个值。 在某种程度上&#xff0c;可以认为DataFrame是“具有相同ind…
最新文章