YOLO实践

一. 环境安装

参考视频

  1. Pytorch环境安装细节
  • pytorch安装:一个单独的环境中,能使用pip就尽量使用pip,实在有问题的情况,例如没有合适的编译好的系统版本的安装包,再使用conda进行安装,不要来回混淆
  • CUDA是否要安装:如果只需要训练、简单推理,则无需单独安装cUDA,直接安装pytorch;如果有部署需求,例如导出TensorRT模型,则需要进行CUDA安装
  • Pytorch安装注意事项:必须使用官网的命令进行安装,否则安装的是cpu的版本
  1. 正确使用windows终端:
  • 使用cmd,而不是powershell(无法激活环境)。
  • 在其他软件,如Pycharm,vscode中也要注意!
  1. 可能出现的问题
  • Arial.ttf字体文件无法下载
    • 手动下载,放到对应的位置,windows下的目录是:~/AppData/Roaming/Ultralytics
  • 页面文件太小,无法完成操作
    • 调整训练参数中的workers,设置为1
    • 修改虚拟内存,将环境安装位置所在的盘,设置一个较大的参数
  • ‘Upsample’ object has no attribute ‘recompute _scale_factor’
    • pytorch版本过高导致,可以选择降版本,1.8.2目前是不会报错的版本
    • 如不想降低版本,可以修改pytorch源码,打开报错的unsampling.py,删除
      recompute_scale_factor这个参数

设置电脑虚拟内存:
在这里插入图片描述
在这里插入图片描述

二 .数据集制作

数据转换代码数据格式转化关键根据相应的文件格式解析处class以及bbox

  1. voc2yolo
def convert_xml_to_txt_format(xml_file_path: str, class_list: list) -> list:"""将单个xml文件转换为txt格式。参数:xml_file_path (str): XML文件的路径。class_list (list): 包含所有类别的列表。返回:list: 包含YOLO格式的标签列表。"""# 根据class_list构建class_to_id_mapclass_to_id_map = {class_name: index for index, class_name in enumerate(class_list)}tree = ET.parse(xml_file_path)root = tree.getroot()width = int(root.find('.//size/width').text)height = int(root.find('.//size/height').text)txt_format = []for obj in root.findall('.//object'):class_name = obj.find('name').textif class_name not in class_to_id_map:continueclass_id = class_to_id_map[class_name]bbox = obj.find('bndbox')xmin = float(bbox.find('xmin').text)ymin = float(bbox.find('ymin').text)xmax = float(bbox.find('xmax').text)ymax = float(bbox.find('ymax').text)x_center = (xmin + xmax) / 2 / widthy_center = (ymin + ymax) / 2 / heightbbox_width = (xmax - xmin) / widthbbox_height = (ymax - ymin) / heighttxt_format.append(f"{class_id} {x_center} {y_center} {bbox_width} {bbox_height}")return txt_formatdef write_yolo_format_labels_to_file(yolo_labels_dir: str, yolo_label_file: str, yolo_content: list):"""将YOLO格式的标签写入到文件。参数:yolo_labels_dir (str): YOLO标签目录的路径。yolo_label_file (str): YOLO标签文件的名称。yolo_content (list): 包含YOLO格式标签的列表。"""yolo_label_path = os.path.join(yolo_labels_dir, yolo_label_file)with open(yolo_label_path, 'w') as f:for line in yolo_content:f.write(line + '\n')def convert_voc2yolo(voc_annotations_dir: str, yolo_labels_dir: str, class_list: list):"""将VOC格式的XML注释转换为YOLO格式的注释。参数:voc_annotations_dir (str): VOC注释目录的路径。yolo_labels_dir (str): YOLO标签目录的路径。class_list (list): 类别名称的list。"""if not os.path.exists(yolo_labels_dir):os.makedirs(yolo_labels_dir)for xml_file in os.listdir(voc_annotations_dir):if xml_file.endswith('.xml'):yolo_label_file = xml_file.replace('.xml', '.txt')xml_file_path = os.path.join(voc_annotations_dir, xml_file)yolo_content = convert_xml_to_txt_format(xml_file_path,class_list)write_yolo_format_labels_to_file(yolo_labels_dir, yolo_label_file, yolo_content)with open(os.path.join(yolo_labels_dir,"classes.txt"),"w",encoding='utf-8') as f:for c in class_list:f.write(c+'\n')
if __name__ == "__main__":dataset_dir = "./dataset"labels_voc_dir = "labels_voc"labels_yolo_dir = "labels_yolo"class_names = ["橘子", "香蕉", "草莓"]convert_voc2yolo(labels_voc_dir,labels_yolo_dir,class_names)
  1. yolo2voc

def convert_txt_to_xml_format(txt_file_path: str, voc_file_path: str, class_names: list, images_dir: str):"""将单个txt文件转换为xml格式。参数:txt_file_path (str): YOLO标签文件txt的路径。voc_file_path (str): XML文件的路径。class_names (list): 包含类别名称的列表。images_dir (str): 包含图像文件的目录路径。"""with open(txt_file_path, 'r') as file:lines = file.readlines()# 获取txt文件的文件名,然后去掉后缀txt_filename = os.path.basename(txt_file_path)txt_filename_without_ext = os.path.splitext(txt_filename)[0]# 使用glob库在images_dir下搜索与txt文件同名的图片文件pattern = os.path.join(images_dir, f"{txt_filename_without_ext}.*")matching_files = glob.glob(pattern)if not matching_files:raise FileNotFoundError(f"No matching image found for {txt_filename_without_ext} in {images_dir}")img_file = matching_files[0]  # 假设找到的第一个匹配文件就是正确的图片# 从与YOLO标签同名的图像文件中读取宽度和高度img = Image.open(img_file)width, height = img.sizeroot = ET.Element("annotation")folder = ET.SubElement(root, "folder")folder.text = os.path.basename(images_dir)filename = ET.SubElement(root, "filename")filename.text = os.path.basename(img_file)path = ET.SubElement(root, "path")path.text = os.path.abspath(img_file)source = ET.SubElement(root, "source")database = ET.SubElement(source, "database")database.text = "Unknown"size = ET.SubElement(root, "size")ET.SubElement(size, "width").text = str(width)ET.SubElement(size, "height").text = str(height)ET.SubElement(size, "depth").text = "3"segmented = ET.SubElement(root, "segmented")segmented.text = "0"for line in lines:values = line.strip().split()if len(values) < 5:continueclass_id, x_center, y_center, bbox_width, bbox_height = map(float, values)object = ET.SubElement(root, "object")name = ET.SubElement(object, "name")name.text = class_names[int(class_id)]pose = ET.SubElement(object, "pose")pose.text = "Unspecified"truncated = ET.SubElement(object, "truncated")truncated.text = "0"difficult = ET.SubElement(object, "difficult")difficult.text = "0"bndbox = ET.SubElement(object, "bndbox")xmin = int((x_center - bbox_width / 2) * width)ymin = int((y_center - bbox_height / 2) * height)xmax = int((x_center + bbox_width / 2) * width)ymax = int((y_center + bbox_height / 2) * height)ET.SubElement(bndbox, "xmin").text = str(xmin)ET.SubElement(bndbox, "ymin").text = str(ymin)ET.SubElement(bndbox, "xmax").text = str(xmax)ET.SubElement(bndbox, "ymax").text = str(ymax)# 使用prettify函数来格式化输出pretty_xml_as_string = prettify(root)with open(voc_file_path, 'w', encoding='utf-8') as f:f.write(pretty_xml_as_string)def prettify(elem):from xml.dom import minidom"""Return a pretty-printed XML string for the Element."""rough_string = ET.tostring(elem, 'utf-8')reparsed = minidom.parseString(rough_string)return reparsed.toprettyxml(indent="	")def convert_yolo2voc(yolo_labels_dir: str, voc_labels_dir: str, images_dir: str, class_list: list):"""将YOLO格式的标签文件夹转换为VOC格式的XML注释文件夹。参数:yolo_labels_dir (str): YOLO标签文件夹的路径。voc_labels_dir (str): 转换后的VOC XML文件夹的路径。images_dir (str): 包含图像文件的目录路径。class_names (list): 包含类别名称的列表。"""# 确保voc_labels_dir存在if not os.path.exists(voc_labels_dir):os.makedirs(voc_labels_dir)# 遍历YOLO标签文件夹for label_file in os.listdir(yolo_labels_dir):if label_file.endswith(".txt"):yolo_file_path = os.path.join(yolo_labels_dir, label_file)voc_file_path = os.path.join(voc_labels_dir, label_file.replace(".txt", ".xml"))convert_txt_to_xml_format(yolo_file_path, voc_file_path, class_list, images_dir)
if __name__ == "__main__":dataset_dir = "./dataset"labels_voc_dir = "labels_voc"labels_yolo_dir = "labels_yolo"class_names = ["橘子", "香蕉", "草莓"]convert_yolo2voc(labels_yolo_dir,labels_voc_dir,"imgs",class_names)
  1. Json转Yolo

提示可以采用 data_df = pd.read_json(json_path),然后利用pandas的语法进行提取bbox和class_id

  1. 划分数据集
def split_dataset(images_origin_dir: str, labels_origin_dir: str, dataset_dir: str, train_ratio: float = 0.8):"""将原始数据集分割为训练集和验证集,并将相应的文件复制到新的文件夹中。参数:images_origin (str): 存放所有图片文件夹路径labels_origin (str): 存放所有标签文件夹路径。dataset_dir (str): 新的数据集根目录。train_ratio (float, optional): 训练集的比例,默认为 0.8。"""images_dir = os.path.join(dataset_dir, "images")labels_dir = os.path.join(dataset_dir, "labels")train_dir = os.path.join(images_dir, "train")val_dir = os.path.join(images_dir, "val")# 创建训练集和验证集的文件夹os.makedirs(train_dir, exist_ok=True)os.makedirs(val_dir, exist_ok=True)os.makedirs(os.path.join(labels_dir, "train"), exist_ok=True)os.makedirs(os.path.join(labels_dir, "val"), exist_ok=True)image_files=[]for file in os.listdir(images_origin_dir):if file.endswith(".jpg") or file.endswith(".png") or file.endswith(".jpeg"):image_files.append(os.path.join(images_origin_dir, file))# 使用 random.sample 函数进行随机划分random.seed(42)  # 设置随机种子train_images = random.sample(image_files, k=int(len(image_files) * train_ratio))val_images = [f for f in image_files if f not in train_images]# 复制文件到训练集和验证集文件夹for subset, images in [('train', train_images), ('val', val_images)]:for image_file in images:# 复制图片文件target_image_path = os.path.join(images_dir, subset, os.path.basename(image_file))shutil.copyfile(image_file, target_image_path)# 复制标签文件label_file = os.path.splitext(os.path.basename(image_file))[0] + '.txt'label_path = os.path.join(labels_origin_dir, label_file)if os.path.exists(label_path):target_label_path = os.path.join(labels_dir, subset, label_file)shutil.copyfile(label_path, target_label_path)print(f"训练集大小: {len(train_images)}")print(f"验证集大小: {len(val_images)}")if __name__ == "__main__":dataset_dir = "./dataset"labels_voc_dir = "labels_voc"labels_yolo_dir = "labels_yolo"class_names = ["橘子", "香蕉", "草莓"]split_dataset("imgs",labels_yolo_dir,dataset_dir)

三.模型使用

  1. YOLOV5 模型调用(本地)
# Model
model = torch.hub.load('.', 'custom', path=r'best.pt',source='local')

.: 本地的yolov5的根目录
source=“local”:从本地调用该模型

  1. YOLOV8 模型调用
# Load the YOLOv8 model
model = YOLO("yolov8n.pt")  # Make sure the model file is in the correct path

如果本地不存在yolov8n.pt,则从网上下载

四. 结果处理

.xyxy():即为[x_min,y_min,x_max,y_max]

  1. YOLOV5 参考博客
import torch
model = torch.hub.load('.', 'yolov5s', source='local') 
im = r'data\images\bus.jpg'  # file, Path, PIL.Image, OpenCV, nparray, list`
results = model(im)  # inference
# results.crop()  # or .show(), .save(), .crop(), .pandas(), etc.

results是一个Detections对象,主要有以下方法:

# results.crop()  # or .show(), .save(), .crop(), .pandas(), etc.
results.xyxy[0]   #Tensor类型
results.pandas().xyxy[0]  #转为pandas格式
results.print()  #控制台显示
frame = results.render()[0]  # 将模型的输出绘制回帧上

另外:想要个性化输出,限定类别

# 将检测结果转换为Pandas DataFrame格式
detections_df = results.pandas().xyxy[0]# 筛选出标签名为'person'的所有检测结果
person_detections = detections_df[detections_df['name'] == 'person'].to_numpy()# 遍历检测到的人
for detection in person_detections:label_name = detection[6]  # 获取标签名bbox = detection[:4].astype('int')  # 获取边界框坐标并转换为整数# 在图像上绘制边界框cv.rectangle(image_temp, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 0, 255), 3)# 在边界框左上角添加标签名cv.putText(image_temp, label_name, (bbox[0] - 10, bbox[1] - 10), cv.FONT_ITALIC, 1, (0, 255, 0), 2)
  1. YOLOV8

建议:ultalytics源码安装,在ultralytics的根目录下pip install -e . -e指的是本地可编辑,下载该库时不会直接下载到site-packages下,而是以链接的方式链接到源码的根目录下

from ultralytics import YOLO
model=YOLO("yolov8n-seg.pt")
results=model(r"images\bus.jpg")

这里的results是list类型。

for idx, result in enumerate(results):boxes = result.boxes  # Boxes object for bounding box outputsmasks = result.masks  # Masks object for segmentation masks outputskeypoints = result.keypoints  # Keypoints object for pose outputsprobs = result.probs  # Probs object for classification outputsobb = result.obb  # Oriented boxes object for OBB outputsif len(boxes.cls) == 0:continuexyxy = boxes.xyxy.data.cpu().numpy().round()cls = boxes.cls.data.cpu().numpy().round()conf = boxes.conf.data.cpu().numpy()

另外:如果想要个性化输出,可以使用 patched_yolo_infer库(我只验证了YOLOV8,其它的YOLO系列不知道)

import cv2
from ultralytics import YOLO
from patched_yolo_infer import visualize_results_usual_yolo_inference# Load the image
img_path = 'images/bus.jpg'
img = cv2.imread(img_path)img=visualize_results_usual_yolo_inference(img,model,conf=0.4,iou=0.7,show_classes_list=[0], #Whether to perform instance segmentation. Default is False.segment=True,          #是否分割thickness=5,show_boxes=False,fill_mask=False,      alpha=0.7,			#The transparency of filled masks. Default is 0.3.show_class=False,delta_colors=25,     #The random seed offset for color variation. Default is 0.inference_extra_args={'retina_masks':True}, #increase the accuracy of the contoursreturn_image_array=True)

:Pyme组件

import cv2 as cv
from PIL import ImageTk, Image
class VideoPlayer():def __init__(self,elementName,video_source=0):super().__init__()self.video_source = video_sourceself.vid = cv.VideoCapture(self.video_source)self.label= Fun.GetElement(uiName,elementName)  #如果想要替换为tk,这里直接注入label对象self.delay = 15self.paused = False  # 暂停状态标志self.update()def update(self):# 检查是否成功读取帧if self.vid.isOpened():if not self.paused:ret, frame = self.vid.read()if ret:frame = self.process_frame(frame)# 转换为Imageself.photo = ImageTk.PhotoImage(image=Image.fromarray(frame))self.label.config(image=self.photo)else:self.vid.release()returnself.label.after(self.delay, self.update)def process_frame(self, frame):#convert BGR to RGBframe = cv.cvtColor(frame, cv.COLOR_BGR2RGB)return framedef pause(self):self.paused = not self.pausedreturn self.pauseddef stop(self):self.vid.release()

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

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

相关文章

数据结构---顺序表---单链表

目录 一、什么是程序&#xff1f; 程序 数据结构 算法 二、一个程序是否优秀的两个标准 2.1.时间复杂度 2.2.空间复杂度 三、数据结构 3.1.数据结构间的关系 1.逻辑结构 1&#xff09;线性关系 2&#xff09;非线性关系 2.存储结构 1&#xff09;顺序存储结构 …

exit_hook和setcontext

文章目录 exit_hook概述例题:思路:利用:setcontextglibc-2.27以及 之前glibc-2.29以及之后:exit_hook 概述 大佬文章:exit_hook在pwn题中的应用 - 不会修电脑 - 博客园 (cnblogs.com) exit_hook :是程序在执行exit函数时,会去该位置拿一个函数指针,进而执行的一段程序…

【单片机开发】IAP技术详解及应用

【前言】 在单片机开发过程中&#xff0c;程序的烧录是一个至关重要的环节。随着技术的不断演进&#xff0c;单片机烧录方式也日益多样化。 【单片机开发】单片机的烧录方式详解&#xff08;ICP、IAP、ISP&#xff09;-CSDN博客文章浏览阅读775次&#xff0c;点赞14次&#x…

低空经济概念火爆:无人机飞手人才培养先行

随着科技的飞速发展&#xff0c;低空经济作为新兴的经济形态&#xff0c;正以前所未有的速度崛起&#xff0c;成为推动产业升级和经济发展的新引擎。无人机作为低空经济的重要组成部分&#xff0c;其应用领域已从最初的军事侦察、航拍扩展到农业植保、物流配送、环境监测、应急…

Question mutiple pdf‘s using openai, pinecone, langchain

题意&#xff1a;使用 OpenAI、Pinecone 和 LangChain 对多个 PDF 文件进行提问。 问题背景&#xff1a; I am trying to ask questions against a multiple pdf using pinecone and openAI but I dont know how to. 我正在尝试使用 Pinecone 和 OpenAI 对多个 PDF 文件进行提…

【计算机组成原理】计算机系统的层次结构——计算机软件

计算机系统的层次结构 导读一、计算机软件的分类二、计算机语言三、计算机系统的层次结构3.1 从计算机语言的角度来理解多级层次结构3.2 计算机层次之间的关系3.3 指令集体系结构&#xff08;ISA&#xff09; 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&a…

市占率最高的显示器件,TFT_LCD的驱动系统设计--Part 1

目录 一、简介 二、TFT-LCD驱动系统概述 &#xff08;一&#xff09;系统概述 &#xff08;二&#xff09;设计要点 二、扫描驱动电路设计 &#xff08;一&#xff09;概述 扫描驱动电路的功能 扫描驱动电路的组成部分 设计挑战 驱动模式 &#xff08;二&#xff09…

多目标应用:基于MOPSO的移动机器人路径规划研究(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

Ubuntu上qt使用SSH样式表

SSH样式表 如果学习过web的同学都知道&#xff0c;我们在学习HTML的时候会用到样式表&#xff0c;我们使用它来更改我们的颜色、大小、背景等等。上到后面&#xff0c;老师会说&#xff1a;我们如果在HTML文件中编辑太多的样式&#xff0c;就会让代码看起来非常的繁琐&#xf…

学习计算机网络

a类0~127&#xff0c;b类128~191&#xff0c;c类192~223 网络地址&#xff1a;看子网掩码&#xff0c;分网络位和主机位&#xff0c;后面是主机位&#xff0c;主机位全部为0&#xff0c;网络地址。 直接广播地址&#xff1a;看子网掩码&#xff0c;分网络位和主机位&#xff…

自建一款开源音乐服务-Navidrome

自建一款开源音乐服务-Navidrome Navidrome&#xff0c;一个开源的音乐服务器和播放器&#xff0c;提供了一个优雅且功能丰富的解决方案&#xff0c;让你的音乐库无论在何处都能触手可及。本文将带你一步步搭建自己的Navidrome音乐服务器&#xff0c;让你的音乐生活更加自由和…

【Qt】关于QMenuBar创建方式的讨论

关于QMenuBar创建方式的讨论 如果在创建项目的时候&#xff0c;没有勾选自动生成ui文件&#xff0c;此时上述代码是正确的&#xff1b;而如果勾选了自动生成ui文件&#xff0c;上述代码则会出现内存泄漏的问题。因为Qt已经生成了一个QMenuBar了 由于之前程序已经自己创建好了一…

STM32 系列MCU 开发利器 STM32CubeIDE

前言 由于自己接触较多的 ARM 系列芯片主要是 STM32 系列的&#xff0c;接触过 STM32 F1、F4、L4、H7 等几个系列&#xff0c;使用的 开发工具&#xff0c;主要是 Keil MDK5、IAR&#xff0c;所以也比较关注开发工具的使用。 Keil MDK5、IAR 属于商用收费的功能强大的IDE&…

【MATLAB】matlab生成的图像如何导出(三种方法教会你)

我们经常使用matlab生成各类的图&#xff0c;如何将其导出&#xff0c;导出为何种类型。 方法一&#xff1a;选择 matlab 生成的图形界面 " Figure 1 " 的菜单栏 " 编辑 " — " 复制图窗 " , 就可以将图像拷贝到 Word 文档中 打开 Word 文档 ,…

单片机编程魔法师-消息处理

消息机制 消息处理的编程思路是当某件事产生后只发送一条事件产生消息以通知相应执行机构执行的一种编程思路。 消息定义 什么是消息&#xff0c;消息是一个指示&#xff0c;可以是数字&#xff0c;字符串&#xff0c;字符或者是任何形式的其他标识符 消息定义的形式与消息…

简易的 Websocket + 心跳机制 + 尝试重连

文章目录 演示大纲基础 WebSocket前端: 添加心跳机制前端: 尝试重新连接历史代码 还没有写完&#xff0c;bug 是有的&#xff0c;我在想解决办法了… 演示 大纲 基础的 webSocket 连接前后端&#xff1a;添加心跳机制后端无心跳反应&#xff0c;前端尝试重新连接设置重新连接…

计算多图的等价无向图的邻接链表表示

计算多图的等价无向图的邻接链表表示 摘要:一、引言二、算法思路三、伪代码实现四、C代码实现五、算法分析六、结论摘要: 在图论中,多图(Multigraph)是一种允许边重复以及存在自循环边(即一个顶点到其自身的边)的图。给定一个多图的邻接链表表示,本文旨在探讨如何构造…

PHP软件下载-安装-环境配置

.1.下载 下载地址如下 windows.php.net - /downloads/releases/ 安装包如下. .2.安装 可以在D盘或者E盘的根目录创建一个自定义目录。注意文件夹目录中不能包含中文&#xff0c;不能包含空格等特殊字符。 版本说明&#xff1a; (1)ts表示非线程安全版本。这个安装包还指明了…

c++模拟实现数据结构之vector篇

那么本篇文章是带大家一起实现一下数据结构vector&#xff0c;那么我们现在就进入正题。 目录 接口介绍部分 增加 尾插 指定插入与头插 删除 尾删 指定位置删除 主要代码逻辑 增加 尾插 指定插入与头插 删除 尾删 指定位置删除 一些其他接口的代码逻辑 模拟实现…

django企业开发实战-学习小结

写在前面 初次阅读此书是三年前&#xff0c;当时没经历过完整的项目 觉得这书就是扯淡 后来经历过项目加班与毒打 今天再翻开此书 觉得实乃不可多得之物 花些时间啃下来吧 django版本 3.2 本博客开源项目地址 kimsmith/django企业实战 (gitee.com) 有的代码因为版本混乱报错…