YOLOV8实战-和平精英敌我检测

YOLOV8实战,从环境配置、数据准备、数据标注、模型训练、模型导出到源码分享

  • 前言:
  • 效果展示
    • ==图片展示==
    • ==视频展示==
  • 简介:
    • **【YOLOV8是啥?】**
    • **【YOLOV8能干啥?有啥应用场景?】**
  • 一、环境准备
    • 1、新建一个虚拟环境
    • 2、配置第三方库
    • 3、另外我们需要通过克隆仓库到本地来获得yolov8最新版本。
    • 4、下载一个预训练模型包
    • 5、环境测试
      • 测试代码
  • 二、数据集制作
    • ①【视频帧提取代码】
    • ②【图片标注】
    • ③【切分数据集】
      • 切分数据集代码:
  • 三、训练文件配置
      • 新建配置文件代码:
  • 四、开始训练
    • 方法一:命令行训练
    • 方法二:代码训练
  • 五、实时检测
    • 代码:
  • 六、模型推理,pt转换成onnx模型
    • 推理代码:
  • 七、源码
    • 源码链接:

前言:

最近刷到有大佬用目标检测在做害虫密度检测,不明觉厉,心想有时间了我也要去琢磨琢磨物体检测,前几天又有人找我帮忙做cf的敌我检测,这回可是下了决心要磕一磕这个技术了,网上写YOLOV8的教程不少,但是从数据集制作、标注、训练、应用的详细教程往往不在一篇文章中,借鉴起来不是那么方便,所以我把自己摸索路上的一些笔记记录在这个平台,一来是备份,方便我将来自己寻找,二来嘛如果将来有人有相同的需求时也能有个参照

效果展示

图片展示

在这里插入图片描述

视频展示

和平精英敌我检测

简介:

【YOLOV8是啥?】

YOLOv8是Ultralytics的最新版本YOLO。作为最先进的 SOTA 模型,YOLOv8 建立在以前版本成功的基础上,引入了新功能和改进,以增强性能、灵活性和效率。

【YOLOV8能干啥?有啥应用场景?】

有应用场景能帮我们更好的掌握这项技术哦,比如我就是从病虫害检测和敌我检测开始入手学习的。
YOLOv8 支持全方位的视觉 AI 任务,包括检测、分割、姿势估计、跟踪和分类。这种多功能性使用户能够在不同的应用程序和域中利用YOLOv8的功能。模型中只需要设定不同的训练模型,就可以得到不同的检测结果。

接下来进入教程了

一、环境准备

1、新建一个虚拟环境

在Anaconda Prompt里面输入以下指令新建环境

conda create --name YOLOV8_1 python=3.9

上面代码里的–name是新建的环境名称,指定python版本为3.9,可按需更改

新建完成后,输入以下代码进入新建的虚拟环境

activate YOLOV8_1

2、配置第三方库

在虚拟环境里输入以下指令下载ultralytic库labelimg库,其中调用YOLOV8在ultralytic库,数据标注要用到labelimg库

pip install ultralytics

pip install labelimg

3、另外我们需要通过克隆仓库到本地来获得yolov8最新版本。

github地址:,链接直达

 https://github.com/ultralytics/ultralytics

git

4、下载一个预训练模型包

github地址:,链接直达

https://github.com/ultralytics/assets/releases/tag/v8.2.0

在这里插入图片描述

网站上提供了s、m、l、x版本,逐渐增大(随着架构的增大,训练时间也是逐渐增大),模型下载好之后和你的代码放在同级文件夹下

5、环境测试

环境准备到这里就差不多了,接下来执行代码测试一下环境搭建是否成功

测试代码


