搜索
CV -- YOLOv8 图像分割(GPU环境)
于 2025-02-19 23:25:52 发布
收藏 14
点赞数 14
版权
4 篇文章1 订阅
已订阅
目录
参考视频:
标注
数据集:
我使用的是一些苹果数据集,可以在我的csdn资源中下载:
https://download.csdn.net/download/2403_83182682/90405543?spm=1001.2014.3001.5503
这里标注使用的 labelme 标注软件,下载和使用都很简单,下载需要打开 cmd 控制台,输入下载代码:
pip install labelme
labelme
输入 labelme 打开软件页面:
中文版的自己玩玩就会了,常用按钮如下
点击【打开目录】,输入苹果文件夹,点击【创建多边形】,绘制多边形,点击保存,然后继续绘制下一张
标记完成后是这样的
需要将 jpg 文件和 json文件分别放入文件夹中,方便后面数据转换。
JSON转为TXT
通过 LabelMe 工具绘制多边形标注后生成的 JSON 文件是一种结构化的数据文件,它遵循了一定的格式来存储图像标注信息。但是 yolov8 官方规定需要的是标注文件,即 .txt 文件,我这里提供一段 json 转 txt 文件的 Python 代码:
-
# -*- coding: utf-8 -*-
-
from tqdm import tqdm
-
import shutil
-
import random
-
import os
-
import argparse
-
from collections import Counter
-
import yaml
-
import json
-
def mkdir(path):
-
if not os.path.exists(path):
-
os.makedirs(path)
-
def convert_label_json(json_dir, save_dir, classes):
-
json_paths = os.listdir(json_dir)
-
classes = classes.split(',')
-
mkdir(save_dir)
-
for json_path in tqdm(json_paths):
-
# for json_path in json_paths:
-
path = os.path.join(json_dir, json_path)
-
with open(path, 'r') as load_f:
-
json_dict = json.load(load_f)
-
h, w = json_dict['imageHeight'], json_dict['imageWidth']
-
# save txt path
-
txt_path = os.path.join(save_dir, json_path.replace('json', 'txt'))
-
txt_file = open(txt_path, 'w')
-
for shape_dict in json_dict['shapes']:
-
label = shape_dict['label']
-
label_index = classes.index(label)
-
points = shape_dict['points']
-
points_nor_list = []
-
for point in points:
-
points_nor_list.append(point[0] / w)
-
points_nor_list.append(point[1] / h)
-
points_nor_list = list(map(lambda x: str(x), points_nor_list))
-
points_nor_str = ' '.join(points_nor_list)
-
label_str = str(label_index) + ' ' + points_nor_str + '\n'
-
txt_file.writelines(label_str)
-
def get_classes(json_dir):
-
'''
-
统计路径下 JSON 文件里的各类别标签数量
-
'''
-
names = []
-
json_files = [os.path.join(json_dir, f) for f in os.listdir(json_dir) if f.endswith('.json')]
-
for json_path in json_files:
-
with open(json_path, 'r') as f:
-
data = json.load(f)
-
for shape in data['shapes']:
-
name = shape['label']
-
names.append(name)
-
result = Counter(names)
-
return result
-
def main(image_dir, json_dir, txt_dir, save_dir):
-
# 创建文件夹
-
mkdir(save_dir)
-
images_dir = os.path.join(save_dir, 'images')
-
labels_dir = os.path.join(save_dir, 'labels')
-
img_train_path = os.path.join(images_dir, 'train')
-
img_val_path = os.path.join(images_dir, 'val')
-
label_train_path = os.path.join(labels_dir, 'train')
-
label_val_path = os.path.join(labels_dir, 'val')
-
mkdir(images_dir)
-
mkdir(labels_dir)
-
mkdir(img_train_path)
-
mkdir(img_val_path)
-
mkdir(label_train_path)
-
mkdir(label_val_path)
-
# 数据集划分比例,训练集75%,验证集15%,测试集15%,按需修改
-
train_percent = 0.90
-
val_percent = 0.10
-
total_txt = os.listdir(txt_dir)
-
num_txt = len(total_txt)
-
list_all_txt = range(num_txt) # 范围 range(0, num)
-
num_train = int(num_txt * train_percent)
-
num_val = int(num_txt * val_percent)
-
train = random.sample(list_all_txt, num_train)
-
# 在全部数据集中取出train
-
val = [i for i in list_all_txt if not i in train]
-
# 再从val_test取出num_val个元素,val_test剩下的元素就是test
-
# val = random.sample(list_all_txt, num_val)
-
print("训练集数目:{}, 验证集数目:{}".format(len(train), len(val)))
-
for i in list_all_txt:
-
name = total_txt[i][:-4]
-
srcImage = os.path.join(image_dir, name + '.jpg')
-
srcLabel = os.path.join(txt_dir, name + '.txt')
-
if i in train:
-
dst_train_Image = os.path.join(img_train_path, name + '.jpg')
-
dst_train_Label = os.path.join(label_train_path, name + '.txt')
-
shutil.copyfile(srcImage, dst_train_Image)
-
shutil.copyfile(srcLabel, dst_train_Label)
-
elif i in val:
-
dst_val_Image = os.path.join(img_val_path, name + '.jpg')
-
dst_val_Label = os.path.join(label_val_path, name + '.txt')
-
shutil.copyfile(srcImage, dst_val_Image)
-
shutil.copyfile(srcLabel, dst_val_Label)
-
obj_classes = get_classes(json_dir)
-
classes = list(obj_classes.keys())
-
# 编写yaml文件
-
classes_txt = {i: classes[i] for i in range(len(classes))} # 标签类别
-
data = {
-
'path': os.path.join(os.getcwd(), save_dir),
-
'train': "images/train",
-
'val': "images/val",
-
'names': classes_txt,
-
'nc': len(classes)
-
}
-
with open(save_dir + '/segment.yaml', 'w', encoding="utf-8") as file:
-
yaml.dump(data, file, allow_unicode=True)
-
print("标签:", dict(obj_classes))
-
if __name__ == "__main__":
-
"""
-
python json2txt_nomalize.py --json-dir my_datasets/color_rings/jsons --save-dir my_datasets/color_rings/txts --classes "cat,dogs"
-
"""
-
classes_list = 'apple' # 类名
-
parser = argparse.ArgumentParser(description='json convert to txt params')
-
parser.add_argument('--image-dir', type=str, default='D:\OneDrive\桌面\yolov8-segment\datasets\segment\images', help='图片地址')
-
parser.add_argument('--json-dir', type=str, default='D:\OneDrive\桌面\yolov8-segment\datasets\segment\json', help='json地址')
-
parser.add_argument('--txt-dir', type=str, default='D:\OneDrive\桌面\yolov8-segment\datasets\segment\\txt', help='保存txt文件地址')
-
parser.add_argument('--save-dir', default='D:\OneDrive\桌面\yolov8-segment\datasets\segment\seg', type=str, help='保存最终分割好的数据集地址')
-
parser.add_argument('--classes', type=str, default=classes_list, help='classes')
-
args = parser.parse_args()
-
json_dir = args.json_dir
-
txt_dir = args.txt_dir
-
image_dir = args.image_dir
-
save_dir = args.save_dir
-
classes = args.classes
-
# json格式转txt格式
-
convert_label_json(json_dir, txt_dir, classes)
-
# 划分数据集,生成yaml训练文件
-
main(image_dir, json_dir, txt_dir, save_dir)
第 90 行左右可以修改数据集划分比例,默认是 90% 训练集,10%验证集。
第147到150行依次为图片地址、json文件地址、保存txt文件地址、分割好的数据集地址
我的项目创建目录如下(都是可以自己修改的):
运行代码
运行成功,训练集是19张图片,验证集是3张,检测到的标签总数量为 53。
运行成功后会帮您创建 Yolov8 训练所需的文件格式,并且将 txt文件放入正确的位置:
训练
训练环境使用的GPU,需要配置的可以看我前文:
训练代码如下:
-
from torch.cuda import device
-
from ultralytics import YOLO
-
model = YOLO('D:\OneDrive\桌面\yolov8-segment\weights\yolov8n-seg.pt')
-
model.train(data='D:\OneDrive\桌面\yolov8-segment\datasets\segment\seg\segment.yaml',
-
epochs=300, #训练轮次
-
imgsz=640, #输入图片尺寸(会转换为该尺寸)
-
batch=4, #每次训练的批量
-
device='cuda:0', #使用GPU训练
-
workers=0 #windows GPU训练需加上该参数,否则会报错
-
)
-
print("训练结束!")
这里使用的是预训练模型,yolov8n-seg.pt,大家可以在我的资源中获取到:
https://download.csdn.net/download/2403_83182682/90405472?spm=1001.2014.3001.5503
训练结束后会生成一些图表:
输出文件说明:
F1-置信度曲线 (BoxF1_curve.png)
观察方法: F1分数是模型准确度的度量,结合了精确度和召回率。在这个图表中,您应该寻找F1分数最高的点,该点对应的置信度阈值通常是模型最佳的工作点。
精确度-置信度曲线 (BoxP_curve.png)
观察方法: 精确度代表了模型预测为正类的样本中实际为正类的比例。在该曲线中,应关注随置信度增加,精确度如何提高,以及在哪个置信度水平上精确度开始下降,这有助于确定阈值设定。
精确度-召回率曲线 (BoxPR_curve.png)
观察方法: 该曲线展示了精确度与召回率之间的权衡。理想的模型应在高精确度和高召回率处达到平衡。通常查看曲线下面积来评估模型整体性能。
召回率-置信度曲线 (BoxR_curve.png)
观察方法: 召回率是指所有正类中模型正确预测的比例。这个图表中,召回率通常随着置信度阈值的降低而增加。理想的置信度阈值通常是召回率较高,但置信度不过低的点。
混淆矩阵 (confusion_matrix.png)
观察方法: 查看矩阵的对角线,对角线上的数值越高表示分类结果越准确。同时观察非对角线元素,了解哪些类别容易被误分类。
标准化混淆矩阵 (confusion_matrix_normalized.png)
观察方法: 与非标准化混淆矩阵类似,但通过标准化可以更容易地比较不同类别之间的分类准确率,特别是在类别样本量不均匀的情况下。
标签分布 (labels.jpg)
观察方法: 柱状图部分显示了每个类别的实例数量,有助于了解数据集中各类别的分布情况。散点图部分可以显示样本的位置分布,有助于了解样本在输入空间的分布特性。
标签相关图 (labels_correlogram.jpg)
观察方法: 相关图显示了数据标签之间的相关性,深色的格子表示较高的正相关,浅色表示较低的相关或负相关。这有助于了解不同类别之间的关系。
掩膜F1-置信度曲线 (MaskF1_curve.png)
观察方法: 类似于F1-置信度曲线,但特别用于评估模型在像素级分类或分割任务中的性能。寻找曲线中F1得分最高的点来确定最佳的置信度阈值。
精确度-召回率曲线 (Precision-Recall Curve) (MaskPR_curve.png)
如何观察理解: 此图表展示了在不同召回率水平上模型精确度的变化。蓝色的线表示所有类别的平均精确度。曲线下的面积(AUC)越大,模型性能越好。理想状态是曲线靠近右上角,即高召回率和高精确度。
召回率-置信度曲线 (Recall-Confidence Curve) (MaskR_curve.png)
如何观察理解: 该图标展示了模型在不同置信度阈值下召回率的变化。您应关注在召回率保持高的同时,置信度阈值的选择。最佳操作点通常是召回率开始显著下降之前的置信度值。
训练和验证指标图 (results.png)
如何观察理解: 这张图显示了多个指标的训练和验证过程,其中包括损失函数的变化和性能指标如精确度和mAP。下降的损失和上升的性能指标通常表明模型在学习过程中正在改进。平滑的曲线有助于识别趋势。
损失和性能指标图
如何观察理解: 类似于上一个图表,这个可能包含了不同的损失和性能指标。每个小图标展示了训练过程中的具体方面,如框体损失、分割损失、分类损失等。这有助于诊断模型在哪些方面表现良好,在哪些方面可能需要进一步优化。
Weights文件:这是一个模型权重文件,通常以.pt(PyTorch模型)格式保存。它包含了经过训练的神经网络的所有参数和权重。这个文件是模型训练过程的直接产物,用于后续的图像识别和分析任务。
Args.yaml文件:这个文件通常包含了模型训练时使用的配置参数。它详细记录了训练过程中使用的所有设置,如学习率、批大小、训练轮数等。这个文件的目的是为了提供一个清晰的训练配置概览,使得训练过程可以被复现或调整。
左半部分是损失函数图,损失函数下降,可能并不能说明训练结果很好,但如果损失函数上升,那训练结果一定不好,说明你的数据可能出现了很大的错误,或者一些其他不好的事情正在发生。
通过对测试数据的详细分析,我们可以观察到原始标注与模型预测的掩膜之间存在差异很小,这实际上体现了模型具备出色的语义分割能力。具体而言,尽管在某些局部细节上可能存在细微偏差,但模型整体能够准确捕捉并区分不同对象的边界和区域,展示了其在复杂场景下对图像内容的强大理解能力。这种高水平的分割精度不仅验证了模型训练的有效性,还为其在实际应用中的性能提供了有力保障。
验证
可以使用我们训练好的模型,对苹果图片进行图像分割,训练好的模型的权重文件中有两个模型文件,第一个是最好的模型,第二个是最后一次训练的模型,一般使用第一个模型。
训练代码:
-
from ultralytics import YOLO
-
import cv2
-
import numpy as np
-
# 模型路径和图像路径
-
model_path = 'D:/OneDrive/桌面/yolov8-segment/runs/segment/train8/weights/best.pt'
-
image_path = 'D:/OneDrive/桌面/apple2.jpg'
-
# 加载模型并进行预测
-
model = YOLO(model_path,task='segment')
-
results = model.predict(source=image_path,save=True,show=True)
成功运行后就能得到分割图片:
可以看见分割效果是有的,但也有点瑕疵,把杯子也识别成 apple 了,可能是因为数据集太少或者标注问题。
当然,也可使用代码将各个 apple 的掩膜提取出来:
-
from ultralytics import YOLO
-
import cv2
-
import numpy as np
-
# 模型路径和图像路径
-
model_path = 'D:/OneDrive/桌面/yolov8-segment/runs/segment/train8/weights/best.pt'
-
image_path = 'D:/OneDrive/桌面/apple2.jpg'
-
# 加载模型并进行预测
-
model = YOLO(model_path,task='segment')
-
results = model.predict(source=image_path,save=True,show=True)
-
# 读取图像
-
img = cv2.imread(image_path)
-
H, W, _ = img.shape
-
print(img.shape)
-
# # 遍历每个结果中的掩码
-
for i, result in enumerate(results):
-
for j, mask in enumerate(result.masks.data):
-
# 将mask从GPU移动到CPU,并转换为numpy数组
-
mask = mask.cpu().numpy()
-
# 如果mask是多维的,选择第一个通道(假设单通道)
-
if len(mask.shape) > 2:
-
mask = mask[0]
-
# 归一化到0-255范围,并转换为uint8类型
-
mask = (mask * 255).astype(np.uint8)
-
# 调整大小以匹配原图尺寸
-
mask_resized = cv2.resize(mask, (W, H))
-
# 保存掩码图像
-
output_path = f'./mask_{i}_{j}.png'
-
cv2.imwrite(output_path, mask_resized)
-
print(f"Saved {output_path}")
得到各个掩膜的 png 文件:
这些掩膜文件在某些时候非常有用。
感谢您的三连!!!
-
14 -
-
14 -
0 -
专栏目录
YoloV8改进策略:主干网络改进|CAS-ViT在YoloV8中的创新应用与显著性能提升
879
使用 YOLOv8 进行实时物体检测和图像分割(一)更快的 R-CNN
1322
Android ncnn-android-yolov8-seg源码解析 : 实现人像分割
2461
讲解Android ncnn-android-yolov8-seg源码,如何实现人像分割 ?
超详细YOLOv8实例分割全程概述:环境、训练、验证与预测详解
4万+
706
YOLOV8实例分割——详细记录环境配置、自定义数据处理到模型训练与部署
2万+
yolov8实例分割,从数据处理到模型训练与模型部署保姆级教程
1304
1万+
3781
OpenCV与AI深度学习 | CIB-SE-YOLOv8: 优化的YOLOv8, 用于施工现场的安全设备实时检测 !
1166
安全设备是确保建筑施工现场安全的关键组成部分,其中头盔尤为重要,能有效减少伤害和死亡。传统的监督和项目经理手动检查方法效率低下且劳动密集,往往无法预防因缺乏安全设备引发的事故。
1万+
云端炼丹手册-云端训练YOLOv5、YOLOv8、YOLOv8,分割 检测 姿态估计
05-24
X-AnyLabeling的yolov7-onnx自动标注模型
06-08
【camera】YOLOV7实现实例分割+目标检测任务(训练、测试、量化、部署)
03-27
使用 C++ 和 ONNX Runtime 框架对 YOLOv11-CLS 图像分类模型进行部署(包含详细的完整的程序和数据)
10-14
YoloV8改进策略:Block改进|Mamba-UNet改进YoloV8,打造全新的Yolo-Mamba网络
3808
【YOLOv8改进 - 特征融合】FFCA-YOLO: 提升遥感图像中小目标检测的精度和鲁棒性
专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。
1681
手把手教你YOLOv8/YOLOv11分割训练自己数据集和推理,并教你使用Labelme工具标注数据(附分割网络结构图)
1447
340
- 公安备案号11010502030143
- 京ICP备19004658号
- 京网文〔2020〕1039-165号
- 经营性网站备案信息
- 北京互联网违法和不良信息举报中心
- 家长监护
- 网络110报警服务
- 中国互联网举报中心
- Chrome商店下载
- 账号管理规范
- 版权与免责声明
- 版权申诉
- 出版物许可证
- 营业执照
- ©1999-2025北京创新乐知网络技术有限公司
码龄1年编辑 高校学生
12万+
访问
等级
4792
积分
2287
粉丝
3343
获赞
1481
评论
2463
收藏
热门文章
- 【重生之我学Python进阶】----第一章 编辑 12229
- 2024 年 MySQL 8.0.40 安装配置、Workbench汉化教程最简易(保姆级) 编辑 9572
- (长期更新)《零基础入门 ArcGIS(ArcMap) 》实验二----网络分析(超超超详细!!!) 编辑 7699
- (长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!) 编辑 7268
- (长期更新)《零基础入门 ArcGIS(ArcMap) 》实验一(上)----空间数据的编辑与处理(超超超详细!!!) 编辑 7211
最新评论
- CV -- 基于GPU版CUDA环境+Pycharm YOLOv8 目标检测
全栈小5: 非常不错的技术领域文章分享,解决了我在实践中的大问题!博主很有耐心,更有对知识的热忱和热爱,写了这么实用有效的分享,值得收藏点赞。支持【CV -- 基于GPU版显卡CUDA环境 Pycharm YOLOv8 检测,博主这篇文章,值得一看】
- CV -- 基于GPU版CUDA环境+Pycharm YOLOv8 目标检测
云边有个稻草人: 这篇文章非常具有启示性和实用性 ,有空一定根据你的 博文写了内容一步一步的试试,感谢博主的分享,期待博主持续带来更多好文
- 【玩转全栈】----闹钟虐我千百遍?我待 Vue3 如初恋!
忧郁的蛋~: 文章内容丰富,涵盖了很多实用的知识点,对我来说非常有帮助,感谢分享
- 【玩转全栈】----闹钟虐我千百遍?我待 Vue3 如初恋!
唯我独尊哈哈: 主播,主播确实有实力
- 第十届全国大学生GIS应用技能大赛 上午题 讲解 【Arcmap 10.8】
唯我独尊哈哈: 主播,主播,感觉你的文章还是太吃操作了
大家在看
- 学习threejs,THREE.Material材质基类详解 编辑 332
- C++ primer plus 1.2 C++简史
- get_property和report_timing命令 编辑 251
- 34、深度学习-自学之路-深入理解-NLP自然语言处理-RNN一个简单的程序,可以从程序中理解RNN的基本思想。 编辑 219
- Android Studio:切换主线程的两种方式runOnUiThread、Handler.post
最新文章
- CV -- 基于GPU版CUDA环境+Pycharm YOLOv8 目标检测
- 第十届全国大学生GIS应用技能大赛 下午题 讲解 【Arcmap 10.8】
- 第十届全国大学生GIS应用技能大赛 上午题 讲解 【Arcmap 10.8】
相关专栏
用2024年最新的成果改进YoloV8,打造YoloV8改进的精品专栏!
YOLOYOLOV8基础解析+创新改进+实战案例: 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
目录
分类专栏
- 编辑人工智能--CV4篇
- 编辑全栈开发14篇
- 编辑Arcgis10篇
- 编辑python进阶1篇
- 编辑数据结构与算法3篇
AI提问