YOLO入门教程(一)——训练自己的模型【含教程源码 + 故障排查】

目录

  • 引言
  • 前期准备
  • Step1 打标训练
  • Step2 格式转换
  • Step3 整理训练集
  • Step4 训练数据集
    • 4.1创建yaml文件
    • 4.2训练
    • 4.3故障排查
      • 4.3.1OpenCV版本故障,把OpenCV版本升级到4.0以上
      • 4.3.2NumPy版本故障,把NumPy降低版本到1.26.4
      • 4.3.3没有安装ultralytics模块
      • 4.3.4Arial.ttf下载超时
      • 4.3.5其他报错
  • 参考博客

引言

YOLO(You Only Look Once)Y作为一个目标检测算法,主要是针对矩形边界框的标注设计的,通常情况下使用的是矩形边界框,常用的LabelImg可以只支持矩形标注,该软件标注的标签可以直接用于应用,本文教程主要介绍如何训练自己的YOLO模型,LabelMe多边形标注的标签如何训练。

前期准备

安装Anaconda,VSCode,LabelMe并配置好Python环境,OpenCV环境,PyTorch即可开始训练自己的数据集。

Step1 打标训练

使用LabelMe软件进行打标签,会在原图路径下生成.json标签文件。
在这里插入图片描述

Step2 格式转换

LabelMe生成的.json标签文件格式不适用于YOLO训练,需要转换格式为.txt标签文件,利用以下代码将.json标签文件归一化为YOLO可直接训练的.txt标签文件。

import json
import os
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np#定义分类
name2id = {'background':0,'dot':1}
#通过相对路径索引到标签文件
label_floder_path = './source'def convert(img_size, corners):# 输入的image_size[0]为宽,[1]为高# 输入的corners[0]和[1]左上角的xy坐标,[2][3]为右下角的xy坐标dw = 1./(img_size[0])dh = 1./(img_size[1])x = (corners[0] + corners[2]) / 2.0 - 1y = (corners[1] + corners[3]) / 2.0 - 1w = abs(corners[2] - corners[0])h = abs(corners[3] - corners[1])x = x * dww = w * dwy = y * dhh = h * dhprint("归一化后矩形中心坐标为(", x, ",", y, ")")print("归一化后矩形中心宽高为(", w, ",", h, ")")return (x, y, w, h)def decode_json(label_floder_path, label_name):# txt文件名为:文件名.json转换为文件名.txttxt_name = label_floder_path + "/" + label_name[0:-5] + '.txt'# 打开txt后续可以进行写入,若不存在改文件会自动创建print("新建的txt文件名称为", txt_name)txt_file = open(txt_name, 'w')# 文件路径+文件名称组成完整路径label_path = os.path.join(label_floder_path, label_name)print("文件路径为", label_floder_path, "文件名称为", label_name)# 打开json后续可进行读取,编码方式为GBKdata = json.load(open(label_path, 'r', encoding='GBK'))# 用索引的方式可以得到数据img_w = data['imageWidth']img_h = data['imageHeight']for i in data['shapes']:label_name = i['label']# 标签形状为矩形时的转换方式if (i['shape_type'] == 'rectangle'):print("标签形状为矩形进行转换")x1 = int(i['points'][0][0])y1 = int(i['points'][0][1])x2 = int(i['points'][1][0])y2 = int(i['points'][1][1])corners = (x1, y1, x2, y2)box = convert((img_w,img_h), corners)txt_file.write(str(name2id[label_name]) + " " + " ".join([str(xy) for xy in box]) + '\n')# 标签形状为多边形时的转换方式elif (i['shape_type'] == 'polygon'):print("标签形状为多边形进行转换")# 创建一个空的列表来存储所有点points = []# 从路径中获取多边形的坐标for point in i['points']:points.append(point)# 使用列表解析创建二维元组列表polygon_vertices = [(points[i][0], points[i][1]) for i in range(0, len(points), 1)]print("点的数量为", len(points), "分别为:", polygon_vertices)# 创建一个多边形对象polygon = Polygon(polygon_vertices, closed=True, edgecolor='r', fill=None)fig, ax = plt.subplots()ax.add_patch(polygon)# 获取多边形的路径对象path = polygon.get_path()# 获取路径的边界框extents = path.get_extents()corners = (extents.xmin, extents.ymax, extents.xmax, extents.ymin)box = convert((img_w,img_h),corners)txt_file.write(str(name2id[label_name]) + " " + " ".join([str(xy) for xy in box]) + '\n')# 标签形状为圆形时的转换方式else:# 圆形的信息circle_center = (3, 4)  # 圆心坐标 (x, y)circle_radius = 2       # 圆的半径# 计算外接矩形的位置# 外接矩形的左上角和右下角坐标rect_top_left = (circle_center[0] - circle_radius, circle_center[1] + circle_radius)rect_bottom_right = (circle_center[0] + circle_radius, circle_center[1] - circle_radius)corners = (rect_top_left[0], rect_top_left[1], rect_bottom_right[0], rect_bottom_right[1])box = convert((img_w,img_h), corners)txt_file.write(str(name2id[label_name]) + " " + " ".join([str(xy) for xy in box]) + '\n')def create_classes(label_floder_path):# txt文件名为:文件名.json转换为文件名.txtclasses_name = label_floder_path + "/classes.txt"# 打开txt后续可以进行写入,若不存在改文件会自动创建print("新建的txt文件名称为", classes_name)classes_file = open(classes_name, 'w')for name in name2id:classes_file.write(name + '\n')if __name__ == "__main__":label_names = os.listdir(label_floder_path)print("转换的总文件数量为", len(label_names))create_classes(label_floder_path)for label_name in label_names:if(label_name[-5:] == '.json'):print("解析文件", label_name)decode_json(label_floder_path, label_name)

label_floder_path替换成标签和图片所在路径
name2id替换成标签
encoding='GBK’为编码格式

以上代码暂时只支持矩形和多边形的形状转换

备注:转换后可以在LabelImg上检验是否转换成功
在这里插入图片描述

Step3 整理训练集

YOLO有数据集要求放置的格式要求,具体要求如下:

dataset/
├── train/
│ ├── images/
│ └── labels/
└── val/
├── images/
└── labels/

利用以下代码将快速将训练集整理好,划分为训练集和验证集:

import random
import shutil
import os
import shutil#通过相对路径索引到数据集
source_floder_path = './source'
# 图片目标路径
images_folder = source_floder_path + '/images'
# 标签目标路径
labels_folder = source_floder_path + '/labels'def CollateDataset(image_dir,label_dir):  # image_dir:图片路径  label_dir:标签路径# 创建一个空列表来存储有效图片的路径valid_images = []# 创建一个空列表来存储有效 label 的路径valid_labels = []# 遍历 images 文件夹下的所有图片for image_name in os.listdir(image_dir):# 获取图片的完整路径image_path = os.path.join(image_dir, image_name)# 获取图片文件的扩展名ext = os.path.splitext(image_name)[-1]# 根据扩展名替换成对应的 label 文件名label_name = image_name.replace(ext, ".txt")# 获取对应 label 的完整路径label_path = os.path.join(label_dir, label_name)# 判断 label 是否存在if not os.path.exists(label_path):# # 删除图片# os.remove(image_path)print("there is no:", label_path)else:# 将图片路径添加到列表中valid_images.append(image_path)# 将 label 路径添加到列表中valid_labels.append(label_path)# 遍历每个有效图片路径for i in range(len(valid_images)):image_path = valid_images[i]label_path = valid_labels[i]# 随机生成一个概率r = random.random()# 判断图片应该移动到哪个文件夹# train:valid:test = 8:2:0if r < 0.0:# 移动到 test 文件夹destination = "./datasets/test"elif r < 0.2:# 移动到 valid 文件夹destination = "./datasets/valid"else:# 移动到 train 文件夹destination = "./datasets/train"# 创建目标文件夹中 images 和 labels 子文件夹os.makedirs(os.path.join(destination, "images"), exist_ok=True)os.makedirs(os.path.join(destination, "labels"), exist_ok=True)# 生成目标文件夹中图片的新路径image_destination_path = os.path.join(destination, "images", os.path.basename(image_path))# 移动图片到目标文件夹shutil.copy(image_path, image_destination_path)# 生成目标文件夹中 label 的新路径label_destination_path = os.path.join(destination, "labels", os.path.basename(label_path))# 移动 label 到目标文件夹shutil.copy(label_path, label_destination_path)def CopyImagesAndLabels(path):# 定义图片尾缀image_suffix = ['.png']# 定义标签尾缀label_suffix = ['.txt']# 遍历源文件夹中的文件for filename in os.listdir(path):print(f"FileName is {filename}")# 将路径分隔符从 '\\' 替换为 '/'filename = filename.replace('\\', '/')# 检查文件是否为图片的后缀结尾for suffix in image_suffix:#图片移动到图片路径if filename.endswith(suffix):# 拼接路径字符串source_file = os.path.normpath(os.path.join(os.getcwd(), path, filename))dest_file = os.path.normpath(os.path.join(os.getcwd(), images_folder, filename))# 复制文件if os.path.exists(source_file):try:# 复制文件# 确保目标文件夹存在,递归创建目录os.makedirs(os.path.dirname(dest_file), exist_ok=True)print(f"Copying Image {source_file} to {dest_file}")shutil.copy(source_file, dest_file)except Exception as e:print(f"Error: {e}") # 检查文件是否为标签的后缀结尾for suffix in label_suffix:#图片移动到图片路径if filename.endswith(suffix):# 拼接路径字符串source_file = os.path.normpath(os.path.join(os.getcwd(), path, filename))dest_file = os.path.normpath(os.path.join(os.getcwd(), labels_folder, filename))# 复制文件print(f"Copy Label {source_file} to {dest_file}")if os.path.exists(source_file):try:# 复制文件# 确保目标文件夹存在,递归创建目录os.makedirs(os.path.dirname(dest_file), exist_ok=True)print(f"Copying Label {source_file} to {dest_file}")shutil.copy(source_file, dest_file)print("File copied successfully!")except Exception as e:print(f"Error: {e}")# 拷贝完成print("File copied successfully!")if __name__ == '__main__':# 整理训练集CopyImagesAndLabels(source_floder_path)CollateDataset(images_folder, labels_folder)

