YOLOv5与YOLOv8 训练准备工作(不包含环境搭建)

news2024/9/19 13:03:49

前言:我发现除了安装环境需要耗费大量时间以外,对于训练前的准备工作也要琢磨一段时间,所以本篇主要讲一下训练前需要准备的工作(主要是XML格式换为txt,以及划分数据集验证集,和训练参数的设置),我在这里都总结一下,留给下次训练的我查看,以及广大网友参考。(默认一些基础的环境例如(CUDA.pytorch.torchvision.opencv)已经搭建好以及安装完requirements)2024.8.6

YOLOv5:

XML格式换为txt,以及划分数据集验证集:

1.首先需要准备好图片(需要训练的图片)和标签(通过labelimg打完标签)按照以下目录存放:
                                         
格式如下:(需要自己完整地创造出以下目录,方便后续进行)
|——VOCdevkit
||——images
        ——train  (空)     
        ——val    (空)
||——labels
        ——train  (空)
        ——val    (空)
||——VOC2007
        ——Annotations  (放置自己的标签XML文件)
        ——JPEGImages   (放置自己的训练图片)
        ——label  (空)  

2.然后在yolov5-5.0目录下(位置不重要)创建xml转YOLO.py 复制粘贴代码↓

代码如下: (没有安装包就pip Install一下)

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join


def convert(size, box):
    x_center = (box[0] + box[1]) / 2.0
    y_center = (box[2] + box[3]) / 2.0
    x = x_center / size[0]
    y = y_center / size[1]
    w = (box[1] - box[0]) / size[0]
    h = (box[3] - box[2]) / size[1]
    return (x, y, w, h)


def convert_annotation(xml_files_path, save_txt_files_path, classes):
    xml_files = os.listdir(xml_files_path)
    print(xml_files)
    for xml_name in xml_files:
        print(xml_name)
        xml_file = os.path.join(xml_files_path, xml_name)
        out_txt_path = os.path.join(save_txt_files_path, xml_name.split('.')[0] + '.txt')
        out_txt_f = open(out_txt_path, 'w')
        tree = ET.parse(xml_file)
        root = tree.getroot()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)

        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in classes or int(difficult) == 1:
                continue
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            # b=(xmin, xmax, ymin, ymax)
            print(w, h, b)
            bb = convert((w, h), b)
            out_txt_f.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


if __name__ == "__main__":
    # 需要转换的类别,需要一一对应  替换为自己的类别
    classes1 = ['red', 'green','blue','bottle']  
    # 2、voc格式的xml标签文件路径 替换为自己的标签文件文件xml(Annotations)所在绝对路径
    xml_files1 = r'D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\VOC2007\Annotations'
    # 3、转化为yolo格式的txt标签文件存储路径  替换为自己想要储存txt标签文件的路径 (label) 
    save_txt_files1 = r'D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\VOC2007\label'

    convert_annotation(xml_files1, save_txt_files1, classes1)

注:修改一下classes1    xml_files1    save_txt_files1 替换为自己的路径

运行过后会得到自己的txt文件:

                                                      

3.然后把JPEGImages 里的图片和刚刚转换好的label里的文件分别复制到 images/train || labels/train这两个地方:

                            

4.然后在yolov5-5.0目录下(位置不重要)创建划分数据集和验证集.py  复制粘贴代码↓

import os, random, shutil


def moveimg(fileDir, tarDir):
    pathDir = os.listdir(fileDir)  # 取图片的原始路径
    filenumber = len(pathDir)
    rate = 0.1  # 自定义抽取图片的比例,比方说100张抽10张,那就是0.1
    picknumber = int(filenumber * rate)  # 按照rate比例从文件夹中取一定数量图片
    sample = random.sample(pathDir, picknumber)  # 随机选取picknumber数量的样本图片
    print(sample)
    for name in sample:
        shutil.move(fileDir + name, tarDir + "\\" + name)
    return


def movelabel(file_list, file_label_train, file_label_val):
    for i in file_list:
        if i.endswith('.jpg'):
            # filename = file_label_train + "\\" + i[:-4] + '.xml'  # 可以改成xml文件将’.txt‘改成'.xml'就可以了
            filename = file_label_train + "\\" + i[:-4] + '.txt'  # 可以改成xml文件将’.txt‘改成'.xml'就可以了
            if os.path.exists(filename):
                shutil.move(filename, file_label_val)
                print(i + "处理成功!")