from ultralytics import YOLO
#加载模型,换成你自己的文件位置,图片也一样
model = YOLO(r"D:\YOLOV8\ultralytics-main\Self_Code\yolov8n.pt"
source=r"C:\Users\user2580185125\Desktop\yolov8博客\测试环境.png"
#进行预测并保存
model.predict(source, save=True, imgsz=640, conf=0.7)

测试效果展示

【原图】

在这里插入图片描述
【效果图】

在这里插入图片描述
这就代表你的环境搭建好了,我们要进入下一步骤了

二、数据集制作

我们测试的图片数据来自游戏视频,当然如果你有自己的图片素材也可,爬虫也可,我先录屏自己玩游戏,之后用代码把视频帧提取出来作为我们的原始图片,在这个上面去标注
在这里插入图片描述

①【视频帧提取代码】

import os
import cv2
import sys
import time
#遍历指定目录下所有的视频,按照指定时间间隔截取视频帧
def save_frame(time_in_sec, file_path):
    # 打开视频文件
    cap = cv2.VideoCapture(file_path)
    # 获取视频的帧率
    fps = cap.get(cv2.CAP_PROP_FPS)
    # 获取视频的总帧数
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    duration = total_frames / fps
    num = 0
    while(num < duration):
        num = num + time_in_sec
        # 计算指定时间对应的帧数
        frame_number = int(num * fps)

        # 设置视频的当前帧
        cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)

        # 读取当前帧
        ret, frame = cap.read()
        if ret:
            timestamp = int(time.time())  # 获取当前时间戳
            save_path = f"image\\frame_{frame_number}_{timestamp}.jpg"
            # 保存当前帧为图片
            cv2.imwrite(save_path, frame)
            print("保存成功:" + save_path)
        else:
            print("读取视频帧失败")

    # 关闭视频文件
    cap.release()