source_floder_path替换成数据集所在路径
images_folder和labels_folder为图片集和标记集所在路径
image_suffix和label_suffix为图片集和标签集的尾缀
destination为最终训练集和验证集所在路径

以上代码只复制png和txt尾缀的数据集

备注:转换后可以在本地路径上检查是否整理成功
在这里插入图片描述

Step4 训练数据集

下载YOLOv10训练源码

4.1创建yaml文件

在这里插入图片描述

Train/val替换成数据集所在绝对路径
Classes为标签数量与名称

4.2训练

from ultralytics import YOLOv10
import torch
import cv2
import os# 模型配置文件
model_yaml_path = "./ultralytics/cfg/models/v10/yolov10n.yaml"
# 数据集配置文件
data_yaml_path = os.path.normpath(os.path.join(os.getcwd(), './yolov10-main/ultralytics/cfg/datasets/mytrain.yaml'))
# 预训练模型
pre_model_name = os.path.normpath(os.path.join(os.getcwd(), './yolov10-main/weights/yolov10n.pt'))
# 模型保存路径
save_model_name = os.path.normpath(os.path.join(os.getcwd(), './yolov10-main/runs/detect/mytrain_0729'))if __name__ == '__main__':print(torch.__version__)  #注意,这里也是两个下划线print(cv2.__version__)# 加载预训练模型model = YOLOv10(model_yaml_path).load(pre_model_name)# model = YOLOv10(pre_model_name)# 训练模型results = model.train(data=data_yaml_path, epochs=10, batch=8, name=save_model_name)

data_yaml_path替换成4.1步骤下yaml的名称与路径
pre_model_name为预训练模型区别如下图
在这里插入图片描述

4.3故障排查

4.3.1OpenCV版本故障,把OpenCV版本升级到4.0以上

ModuleNotFoundError: No module named ‘cv2’

下载所需版本的OpenCV包,将安装好的.whl文件拷贝到.\Anaconda3\Lib\site-packages文件夹中,并将原来的OpenCV卸载
pip uninstall opencv-python
pip uninstall opencv-contrib-python
cd .\Anaconda3\Lib\site-packages
pip install msgpack-python
pip install msgpack
pip install x.whl

备注:版本cp后的数字代表了适配Python的版本。如果你的Python版本是3.7.4请务必选择cp37,其它依此类推。对于我们Windows64位系统,应当选择win_amd64系列。