if __name__ == '__main__':
    fileDir = r"D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\images\train" + "\\"  # 源图片文件夹路径
    tarDir = r'D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\images\val'  # 图片移动到新的文件夹路径
    moveimg(fileDir, tarDir)
    file_list = os.listdir(tarDir)
    file_label_train = r"D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\labels\train"  # 源图片标签路径
    file_label_val = r"D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\labels\val"  # 标签
    # 移动到新的文件路径
    movelabel(file_list, file_label_train, file_label_val)

注:修改一下

fileDir   = ——\VOCdevkit\images\train           (images\train 所在的绝对路径)

tarDir    = ——\VOCdevkit\images\val               (images\val 所在的绝对路径)

file_label_train   = ——\VOCdevkit\labels\train      (labels\train 所在的绝对路径)

file_label_val      =——\VOCdevkit\labels\val         (labels\val 所在的绝对路径)

运行代码即可得到训练集和验证集

训练参数设置:

1.在data文件夹下创建xxx.yaml :可以复制随便一个yaml文件然后改个名字(我的为GKS.yaml)和内容

                                                         

内容如下:(具体看注释)

# PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC/
# Train command: python train.py --data voc.yaml
# Default dataset location is next to /yolov5:
#   /parent_folder
#     /VOC
#     /yolov5


# download command/URL (optional)
#download: bash data/scripts/get_voc.sh

# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\images\train  # 存放自己的训练集
val: D:\yolov5\yolov5-5.0\yolov5-5.0\VOCdevkit\images\val      # 存放自己的验证集

# number of classes
nc: 4        #自己的标签分类个数 在这里我的是四个  ↓

# class names
names: [ 'red','green','blue','bottle' ]  #标签分类名字 最好按照固定的顺序

然后进入如下目录:

                                             

复制yolov5s.yaml(根据自己所需模型大小选择)   改名为xxx.yaml(这里我的为yolov5_GKS.yaml)

其他都不动,修改nc:xxx(修改为你的标签分类数量,我的是4)

至此基本内容已经准备好了!

然后进入 train.py

 改一下这几个路径,对应上面自己定义的yaml文件夹即可

parser.add_argument("--weights", type=str, default="D:\yolov5\yolov5-master\weights\yolov5s.pt", help="initial weights path")  #权重文件需要自己下载
parser.add_argument("--cfg", type=str, default="D:\yolov5\yolov5-master\models\yolov5_GKS.yaml", help="model.yaml path")   #在models下的yaml文件
parser.add_argument("--data", type=str, default="D:\yolov5\yolov5-master\data\GKS.yaml", help="dataset.yaml path")          #在data下的yaml文件

其他参数可以看网上的自定义

至此可以开始训练了!

YOLOv8:

相比于YOLOv5 YOLOv8配置更简单一些:

XML格式换为txt,以及划分数据集验证集:

1.首先在yolov8目录下新建文件data                                                         D:\yolov8\data 
2.在data下创建images文件夹用于存放                                                     D:\yolov8\data\images (把训练图片放在这里面)
3.在data下创建Annotations文件夹用于存放打标签xml文件                         D:\yolov8\data\Annotations (把训练xml文件放在这里面)
4.在data下创建labels文件夹用于存放YOLO格式txt文件                     D:\yolov8\data\labels (暂时为空)

整体结构如下:

2.在data下创建:1.XML转TXT格式.py 文件 

复制黏贴以下代码进行XML格式转化为TXT格式:      (具体细节看注释)

import xml.etree.ElementTree as ET
import os, cv2
import numpy as np
from os import listdir
from os.path import join

classes = ['red','green','blue','bottle']  #修改自己的训练分类


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(xmlpath, xmlname):
    with open(xmlpath, "r", encoding='utf-8') as in_file:
        txtname = xmlname[:-4] + '.txt'
        txtfile = os.path.join(txtpath, txtname)
        tree = ET.parse(in_file)
        root = tree.getroot()
        filename = root.find('filename')
        img = cv2.imdecode(np.fromfile('{}/{}.{}'.format(imgpath, xmlname[:-4], postfix), np.uint8), cv2.IMREAD_COLOR)
        h, w = img.shape[:2]
        res = []
        for obj in root.iter('object'):
            cls = obj.find('name').text
            if cls not in classes:
                classes.append(cls)
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            bb = convert((w, h), b)
            res.append(str(cls_id) + " " + " ".join([str(a) for a in bb]))
        if len(res) != 0:
            with open(txtfile, 'w+') as f:
                f.write('\n'.join(res))