def traverse_directory(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            video_path = os.path.join(root, file)
            print(video_path)
            save_frame(2, video_path)
if __name__ == '__main__':
    # 遍历当前目录,这个换成自己的
    traverse_directory(r'D:\YOLOV8\ultralytics-main\Self_Code\视频逐帧转为图片\video')

    print("运行成功")

代码的同级文件夹下要新建一个image文件夹,用来存放图片的,我没写判断语句,没有的话会报错

②【图片标注】

有了图片我们就可以开始标注了,先激活虚拟环境,在虚拟环境中执行以下代码打开标注软件

labelimg

在这里插入图片描述
软件打开之后是这样的

在这里插入图片描述
在软件左侧选择你需要打标签的文件夹,记得文件格式选择yolo格式,注意看图片,都圈出来了,之后就可以尽情的标注了,标注好了一张图片就保存一张,这一步比较费眼睛

③【切分数据集】

标注好的数据集需要切分为训练、测试、验证数据集,执行以下代码进行一键切分,代码中需要修改原数据集存放位置和保存位置,另外就是原图片得放在一个images文件夹里面,不然会报错

切分数据集代码:

import os
import random
import shutil

# 原数据集目录
root_dir = r'D:\YOLOV8\ultralytics-main\Self_Code\视频逐帧转为图片'
# 划分比例
train_ratio = 0.8
valid_ratio = 0.1
test_ratio = 0.1

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

# 拆分后数据集目录
split_dir = r'D:\YOLOV8\ultralytics-main\Self_Code\self_img'
os.makedirs(os.path.join(split_dir, 'train/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'train/labels'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'valid/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'valid/labels'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'test/images'), exist_ok=True)
os.makedirs(os.path.join(split_dir, 'test/labels'), exist_ok=True)

# 获取图片文件列表
image_files = os.listdir(os.path.join(root_dir, 'images'))
image_files = [file for file in image_files if file[-3:] != 'txt']

# 随机打乱文件列表
# combined_files = list(zip(image_files, label_files))
combined_files = list(image_files)
random.shuffle(combined_files)
# image_files_shuffled, label_files_shuffled = zip(*combined_files)
image_files_shuffled = combined_files
# 根据比例计算划分的边界索引
train_bound = int(train_ratio * len(image_files_shuffled))
valid_bound = int((train_ratio + valid_ratio) * len(image_files_shuffled))

# 将图片和标签文件移动到相应的目录

for i, image_file in enumerate(image_files_shuffled):
    label_file = f"{image_file.split('.')[0]}.txt"
    # 复制文件划分数据集,可以将图片和标签放在同一个文件夹下
    if i < train_bound:

        shutil.copy(os.path.join(root_dir, 'images', image_file), os.path.join(split_dir, 'train/images', image_file))
        shutil.copy(os.path.join(root_dir, 'images', label_file), os.path.join(split_dir, 'train/labels', label_file))
    elif i < valid_bound:
        shutil.copy(os.path.join(root_dir, 'images', image_file), os.path.join(split_dir, 'valid/images', image_file))
        shutil.copy(os.path.join(root_dir, 'images', label_file), os.path.join(split_dir, 'valid/labels', label_file))
    else:
        shutil.copy(os.path.join(root_dir, 'images', image_file), os.path.join(split_dir, 'test/images', image_file))
        shutil.copy(os.path.join(root_dir, 'images', label_file), os.path.join(split_dir, 'test/labels', label_file))

print('执行完成')

切分好的文件夹层级是这样的

在这里插入图片描述图片
在这里插入图片描述
标签

在这里插入图片描述

三、训练文件配置

新建一个yaml配置文件,放在训练代码的同级文件夹下,我这里随便取个名字叫cat.yaml,修改里面的文件存放地址,改成你自己的文件地址,names那里你有几个类就写几个类,往下加或者减,按照格式来就行

新建配置文件代码:

# 和平精英
train: D:\YOLOV8\ultralytics-main\Self_Code\self_img\train
val: D:\YOLOV8\ultralytics-main\Self_Code\self_img\valid
test: D:\YOLOV8\ultralytics-main\Self_Code\self_img\test

# Classes
names:
  0: enemy
  1: self
  2: team
  3: jilifu

另外还需要去修改你预训练模型的配置文件,这个文件是你在github那里下载下来的,图片里圈的很详细怎么找,我用的是yolov,就要去D:\YOLOV8\ultralytics-main\ultralytics\cfg\models\v8文件夹修改yolov8.yaml文件夹,主要是改nc,你有几个类别就改成几我复制了一份文件,改的复制文件的内容,这样下次还能找着源文件

在这里插入图片描述
好,准备工作结束,即将开始训练

四、开始训练

训练有两种方式,一种是命令行训练,一种是代码训练,我个人更倾向代码训练,这样方便我找训练好的权重文件,这里两种方式都给出了

方法一:命令行训练

yolo task=detect mode=train model=yolov8n.yaml data=cat.yaml epochs=300 batch=1

以上参数解释如下:

  • task:选择任务类型,可选[‘detect’, ‘segment’, ‘classify’, ‘init’]

  • mode: 选择是训练、验证还是预测的任务蕾西 可选[‘train’, ‘val’, ‘predict’]

  • model:
    选择yolov8不同的模型配置文件,可选yolov8s.yaml、yolov8m.yaml、yolov8l.yaml、yolov8x.yaml

  • data: 选择生成的数据集配置文件

  • epochs:指的就是训练过程中整个数据集将被迭代多少次,显卡不行你就调小点。

  • batch:一次看完多少张图片才进行权重更新,梯度下降的mini-batch,显卡不行你就调小点

方法二:代码训练

from ultralytics import YOLO

if __name__ == '__main__':
 
model = YOLO(r'D:\YOLOV8\ultralytics-main\ultralytics\cfg\models\v8\yolov8_test.yaml')


model.train(model=r'D:\YOLOV8\ultralytics-main\Self_Code\yolov8n.pt',data=r'D:\YOLOV8\ultralytics-main\Self_Code\cat.yaml', epochs=300 , imgsz=640, batch=1, workers=0,
            pretrained=False, save_dir=r"D:\YOLOV8\ultralytics-main\Self_Code")

是不是很简单

训练开始了

在这里插入图片描述
静静等待训练结束,看看损失函数

在这里插入图片描述
在这里插入图片描述

因为我这训练集只有58张图片,训练了300个epoch,明显是不够的,检测自己是大概率能检测出来,敌人和队友目前检测效果不是很好

五、实时检测

代码:

import cv2
from ultralytics import YOLO

# 加载YOLOv8模型
model = YOLO(r'D:\YOLOV8\ultralytics-main\Self_Code\runs\detect\train5\weights\best.pt')

# 打开视频文件
video_path = r"C:\Users\user2580185125\Desktop\5月11日.mp4"
cap = cv2.VideoCapture(video_path)

# 循环遍历视频帧
while cap.isOpened():
    # 从视频读取一帧
    success, frame = cap.read()

    if success:
        # 在帧上运行YOLOv8追踪,持续追踪帧间的物体
        results = model.track(frame, persist=True)
        # 输出每次追踪推理结果的boxes,这些参数实际上是和模型直接predict类似的。
        print(results[0].boxes)
        # 在帧上展示结果
        annotated_frame = results[0].plot()
        # 展示带注释的帧
        cv2.imshow("YOLOv8 Tracking", annotated_frame)

        # 如果按下'q'则退出循环
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        # 如果视频结束则退出循环
        break

# 释放视频捕获对象并关闭显示窗口
cap.release()
cv2.destroyAllWindows()

接下来把我们训练好的模型拿来跑一跑实时检测,发现欠缺的地方还蛮多的,如果扩充训练集和epoch,模型效果应该会更好

六、模型推理,pt转换成onnx模型

ONNX的主要优势包括:

  • 框架无关性:ONNX允许开发者在PyTorch、TensorFlow、Caffe2等多个流行框架之间自由转换模型。

  • 优化和加速:ONNX提供了一套优化工具,可以减少模型的大小并提高执行效率,特别是在不同硬件上部署时。

  • 广泛的支持:从云计算服务到边缘设备,ONNX都能提供良好的支持,使得模型部署变得更加灵活和广泛。

推理代码:



from ultralytics import YOLO
model = YOLO(r"D:\YOLOV8\ultralytics-main\Self_Code\runs\detect\train\weights\best.pt")
success = model.export(format="onnx", simplify=True)  # export the model to onnx format
assert success
print("转换成功")

七、源码

源码全部公开,感兴趣的朋友可以继续开发

在这里插入图片描述

源码链接:

百度云盘链接

链接:https://pan.baidu.com/s/1Ci5Fpx4iBXRphQhhyR4Sig 
提取码:dp18

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

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

相关文章

VBA在Excel中登录页面的应用—动态密码设置

https://mp.weixin.qq.com/s?__biz=MzkwMzY1OTIzOA==&mid=2247484420&idx=1&sn=5f98ef156cd6a784f0b1e64eed11ee42&chksm=c093af8df7e4269bdda3ed4adc37ce5f30707760ad42a2e0c6c3278ff0a0c5fcaf890016f9b5&token=1012529499&lang=zh_CN#rd 文章目录 …

css中用于设置光标颜色的属性

caret-color 是一个 CSS 属性&#xff0c;它用于定义输入光标&#xff08;caret&#xff09;的颜色。这里的“插入光标”&#xff08;insertion caret&#xff09;指的是在网页的可编辑器区域内&#xff0c;用来指示用户的输入具体会插入到哪里的那个一闪一闪的形似竖杠 | 的东…

正则化 缓解过拟合

缓解过拟合&#xff1a;收集更多的训练数据、正则化 权重衰减也被称为 L 2 L_{2} L2​正则化 如果我们的权重向量增长的太大&#xff0c; 我们的学习算法可能会更集中于最小化权重范数 ∣ ∣ w ∣ ∣ 2 ||w||^2 ∣∣w∣∣2。 为了惩罚权重向量的大小&#xff0c; 我们必须以某…

OCR技术在增值税发票数据分析中的应用

OCR技术在增值税发票数据分析中的应用&#xff0c;为企业的财务管理和商业决策注入了新的活力。随着数字化时代的来临&#xff0c;企业面临着海量的数据处理挑战&#xff0c;如何高效、准确地从这些信息中提炼出有价值的数据&#xff0c;成为企业提升竞争力的关键。OCR技术&…

6.Labview使用子vi进行VI间的数据传递详解(模块化)

本文通过讲解建立子VI的方式来进行VI间的数据传递方式。 大家可以将子VI理解为一个可以被调用的子程序&#xff0c;我们把某个程序中的一部分程序封装成一个模块以后就可以在其他的程序里边调用这一个模块。 题注&#xff1a; 那么我们为什么要把子VI封装成一个模块呢&#xff…

C语言学习【C语言基本数据类型二】

C语言学习【C语言基本数据类型二】 _Bool类型 C99标准添加了_Bool类型&#xff0c;用于表示布尔值&#xff0c;即逻辑值true和false&#xff0c;原则上仅占用1位存储空间&#xff1b; float、double和long double 记数法示例 C标准规定&#xff0c;float类型必须至少能表示…

第33次CSP认证Q3:化学方程式配平

&#x1f344;题目描述 为了配平一个化学方程式&#xff0c;我们可以令方程式中各物质的系数为未知数&#xff0c;然后针对涉及的每一种元素&#xff0c;列出关于系数的方程&#xff0c;形成一个齐次线性方程组。然后求解这个方程组&#xff0c;得到各物质的系数。这样&#x…

免费SSL证书获取与部署教程

在互联网时代&#xff0c;HTTPS已成为网站安全的基石&#xff0c;为用户数据传输提供加密保障。免费SSL证书的出现降低了部署HTTPS的门槛&#xff0c;尤其对于个人网站、小微企业及测试环境而言&#xff0c;它们是理想的选择。本文旨在提供一份详尽指南&#xff0c;帮助您轻松获…

QLExpress入门及实战总结

文章目录 1.背景2.简介3.QLExpress实战3.1 基础例子3.2 低代码实战3.2.1 需求描述3.2.1 使用规则引擎3.3.2 运行结果 参考文档 1.背景 最近研究低代码实现后端业务逻辑相关功能&#xff0c;使用LiteFlow作为流程编排后端service服务, 但是LiteFlow官方未提供图形界面编排流程。…

穿越网络界限:探索NAT IPv4的神秘面纱

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 穿越网络界限&#xff1a;探索NAT IPv4的神秘面纱 前言NAT IPv4概述NAT IPv4的类型NAT IPv4的工作流程NAT IPv4的局限性和挑战 前言 在我们日常的网络使用中&#xff0c;我们或多或少都会遇到NAT&…

SAP:FI 财务凭证行项目文本前台修改

一、问题描述 财务凭证行项目文本点击修改&#xff0c;但是前台有的行可以修改&#xff0c;有的行是灰色的不能修改&#xff0c;如下图所示&#xff0c;这个文本信息有误&#xff0c;必须修改怎么办&#xff1f; 二、思路分析 有的行可以修改&#xff0c;有的行不能修改&#x…

【MySQL数据库】初步认识数据库,实现基本操作

在信息爆炸的今天&#xff0c;数据无处不在&#xff0c;它们构成了互联网世界的基石。但数据本身若未经有效组织和管理&#xff0c;就如同散落在沙滩上的珍珠&#xff0c;难以发挥其真正的价值。这时&#xff0c;“数据库”这一概念便如同一根线&#xff0c;将这些珍珠串联起来…

position:fixed无法固定到父盒子上面的解决方案

目录 问题如图所示&#xff1a; 下面是错误的代码&#xff1a; 解决方案1&#xff1a; 使用fixed固定定位固定到父元素&#xff1a; 解决方案2&#xff1a; 推荐使用的其他方案&#xff08;粘性定位&#xff09;&#xff1a; 什么是粘性定位&#xff1a; 粘性定位的使用…

答辩PPT设计太耗时?aippt工具,AI一站式服务

这些网站我愿称之为制作答辩PPT的神&#xff01; 很多快要毕业的同学在做答辩PPT的时候总是感觉毫无思路&#xff0c;一窍不通。但这并不是你们的错&#xff0c;对于平时没接触过相关方面&#xff0c;第一次搞答辩PPT的人来说&#xff0c;这是很正常的一件事。一个好的答辩PPT…

搞懂Docker(九)- 使用Docker Compose

获取示例程序 示例程序 或者 示例程序 获取示例程序程序结构如下├── getting-started-app/ │ ├── package.json │ ├── README.md │ ├── spec/ │ ├── src/ │ └── yarn.lock使用Docker Compose Docker Compose是一个帮助你定义和共享多容器应用程序的工具…

在线数据库设计工具drawDB

什么是 DrawDB &#xff1f; DrawDB 是浏览器中强大且用户友好的数据库实体关系&#xff08;DBER&#xff09;编辑器。只需点击几下即可构建图表、导出 SQL 脚本、自定义编辑器等等&#xff0c;无需创建帐户。 软件特点&#xff1a; DrawDB 是完全免费的无需注册或登录。只需投…

19.接口自动化-Jekins学习

1.CI-持续集成 频繁的&#xff08;一天多次&#xff09;将代码集成到主干 目的&#xff1a;让产品快速迭代&#xff0c;保持高质量 好处&#xff1a; 快速发现错误&#xff0c;每次更新都集成到主干&#xff0c;可以快速发现错误&#xff0c;定位错误也容易防止分支大幅偏离主…

字符串取第一个空格之后的所有的值字符串取第一个空格之后的第二个元素的值,不要后面的值

当我们后端返回值可能存在某些特定的值或标识导致返回数据不固定且是空格分割时&#xff0c;我们想取出返回字符串中的某个值&#xff0c;就可以参考下面对这个字符串进行操作提取&#xff0c;当然&#xff0c;如果是别的符号分割开的把下面的空格替换即可 1、字符串取第一个空…

C语言笔记14

指针1 在C语言中给内存单元的编号起了个名字叫做指针&#xff0c;通俗来说就是地址。&#xff08;内存单元编号地址指针&#xff09; 1.指针变量与地址 int a10&#xff1b; int* p&a&#xff1b; * 说明了这里p的是指针变量&#xff1b;int*说明p是一个整形指针&…

SpringBoot 实现对提供的接口进行 AES (加密,解密)

业务来源&#xff1a; 最近工作中&#xff0c;领导要求给别的项目组的小伙伴提供几个接口&#xff0c;要求对接口的参数进行解密操作&#xff0c;然后对返回的数据进行加密操作。 这时我想到了AES AES 是对称加密算法&#xff0c;优点&#xff1a;加密速度快&#xff1b;缺点…