4.3.2NumPy版本故障,把NumPy降低版本到1.26.4

A module that was compiled using NumPy 1.x cannot be run in NumPy 2.0.1 as it may crash. To support both 1.x and 2.x versions of NumPy, modules must be compiled with NumPy 2.0. Some module may need to rebuild instead e.g. with ‘pybind11>=2.12’.

pip uninstall numpy
pip install numpy==1.26.4

4.3.3没有安装ultralytics模块

New https://pypi.org/project/ultralytics/8.2.66 available 😃 Update with ‘pip install -U ultralytics’

pip install -U ultralytics

4.3.4Arial.ttf下载超时

解决yolov5环境配置报错Arial.ttf下载超时Downloading

4.3.5其他报错

其他报错可以搜索或者在YOLO官方常见问题文档中查找

参考博客

1.深度学习之目标检测从入门到精通——json转yolo格式
2.模型训练篇 | yolov10来了!手把手教你如何用yolov10训练自己的数据集(含网络结构 + 模型训练 + 模型推理等)
3.在win10下安装Anaconda环境并配置OpenCV
4.ModuleNotFoundError: No module named ‘torch‘ 解决方案

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

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

相关文章

Web 安全:Memcached 未授权访问漏洞.(11211端口)

Web 安全&#xff1a;Memcached 未授权访问漏洞 Memcached 是一套常用的 key-value 缓存系统&#xff0c;由于它本身没有权限控制模块&#xff0c;所以对公网开放的 Memcache 服务很容易被攻击者扫描发现。然而 Memcached 的默认配置&#xff0c;11211 端口 不需要密码即可访问…

ROUND() Function in SQL(四舍五入)

ROUND() Function in SQL ROUND() 函数用于将数值四舍五入到指定的小数位数或者整数位数。 不同的数据库系统可能会有一些细微的语法差异&#xff0c;但基本功能都是一致的。 1. 基本语法 ROUND(number, decimal_places)number: 要进行四舍五入的数值。decimal_places: 可选参…

Spring事件监听的核心机制及其原理

Spring事件监听 Spring的事件监听机制主要由三大核心部分组成即事件&#xff0c;监听器和播放器三部分组成。 事件的发布是通过spring当中的pulishEvent方法实现。事件监听实现是通过监听器监听了对应事件的监听器来实现的。 事件监听的作用&#xff1a;为系统业务之间进行一…

1、AI测试辅助-提示词优化

AI测试辅助-提示词优化 一、基本规则二、提示词优化技巧&#xff1a;2.1 Prompt 逆向工程2.2 提示词框架2.2.1 CO-STAR 框架 2.3 提示词生成器 三、总结 一、基本规则 写提示词有个通用的基本规则&#xff0c;遵循这个规则基本上能解决大部分的问答&#xff1a; 角色任务要求 …

2024经济师考试报名『注册流程』图解!

⏰报名时间&#xff1a;8月12日—9月11日 ☑️报名注册流程 1、经济师考试报名注册网站&#xff1a;中国人事考试网. 2、点击考生登录栏目中的【新用户注册】按钮&#xff0c;进行注册。 3、进入用户注册界面&#xff0c;填写注册信息。 4、填写完毕确认无误后点击【提交】&…

thinkPHP开发的彩漂网站源码,含pc端和手机端

源码简介 后台thinkPHP架构,页面程序双分离,Mysql数据库严谨数据结构、多重数据审核机制、出票机制和监控机制,html5前端技术适用移动端,后台逻辑更多以server接口可快捷实现对接pc和ap,下载会有少量图片素材丢失,附件有下载说明前端demo账户密码和后台管理地址管理员账户密码…

【C++】C++11的新特性 --- lambda表达式 ,新的类功能,模块的可变参数 , emplace系列接口