if __name__ == "__main__":
    postfix = 'jpg'
    imgpath = 'D:\yolov8\data\images'          #修改为自己images的绝对路径
    xmlpath = 'D:\yolov8\data\Annotations'     #修改为自己Annotations的绝对路径
    txtpath = 'D:\yolov8\data\labels'          #修改为自己要储存的txt文件的绝对路径

    if not os.path.exists(txtpath):
        os.makedirs(txtpath, exist_ok=True)

    list = os.listdir(xmlpath)
    error_file_list = []
    for i in range(0, len(list)):
        try:
            path = os.path.join(xmlpath, list[i])
            if ('.xml' in path) or ('.XML' in path):
                convert_annotation(path, list[i])
                print(f'file {list[i]} convert success.')
            else:
                print(f'file {list[i]} is not xml format.')
        except Exception as e:
            print(f'file {list[i]} convert error.')
            print(f'error message:\n{e}')
            error_file_list.append(list[i])
    print(f'this file convert failure\n{error_file_list}')
    print(f'Dataset Classes:{classes}')

运行完后会发现labels文件夹下会多出txt文件,这就代表成功了!

2.在data下创建:2.划分测试训练验证集.py 文件

复制黏贴以下代码进行训练集测试集验证集的划分:

# coding=gb2312
import os
import random
import shutil

# 原数据集目录
root_dir = 'D:\yolov8\data'      #改为data文件夹的绝对路径
# 划分比例
train_ratio = 0.7
valid_ratio = 0.2
test_ratio = 0.1

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

# 拆分后数据集目录
split_dir = 'D:\yolov8\data'     #改为data文件夹的绝对路径 (跟上面是同一个路径)
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'))
label_files = os.listdir(os.path.join(root_dir, 'labels'))

# 随机打乱文件列表
combined_files = list(zip(image_files, label_files))
random.shuffle(combined_files)
image_files_shuffled, label_files_shuffled = zip(*combined_files)

# 根据比例计算划分的边界索引
train_bound = int(train_ratio * len(image_files_shuffled))
valid_bound = int((train_ratio + valid_ratio) * len(image_files_shuffled))

# 定义移动函数
def move_files(src_image_dir, src_label_dir, dest_image_dir, dest_label_dir, files):
    for image_file, label_file in files:
        src_image_path = os.path.join(src_image_dir, image_file)
        src_label_path = os.path.join(src_label_dir, label_file)
        dest_image_path = os.path.join(dest_image_dir, image_file)
        dest_label_path = os.path.join(dest_label_dir, label_file)
        shutil.copyfile(src_image_path, dest_image_path)
        shutil.copyfile(src_label_path, dest_label_path)

# 移动文件到划分后的目录
move_files(os.path.join(root_dir, 'images'), os.path.join(root_dir, 'labels'),
           os.path.join(split_dir, 'train', 'images'), os.path.join(split_dir, 'train', 'labels'),
           combined_files[:train_bound])

move_files(os.path.join(root_dir, 'images'), os.path.join(root_dir, 'labels'),
           os.path.join(split_dir, 'valid', 'images'), os.path.join(split_dir, 'valid', 'labels'),
           combined_files[train_bound:valid_bound])

move_files(os.path.join(root_dir, 'images'), os.path.join(root_dir, 'labels'),
           os.path.join(split_dir, 'test', 'images'), os.path.join(split_dir, 'test', 'labels'),
           combined_files[valid_bound:])

执行完后即可得到此次训练所需要的训练集、测试集、验证集了!

目录如下:

训练参数设置:

跟YOLOv5一样,本次我们需要准备两个yaml文件如图所示:

一个是xxx.yaml (我的叫data.yaml)训练集验证集测试集路径文件:

可以首先复制黏贴任意一个xxx.yaml文件到data目录下,然后删除所有内容再直接复制以下代码: 

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
train: D:\yolov8\data\train # 改为自己的训练集的绝对路径
val: D:\yolov8\data\valid # 改为自己的验证集的绝对路径
test: D:\yolov8\data\test # 改为自己的测试集的绝对路径

nc: 4  #改为训练类别个数

# Classes
names: ['red','green','blue','bottle']  #改为自己的训练类别名字

                                                                注意看注释

一个是xxx.yaml (我的叫yolov8n.yaml)训练集验证集测试集路径文件如下图所示:

