前言 经常有人问:C# 能不能调用 YOLOv8 做物体检测?答案当然是可以。不过市面上的方案大多是基于 ONNX Runtime 或者 OpenVINO,用 NCNN 的倒是少见。 NCNN 是腾讯开源的轻量级推理框架,主打移动端和嵌入式设备,在 PC 上同样表现不错。这套封装的初衷很简单——把 YOLOv8 的推理过程打包成 C# 可直接调用的接口,不用关心张量怎么构造、NMS 怎么实现,几行代码就能跑起来。 项目介绍 Yolov8NcnnCsharp 是一个基于腾讯 NCNN 框架的 YOLOv8 C# 封装库。它把 NCNN 的推理逻辑封装成两个 DLL(Yolov8ChenZhe.dll 和 Yolov8Ncnn.dll),通过一个叫 CZyolov8 的类对外暴露接口。 这套封装的核心价值在于:你不用懂 NCNN 的底层实现,也不用操心图像预处理和后处理的细节,只需要加载模型文件,调用识别方法,就能拿到检测结果。所有推理逻辑都跑在 NCNN 引擎上,支持 CPU 和 GPU 两种推理模式。 项目功能 模型加载:加载 NCNN 框架的 param、bin 和 names 三个文件,支持带密码的加密模型 屏幕实时检测:指定屏幕区域,持续识别画面中的物体,返回位置和类别信息 图片检测:传入图片二进制数据或图片路径,返回检测结果 快速检测模式:只返回是否检测到物体,不输出详细结果,适合做触发判断 GPU 加速:支持 NVIDIA 显卡推理,也可在核显上运行 多线程支持:检测函数本身是单线程的,但可以在后台线程中循环调用实现实时检测 检测耗时统计:每次推理返回毫秒级耗时,方便调优 项目特点 基于腾讯 NCNN 框架,推理效率高 原生 C# 封装,接口简单直观 支持屏幕区域实时检测,适合做自动化工具 支持图片文件或二进制数据输入,灵活适配不同场景 自动管理检测结果的容器,避免重复分配内存 模型加载与推理分离,可运行时切换模型 支持模型加密密码,保护模型版权 开箱即用,两行代码就能完成推理 项目技术 技术项 | 说明 | 开发框架 | .NET 10.0 | 推理引擎 | 腾讯 NCNN | 封装语言 | C# | 模型格式 | NCNN param + bin(可从 ONNX 转换) | 类别配置 | .names 文件,按行对应类别 ID | 推理模式 | CPU / GPU | 目标平台 | x86(32 位) | 输入尺寸 | 640×640(可配置) |
项目代码 下面是这套封装的完整使用示例,从环境配置到调用推理,一步步拆开来看。 第一步:准备环境 项目基于.NET 10.0 SDK,建议使用 32 位环境运行——因为开源的 DLL 是 32 位的。如果你的 C# 环境是 64 位,打包的时候选择 32 位运行即可。 下载安装 .NET SDK 10.0: https://dotnet.microsoft.com/zh-cn/安装完成后在 cmd 里验证: dotnet --version# 显示 10.0.xxx 代表环境配置成功新建一个控制台项目: dotnet new console把两个 DLL 文件复制到项目根目录: 第二步:配置项目文件 修改 project.csproj,引用封装 DLL 并确保 NCNN 原生库能随程序一起发布: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe<!--OutputType--> <TargetFramework>net10.0<!--TargetFramework--> <ImplicitUsings>enable<!--ImplicitUsings--> <Nullable>enable<!--Nullable--><!--PropertyGroup--><ItemGroup> <Reference Include="Yolov8ChenZhe"> <HintPath>Yolov8ChenZhe.dll<!--HintPath--> <!--Reference--><!--ItemGroup--><ItemGroup> <Content Include="Yolov8Ncnn.dll"> <CopyToOutputDirectory>PreserveNewest<!--CopyToOutputDirectory--> <!--Content--><!--ItemGroup--><!--Project-->第三步:加载模型 在代码里引入命名空间并实例化 CZyolov8 对象: using Yolov8ChenZhe;public static CZyolov8 cZyolov8 = new CZyolov8();加载模型需要三个文件: .param:NCNN 的模型结构文件,描述网络结构 .bin:NCNN 的模型权重文件,存储训练好的参数 .names:自定义的类别名文件,按行对应识别 ID .names 文件的格式很简单,按行写即可。比如识别苹果和香蕉: applebanana加载模型的代码: bool IsLoadSuccess = cZyolov8.LoadModelFromFile( paramFile: Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./aaa.param")), binFile: Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./aaa.bin")), namesFile: Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./aaa.names")), cpuThreads: 1, // CPU 线程数,建议填 1 useGpu: true, // 开启 GPU 加速 deviceId: 0, // 显卡设备 ID password: "" // 模型密码,没有就留空);加载成功返回 true,失败返回 false。不推荐多线程同时加载模型,可能会崩溃。 第四步:开始推理 屏幕实时检测 在后台线程循环调用 DetectScreenArea,可以持续检测屏幕指定区域: public static List<yolotarget> targets = new List<yolotarget>();publicstaticstring resultText = "";publicstaticint useTime = 0;Task.Run(() =>{ while (true) { bool IsDetectSuccess = cZyolov8.DetectScreenArea( left: 0, top: 0, width: 1920, height: 1080, targets: out Program.targets, resultText: out Program.resultText, useTime: out Program.useTime, confidence: 0.4d, targetSize: 640 ); if (IsDetectSuccess) { foreach (YoloTarget i in Program.targets) { Console.WriteLine($"对象ID:{i.ObjId}--X:{i.X}--Y:{i.Y}--宽:{i.W}--高:{i.H}--可信度:{i.Prob}--名称:{i.Name}"); } } }});每个 YoloTarget 包含以下字段: 如果只需要判断屏幕上有没有目标物体,可以用快速模式: bool IsDetectSuccess = cZyolov8.DetectScreenAreaFast( left: 0, top: 0, width: 1920, height: 1080, confidence: 0.4d, targetSize: 640);// 返回 true 表示检测到物体,false 表示没有图片检测 传入图片的二进制数据: byte[] imageBytes = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./1.jpg"));bool IsDetectImageSuccess = cZyolov8.DetectImage( imageBytes: imageBytes, targets: out Program.targets, resultText: out Program.resultText, useTime: out Program.useTime, confidence: 0.4d, targetSize: 640);也可以直接传入图片路径: string imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./1.jpg");bool IsDetectImageSuccess = cZyolov8.DetectFile( imageFile: imagePath, targets: out Program.targets, resultText: out Program.resultText, useTime: out Program.useTime, confidence: 0.4d, targetSize: 640);第五步:卸载模型 推理结束后,调用 UnloadModel 释放资源: bool IsUninstallModelSuccess = cZyolov8.UnloadModel();运行与打包 运行(32 位环境): dotnet run打包成单文件: dotnet publish -c Release -r win-x86 --self-contained true -p:PublishSingleFile=true项目效果 在实际使用中,这套封装的表现比较稳定。在 i7-10700 平台上,CPU 推理单帧耗时大概在 10-15ms 左右,开启 GPU 后能压到 8ms 以内。检测精度取决于你用的模型本身——这套封装只是推理工具,不包含模型训练能力,你需要自己准备训练好的 NCNN 格式模型。 DetectScreenArea 接口很适合做桌面自动化工具,比如监控某个应用界面上的特定图标或按钮,检测到后自动触发后续操作。搭配 DetectScreenAreaFast 做快速判断,能进一步降低 CPU 占用。 项目源码 目录结构 ├── Program.cs # 示例代码├── Yolov8ChenZhe.dll # C# 封装 DLL├── Yolov8Ncnn.dll # NCNN 原生库(32 位)└── models/ # 模型示例(守望先锋目标检测) ├── aaa.param ├── aaa.bin └── aaa.names模型准备:如果你手里有 YOLOv8 的 ONNX 模型,可以用 NCNN 提供的 onnx2ncnn 工具转换成 param + bin 格式。具体命令参考 NCNN 官方文档。。 总结 这套封装把 NCNN 推理 YOLOv8 的过程简化到了极致:两个 DLL、一个类、几个方法调用,就能跑起目标检测。不需要懂 NCNN 的底层实现,也不用自己写图像预处理和后处理代码。特别适合两类场景:一是桌面自动化工具需要做视觉识别,二是想快速验证 YOLOv8 在 C# 环境下的运行效果。 当然,这套方案也有局限。目前只提供了 32 位版本,如果需要 64 位需要自己重新编译;模型必须转换成 NCNN 格式,多了一步转换工作;GPU 支持依赖 NVIDIA 显卡,核显虽然也能跑但效率会差一些。不过对于大部分桌面应用场景来说,这些都不是大问题。 如果大家需要在一个 C# 项目里集成 YOLOv8 物体检测能力,又不想折腾 ONNX Runtime 那一套复杂的接口,这个封装值得一试。 关键词 最后 如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长! 作者:小码编匠 出处:gitee.com/smallcore/DotNetCore 声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢! 觉得有收获?不妨分享让更多人受益 关注「DotNet技术匠」,共同提升技术实力
</yolotarget></yolotarget> 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |