【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理
【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理
- 项目背景
- 项目实现
- 推理过程
- 训练过程
- 项目展望
- 写在最后
- 项目下载链接
本文为原创文章,若需要转载,请注明出处。
原文地址:https://blog.csdn.net/qq_30270773/article/details/145169580
项目对应的Github地址:https://github.com/IntptrMax/YoloSharp
项目打包的Nuget地址:https://www.nuget.org/packages/IntptrMax.YoloSharp
C#深度学习之路专栏地址:https://blog.csdn.net/qq_30270773/category_12829217.html
关注我的Github,可以获取更多资料,请为你感兴趣的项目送上一颗小星星:https://github.com/IntptrMax
另外本人已经在多平台上发现了不做任何修改直接照抄就发布我的文章的盗版行为,还将我的开源免费资源当成付费资源发布的行为,对此表示强烈的不满。这种“盗窃知识”的行为严重损害了开源项目作者的个人利益以及开源共享精神。
项目背景
本人已经在Github及CSDN上连续发布了Yolov5,Yolov8,Yolov11模型的Predict方法的训练及推理的源码及实现方法介绍,这些项目成功实现了Yolo模型在C#平台上的训练,并且已经在Nuget中进行了打包。项目发布后一些小伙伴在问是否可以实现Segment方法,故进行了进一步的开发,本文就是对Segment的实现。
如果该资料对你有帮助,请在我的Github上送我一颗小星星。该项目的Github链接为https://github.com/IntptrMax/YoloSharp
项目实现
对于单独的Yolov5、Yolov8、Yolov11 Predict方法的实现原理及代码,请参考C#深度学习之路专栏内的相关文章。
Segment方法是在Predict方法上进行了进一步的开发。在Yolo模型上,仅为Segment层代替Predict层,而且Segment是继承自Predict的,加入了cv4这个模块,对Mask的计算。
详细代码如下:
推理过程
public class Segment : YolovDetect
{private readonly int nm;private readonly int npr;private readonly Proto proto;private readonly int c4;private readonly ModuleList<Sequential> cv4 = new ModuleList<Sequential>();public Segment(int[] ch, int nc = 80, int nm = 32, int npr = 256, bool legacy = false) : base(nc, ch, legacy){this.nm = nm; // number of masksthis.npr = npr; // number of protosthis.proto = new Proto(ch[0], this.npr, this.nm); // protosc4 = Math.Max(ch[0] / 4, this.nm);foreach (int x in ch){cv4.append(Sequential(new Conv(x, c4, 3), new Conv(c4, c4, 3), nn.Conv2d(c4, this.nm, 1)));}//RegisterComponents();}public override Tensor[] forward(Tensor[] x){Tensor p = this.proto.forward(x[0]); // mask protoslong bs = p.shape[0]; //batch sizevar mc = torch.cat(this.cv4.Select((module, i) => module.forward(x[i]).view(bs, this.nm, -1)).ToArray(), dim: 2); // mask coefficients x = base.forward(x);x = base.forward(x);if (this.training){x = (x.Append(mc).Append(p)).ToArray();return x;}else{return [torch.cat([x[0], mc], dim: 1), x[1], x[2], x[3], p];}}
}
经过Segment层的计算,得到了与Predict后相同的输出,并且额外得到了一组与Predict对应,且形状为[160,160]的Mask张量。这组张量里保存Mask的信息,按尺寸和比例进行缩放,即为原始图像中对应的分割区域。
训练过程
Segment下的训练与Predict方法下的训练相似,不过需要对Mask进行额外处理。
这里有一个精巧的构思,为了在一个Mask(形状为[160,160])里容纳所有Label对应的掩码,在有Mask的区域使用label的index+1的值表示。其余0的区域表示没有Mask。处理图像本体、label、mask的具体代码如下:
public (Tensor, Tensor, Tensor) GetLetterBoxSegmentData(long index)
{using var _ = NewDisposeScope();int maskSize = 160;Tensor orgImageTensor = torchvision.io.read_image(imageFiles[(int)index], torchvision.io.ImageReadMode.RGB);int originalWidth = (int)orgImageTensor.shape[2];int originalHeight = (int)orgImageTensor.shape[1];float scale = Math.Min((float)imageSize / originalWidth, (float)imageSize / originalHeight);int padWidth = imageSize - (int)(scale * originalWidth);int padHeight = imageSize - (int)(scale * originalHeight);float maskWidthScale = scale * originalWidth / imageSize;float maskHeightScale = scale * originalHeight / imageSize;Tensor imgTensor = torchvision.transforms.functional.resize(orgImageTensor, (int)(originalHeight * scale), (int)(originalWidth * scale));imgTensor = torch.nn.functional.pad(imgTensor, [0, padWidth, 0, padHeight], PaddingModes.Zeros);Tensor outputImg = torch.zeros([3, imageSize, imageSize]);outputImg[TensorIndex.Colon, ..(int)imgTensor.shape[1], ..(int)imgTensor.shape[2]] = imgTensor;string labelName = GetLabelFileNameFromImageName(imageFiles[(int)index]);string[] lines = File.ReadAllLines(labelName);float[,] labelArray = new float[lines.Length, 5];Tensor mask = torch.zeros([maskSize, maskSize]);for (int i = 0; i < lines.Length; i++){string[] datas = lines[i].Split(' ');labelArray[i, 0] = float.Parse(datas[0]);List<PointF> points = new List<PointF>();for (int j = 1; j < datas.Length; j = j + 2){points.Add(new PointF(float.Parse(datas[j]) * scale * originalWidth * maskSize / imageSize, float.Parse(datas[j + 1]) * scale * originalHeight * maskSize / imageSize));}float maxX = points.Max(p => p.X) / maskSize;float maxY = points.Max(p => p.Y) / maskSize;float minX = points.Min(p => p.X) / maskSize;float minY = points.Min(p => p.Y) / maskSize;float width = maxX - minX;float height = maxY - minY;labelArray[i, 1] = minX + width / 2;labelArray[i, 2] = minY + height / 2;labelArray[i, 3] = width;labelArray[i, 4] = height;Bitmap bitmap = new Bitmap(maskSize, maskSize);Brush brush = new SolidBrush(Color.White);Graphics g = Graphics.FromImage(bitmap);g.FillClosedCurve(brush, points.ToArray());g.Save();Tensor msk = Lib.GetTensorFromBitmap(bitmap);msk = msk[0] > 0;mask[msk] = i + 1;}Tensor labelTensor = tensor(labelArray);long p = imgTensor.shape[0];return (imgTensor.MoveToOuterDisposeScope(), labelTensor.MoveToOuterDisposeScope(), mask.MoveToOuterDisposeScope());
}
另外Loss的计算也加入了Mask部分,此处不再仔细讲解。
项目效果如下
项目展望
目前已经实现了Yolov8、Yolov11 Segment方法的训练和推理,并且已经可以成功加载官方的预训练模型进行,或作为训练的基础权重。
接下来还有Pose和Obb方法,过段时间估计会有新的进展。
写在最后
使用C#深度学习项目是很多人所希望的。不过在该方向上资料很少,开发难度大。常规使用C#进行深度学习项目的方法为使用Python训练,转为Onnx模型再用C#调用。
目前我希望能够改变这一现象,希望能用纯C#平台进行训练和推理。这条路还很长,也很困难,希望有兴趣的读者能跟我一起让让C#的深度学习开发环境更为完善,以此能帮助到更多的人。
另外随着项目的关注度增多,已经开始有人盗版我的项目并将免费开源的项目当成付费项目在卖了。这种行为极其恶劣,请各位小伙伴积极抵制这种行为,还开源项目一片干净的环境,也让开源项目开发者有动力继续贡献更多的项目。
我在Github上已经将完整的代码发布了,项目地址为:https://github.com/IntptrMax/YoloSharp,期待你能在Github上送我一颗小星星。在我的Github里还GGMLSharp这个项目,这个项目也是C#平台下深度学习的开发包,希望能得到你的支持。
项目下载链接
https://download.csdn.net/download/qq_30270773/89969923
相关文章:

【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理
【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理 项目背景项目实现推理过程训练过程 项目展望写在最后项目下载链接 本文为原创文章,若需要转载,请注明出处。 原文地址:https://blog.csdn.net/qq_30270773/article…...

Oracle 分区索引简介
目录 一. 什么是分区索引二. 分区索引的种类2.1 局部分区索引(Local Partitioned Index)2.2 全局分区索引(Global Partitioned Index) 三. 分区索引的创建四. 分区索引查看4.1 USER_IND_COLUMNS 表4.2 USER_INDEXES 表 五. 分区索…...

【科技赋能未来】NDT2025第三届新能源数字科技大会全面启动!
随着我国碳达峰目标、碳中和目标的提出,以及经济社会的发展进步,以风电、光伏发电为代表的新能源行业迎来巨大发展机遇,成为未来绿色经济发展的主要趋势和方向。 此外,数字化技术的不断发展和创新,其在新能源领域的应…...

Broker收到消息之后如何存储
1.前言 此文章是在儒猿课程中的学习笔记,感兴趣的想看原来的课程可以去咨询儒猿课堂《从0开始带你成为RocketMQ高手》,我本人觉得这个作者还是不错,都是从场景来进行分析,感觉还是挺适合我这种小白的。这块主要都是我自己的学习笔…...

Mysql--实战篇--SQL优化(查询优化器,常用的SQL优化方法,执行计划EXPLAIN,Mysql性能调优,慢日志开启和分析等)
一、查询优化 1、查询优化器 (Query Optimizer) MySQL查询优化器(Query Optimizer)是MySQL数据库管理系统中的一个关键组件,负责分析和选择最有效的执行计划来执行SQL查询。查询优化器的目标是尽可能减少查询的执行时间和资源消耗ÿ…...

BERT与CNN结合实现糖尿病相关医学问题多分类模型
完整源码项目包获取→点击文章末尾名片! 使用HuggingFace开发的Transformers库,使用BERT模型实现中文文本分类(二分类或多分类) 首先直接利用transformer.models.bert.BertForSequenceClassification()实现文本分类 然后手动实现B…...

rabbitmqp安装延迟队列
在RabbitMQ中,延迟队列是一种特殊的队列类型。当消息被发送到此类队列后,不会立即投递给消费者,而是会等待预设的一段时间,待延迟期满后才进行投递。这种队列在多种场景下都极具价值,比如可用于处理需要在特定时间触发…...

深入探讨DICOM医学影像中的MPPS服务及其具体实现
深入探讨DICOM医学影像中的MPPS服务及其具体实现 1. 引言 在医疗影像的管理和传输过程中,DICOM(数字影像和通信医学)标准发挥着至关重要的作用。除了DICOM影像的存储和传输(如影像存储SCP和影像传输SCP),…...
集合帖:区间问题
一、AcWing 803:区间合并 (1)题目来源:https://www.acwing.com/problem/content/805/ (2)算法代码:https://blog.csdn.net/hnjzsyjyj/article/details/145067059 #include <bits/stdc.h>…...

C#,入门教程(27)——应用程序(Application)的基础知识
上一篇: C#,入门教程(26)——数据的基本概念与使用方法https://blog.csdn.net/beijinghorn/article/details/124952589 一、什么是应用程序 Application? 应用程序是编程的结果。一般把代码经过编译(等)过程&#…...

迅翼SwiftWing | ROS 固定翼开源仿真平台正式发布!
经过前期内测调试,ROS固定翼开源仿真平台今日正式上线!现平台除适配PX4ROS环境外,也已实现APROS环境下的单机飞行控制仿真适配。欢迎大家通过文末链接查看项目地址以及具体使用手册。 1 平台简介 ROS固定翼仿真平台旨在实现固定翼无人机决策…...
CSS 样式 box-sizing: border-box; 详细解读
box-sizing是 CSS 中的一个属性,用于控制元素的盒模型计算方式。border-box值表示元素的宽度和高度将包括内边距(padding)和边框(border),而不仅仅是内容的宽度和高度。这意味着当你为元素设置宽度和高度时…...
FLASK创建下载
html用a标签 <!-- Button to download the image --> <a href"{{ url_for(download_file, filenameimage.png) }}"><button>Download Image</button> </a> 后端:url_for双大括号即是用来插入变量到模板中的语法。也就是绑…...

漫话架构师|什么是系统架构设计师(开篇)
~犬📰余~ “我欲贱而贵,愚而智,贫而富,可乎? 曰:其唯学乎” 关注犬余,共同进步 技术从此不孤单...

Web Socket
Web Socket WebSocket是一种基于TCP的网络通信协议,允许客户端和服务器之间建立全双工(双向)通信通道。WebSocket通过HTTP协议进行握手,建立连接后,客户端和服务器可以在同一个连接上同时发送和接收数据࿰…...

JavaSE学习心得(反射篇)
反射 前言 获取class对象的三种方式 利用反射获取构造方法 利用反射获取成员变量 利用反射获取成员方法 练习 保存信息 跟配置文件结合动态创建 前言 接上期文章:JavaSE学习心得(多线程与网络编程篇) 教程链接:黑马…...

使用FRP进行内网穿透
一、基本概念 内网穿透:它是一种网络技术或方法,旨在允许外部网络(如互联网)访问位于内部网络(内网)中的设备或服务。由于内部网络通常处于NAT(网络地址转换)、防火墙或其他安全机制…...
长安“战疫”网络安全公益赛的一些随想
起因 今年刚进入大学,开始带校队,为了培养校队新成员,也就一直计划着和当地的一些高校合作交流,但是由于种种原因一直被搁置下来。正巧学校信息中心和四叶草有一个培训项目的合作,学校的网安协会也算是沾了光成为了培…...
flutter 安卓端打包
在 Flutter 中打包 Android 应用程序是一个相对简单的过程。你可以使用 Flutter 的命令行工具来构建并打包你的 APK 或 AAB(Android App Bundle)。以下是打包 Flutter Android 应用的步骤: 1. 安装 Flutter 环境 确保你已经安装了 Flutter …...
Cesium中的CustomDataSource 详解
Cesium CustomDataSource 详解 在 Cesium 中,CustomDataSource 是一个强大的类,用于处理自定义的地理数据。它提供了一种方法,可以通过程序方式添加、管理和更新动态的地理实体,而无需依赖外部数据格式(如 GeoJSON 或…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...