可以复制这个路径下的文件(可选择自己的模型,我选的是yolov8.yaml)到data目录下,改为自己想要的名字,然后只需要修改nc:xxx为自己训练类别个数即可

然后我们还需要从官网上下载一个yolov8n.pt 文件到data目录下

官方网址如下:

https://github.com/ultralytics/ultralytics?tab=readme-ov-fileicon-default.png?t=N7T8https://github.com/ultralytics/ultralytics?tab=readme-ov-file点YOLOv8n 下载权重文件放到data目录下

至此我们的文件目录应该长这样:

然后如果我们要训练,直接在终端执行如下代码:

yolo task=detect mode=train model=D:\yolov8\data\yolov8n.yaml  data=D:\yolov8\data\data.yaml epochs=300 workers=5 device=0

其中model = yolov8n.yaml的绝对路径 data = data.yaml的绝对路径 epochs为训练轮数 device = 0代表使用GPU训练 如果没有可以去掉device = 0

至此就已经可以开始训练了!

附上摄像头检测代码:

import cv2
from ultralytics import YOLO

# 模型加载权重
model = YOLO(r'xxx\weights\best.pt')  #训练出最好的权重绝对路径
# 视频路径
cap = cv2.VideoCapture(0)
# 对视频中检测到目标画框标出来
while cap.isOpened():
    # Read a frame from the video
    success, frame = cap.read()

    if success:
        # Run YOLOv8 inference on the frame
        results = model(frame,conf=0.7)


        # Visualize the results on the frame
        annotated_frame = results[0].plot()

        # Display the annotated frame
        cv2.imshow("YOLOv8 Inference", annotated_frame)

        # Break the loop if 'q' is pressed
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        # Break the loop if the end of the video is reached
        break

# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()

如有不懂希望可以在评论区多多交流!谢谢!

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

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

相关文章

8–9月,​Sui Move智能合约工作坊将在台北+线上举行

你对区块链和去中心化应用感兴趣吗?想深入学习Sui Move编程语言吗? 从8月10日到9月28日,Sui Mover社区将在每周六下午13:00–17:00举办精彩的工作坊,为期两个月,带你从零基础入门到高级进阶,全面掌握Sui M…

Django配置模板引擎

【图书介绍】《Django 5企业级Web应用开发实战(视频教学版)》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 《Django 5企业级Web应用开发实战(视频教学版)》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 本节主要介…

Linux之进程间通信(上)

目录 进程间通信的目的 进程通信的分类 进程通信之匿名管道 创建匿名管道 匿名管道的特点 匿名管道四种通信类型 在现实生活中,人们要进行合作,就必须进行交流,那么在进程之间,会存在交流的情景吗?答案是肯定的…

音频转换器在线哪个好?提升音频质量的转换工具

你是否曾梦想过将手机里的铃声变成自己的原创作品?或者,有没有想过将一段演讲录音转化为易于分享的MP3格式? 如果答案是肯定的,那么这款音频转换器mp3就是你寻找的答案。现在,让我们一起探索它的魅力吧! 一…

基于MATLAB机器学习、深度学习实践技术

近年来,MATLAB在机器学习和深度学习领域的发展取得了显著成就。其强大的计算能力和灵活的编程环境使其成为科研人员和工程师的首选工具。在无人驾驶汽车、医学影像智能诊疗、ImageNet竞赛等热门领域,MATLAB提供了丰富的算法库和工具箱,极大地…

浏览器用户文件夹详解 - Preferences(十)

1.Preferences简介 1.1 什么是Preferences文件? Preferences文件是Chromium浏览器中用于存储用户个性化设置和配置的一个重要文件。每当用户在浏览器中更改设置或安装扩展程序时,这些信息都会被记录在Preferences文件中。通过这些记录,浏览…

海思ISP记录七:低照度图像调整

Hi3519av100imx585 记录下低照度图像调整的流程和思路 一、环境与配置 环境:暗房不开灯,只有零散漏光和电脑光亮gain与帧率:根据手册我设置的是Again:31282;Dgain:8192;ISP Dgain:…

B1.1 关于应用程序员模型-概述

快速链接: . 👉👉👉 ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 付费专栏-付费课程 【购买须知】个人博客笔记导读目录(全部) B1.1 关于应用程序员模型–概述 本章节包含了应用程序开发所需的程序员模型信息。 本章节中的信息不同于支持和服务于操作系统下应用程…