如果你停止,就是谷底! 如果你还在继续,就是上坡! 这是我听过关于人生低谷最好的阐述。 -- 刘同 C11的新特性 1 lambda表达式1.1 基本用法1.2 细谈参数列表与捕捉列表 2 新的类功能2.1 移动构造与移动赋值2.2 default和delete 3 模块的可变参数4 emplace系列接口Thanks♪(&…

C语言:指针(1)

一. 内存和地址 比如&#xff0c;我们的内存就相当⼀栋宿舍楼&#xff0c;楼里有很多的房间&#xff0c;每个房间都有一个房间号&#xff0c;每个房间里都住着8个人。这时如果你的朋友想要来找你&#xff0c;我们只需要把房间号告诉他就能快速的找到我们。 然而&#xff0c;&…

Stable Diffusion 提示词攻略

一、提示词作用 提示词所做的工作是缩小模型出图的解空间&#xff0c;即缩小生成内容时在模型数据里的检索范围&#xff0c;而非直接指 定作画结果。 提示词的效果也受模型的影响&#xff0c;有些模型对自然语言做特化训练&#xff0c;有些模型对单词标签对做特化训练&#xf…

负债了,打死也别干的六件事!逾期了,六句谎言千万别信!

负债这事儿&#xff0c;真是一言难尽&#xff0c;稍不留神&#xff0c;就可能让情况雪上加霜。今儿咱们聊聊&#xff0c;负债后那几件打死也别干的几件事&#xff0c;尤其是针对还没有逾期的朋友们&#xff0c;免得后悔莫及。 首先&#xff0c;千万别动歪脑筋&#xff0c;拿公款…

【Golang 面试 - 基础题】每日 5 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

YOLOV8-人员越界识别

原文:YOLOV8-人员越界识别 - 知乎 (zhihu.com) 一、人员越界识别背景描述 实际生活中某些场景下需要配合摄像头自动识别危险区域,并在发现有人员闯入危险区域(禁止进入区域)时进行报警。翻越围墙监测预警系统对监控区域内的护栏、围墙设定警戒围墙区域,一旦有可疑人员靠…

springboot电子产品销售系统-计算机毕业设计源码80294

摘 要 电子商务行业在全球范围内迅速发展&#xff0c;随之而来的是电子产品销售市场的快速增长和消费者对在线购物体验的需求提升&#xff0c;因此&#xff0c;电子产品销售系统应运而生。该系统旨在满足电子产品市场的需求&#xff0c;提供全面的购物功能和高效的管理操作。 …

高级及架构师高频面试题-基础型

1、设计模式有哪些原则&#xff08;待解释的更直白&#xff09; 单一职责原则&#xff1a;一个类或方法应只负责一项职责&#xff0c;避免一个类因为多个变化原因而改变。开闭原则&#xff1a;软件实体应对扩展开放&#xff0c;对修改封闭。比如要增加用户类别的时候可以新增一…

校车购票小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;我的乘车信息管理&#xff0c;车辆信息管理&#xff0c;座位管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;车辆信息&#xff0c;我的 开发系统…

【项目管理】高手项目经理都在用的6个SOP

SOP&#xff08;Standard Operating Procedure&#xff09;流程是一种标准化的操作指南&#xff0c;旨在确保组织或团队在各种情况下都能高效、一致地完成任务。SOP流程通常包括详细的步骤、关键控制点和责任分配&#xff0c;以确保质量和安全。SOP流程涉及从日常运营到危机管理…

28.x86游戏实战-初探XXX发包

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

GPT-4o mini小型模型具备卓越的文本智能和多模态推理能力

GPT-4o mini 是首个应用OpenAI 指令层次结构方法的模型&#xff0c;这有助于增强模型抵抗越狱、提示注入和系统提示提取的能力。这使得模型的响应更加可靠&#xff0c;并有助于在大规模应用中更安全地使用。 GPT-4o mini 在学术基准测试中&#xff0c;无论是在文本智能还是多模…

微信小游戏之三消(二)主要游戏控制方法

设计一个 game class。负责了游戏的核心控制逻辑&#xff0c;包括游戏状态管理、方块和道具的生成与效果处理&#xff0c;以及游戏的重新开始和复活流程。通过这些方法&#xff0c;脚本实现了游戏的基本玩法和用户交互。 主要游戏控制方法 gameStart()&#xff1a;开始游戏&am…

Java学习Day16:基础篇6

1.静态和非静态 2.调用静态和非静态的过程 注&#xff1a;在Java中&#xff0c;同类中&#xff0c;确实可以使用类的对象来调用静态方法&#xff0c;尽管这不是推荐的做法。静态方法属于类本身&#xff0c;而不是类的任何特定实例。因此&#xff0c;理论上讲&#xff0c;你应该…