1.MySQL面试题之innodb如何解决幻读

1. 写在前面 在数据库系统中,幻读(Phantom Read)是指在一个事务中,两次读取同一范围的数据集时,由于其他事务的插入操作,导致第二次读取结果集发生变化的问题。InnoDB 作为 MySQL 的一个存储引擎&#xff…

PyTorch深度学习实战(2)——PyTorch快速入门

PyTorch的简洁设计使得它易于入门,在深入介绍PyTorch之前,本文先介绍一些PyTorch的基础知识,以便读者能够对PyTorch有一个大致的了解,并能够用PyTorch搭建一个简单的神经网络。 1 Tensor Tensor是PyTorch中最重要的数据结构&#…

docker、k8s部署 mysql group replication 和 ProxySQL 读写分离

MySQL Group Replication(简称MGR)是MySQL官方推出的一个高可用与高扩展的解决方案。MySQL组复制它提供了高可用、高扩展、高可靠的MySQL集群服务,这里部署的 mysql 版本 5.7.33,架构是一读一写。特别要注意一个关键点: 必须保证各…

sqli-labs-php7-master第11-16关

猜注入点 先来猜数字型 单引号字符型: 发现注入点找到了 猜测数据库有多少个字段: 1’ order by 4 # 密码随便输的。 这里没有使用--注释,因为没作用,可能是过滤掉了 继续猜。刚才没猜对 1 order by 2 # 没报错,猜…

如何将neo4j,4.x版本部署到服务器上

一. 简介 当我们使用neo4j构建知识图谱时,我们希望让别人能和我们共用neo4j进行知识图谱的构建,我们的方法之一就是将neo4j部署到我们的服务器上,然后将7474,7687端口暴露出来,这样就可以通过访问服务器公网IP的7474端口来操作我…

电脑硬盘坏了数据可以恢复吗?如何恢复硬盘数据?

电脑硬盘坏了数据可以恢复吗?对于这种问题,还需要具体问题具体分析的,一般是可以恢复。 硬盘损坏可以分为物理损坏和逻辑损坏两种情况: 1.逻辑损坏 这通常是由于软件问题,如文件系统错误、病毒攻击、误删除、格式化等…

CentOS Linux release 7.9.2009 中sudo命令未找到

先在 Windows 环境中下载 sudo 的安装包 选择适合自己 Centos 版本的安装包下载到本地:https://www.sudo.ws/releases/stable/ 然后把安装包拷贝的 Centos (Linux系统)中,cd 进入安装包所在的目录执行下面的命令: 格…

【Unity】线性代数基础:矩阵、矩阵乘法、转置矩阵、逆矩阵、正交矩阵等

文章目录 矩阵(Matrix)矩阵能干啥?矩阵基本运算矩阵加减法矩阵和标量的乘法矩阵和矩阵的乘法矩阵的转置矩阵相等 特殊的矩阵方块矩阵对称矩阵对角元素(Diagonal Elements)对角矩阵(Diagonal Matrix&#xf…

sqli-labs-master初学者题目练习

Less-1 从源码可以看出id为注入点,且为单引号过滤 使用 闭合 --为注释 原本应该用--‘space’,但-与‘连在一起无法起到注释作用 order by为联合查询——同时查询两张表,但两张表列数必须相同 所有从以上两张图可以看出此表格有三列数据 爆…

计算机网络知识汇总(超详细整理)从零基础入门到精通,看完这一篇就够了

文章目录 前言一、计算机网络概述 1 互联网的构成2.网络分类3.接入网4.网络核心的两大功能 ①路由②转发 5.网络分层 ①OSI 7层模型②TCP/IP 4层模型③两种模型比较 二、物理层 1.物理介质 ①引导型介质②非引导型介质 2.数据交换方式 ①分组交换②电路交换 3.信道复用 …

在亚马逊云科技AWS上利用PEFT和RLHF高效微调AI大模型减少有害回复

简介: 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。 本次我将介绍如何用亚马逊云科技的AI模型训练服…

基于K8S部署安装Jenkins

基于K8S部署安装Jenkins 1.Jenkins Kubernetes 清单文件2.Kubernetes Jenkins 部署1:为 Jenkins 创建 Namespace。 最好将所有DevOps工具分类为与其他应用程序分开的命名空间。2:创建“serviceAccount.yaml”文件并复制以下管理员服务帐户清单。1. kubec…