能否通过C#向YOLO(Darknet)发送图片并获取目标物体的位置与类型?
完全可以通过C#实现和YOLO(Darknet)的交互,完成图片检测并获取物体类型与位置信息!下面我会给你详细讲清楚实现方案、预期结果和代码示例:
预期检测结果格式
检测后你会得到类似这样的结构化数据,用表格展示更清晰:
| 类型 | X坐标 | Y坐标 | 宽度 | 高度 |
|---|---|---|---|---|
| bicycle | 214 | 150 | 450 | 378 |
| dog | 150 | 260 | 210 | 350 |
| truck | 540 | 100 | 250 | 150 |
对应的可视化检测效果如下:
C#实现方案与代码示例
这里提供两种主流实现思路,先给你展示最易上手的命令行调用方式,再简要说明高性能的C API调用方式:
1. 命令行调用方式(快速实现)
这种方式通过调用Darknet的命令行工具来处理图片,然后解析输出结果,适合快速验证需求:
首先定义存储检测结果的实体类,以及核心的检测器类:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Diagnostics; using System.Linq; public class ObjectPosition { public string Type { get; set; } public int X { get; set; } public int Y { get; set; } public int Width { get; set; } public int Height { get; set; } } public class YoloDetector { private readonly string _darknetExecutablePath; private readonly string _yoloConfigPath; private readonly string _yoloWeightsPath; private readonly string _dataConfigPath; // 构造函数初始化Darknet相关文件路径 public YoloDetector(string darknetExePath, string configPath, string weightsPath, string dataPath) { _darknetExecutablePath = darknetExePath; _yoloConfigPath = configPath; _yoloWeightsPath = weightsPath; _dataConfigPath = dataPath; } public ObjectPosition[] GetObjects(Image image) { // 步骤1:将输入图片保存为临时文件(Darknet命令行需要读取本地文件) string tempImagePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.jpg"); image.Save(tempImagePath, ImageFormat.Jpeg); // 步骤2:构建Darknet检测命令 string commandArgs = $"detect {_dataConfigPath} {_yoloConfigPath} {_yoloWeightsPath} {tempImagePath} -dont_show"; var processStartInfo = new ProcessStartInfo { FileName = _darknetExecutablePath, Arguments = commandArgs, RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = Path.GetDirectoryName(_darknetExecutablePath) // 设置工作目录为Darknet所在文件夹 }; // 步骤3:执行命令并解析输出结果 var detectionResults = new List<ObjectPosition>(); using (var darknetProcess = Process.Start(processStartInfo)) { while (!darknetProcess.StandardOutput.EndOfStream) { string outputLine = darknetProcess.StandardOutput.ReadLine(); // 筛选包含检测结果的行(格式示例:bicycle: 99% (214, 150) -> (664, 528)) if (!string.IsNullOrEmpty(outputLine) && outputLine.Contains("%")) { var lineParts = outputLine.Split(new[] { ": ", " (", ") -> (" }, StringSplitOptions.RemoveEmptyEntries); if (lineParts.Length >= 4) { string objectType = lineParts[0]; var topLeftCoords = lineParts[2].Split(',').Select(int.Parse).ToArray(); var bottomRightCoords = lineParts[3].Split(new[] { ',', ')' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); detectionResults.Add(new ObjectPosition { Type = objectType, X = topLeftCoords[0], Y = topLeftCoords[1], Width = bottomRightCoords[0] - topLeftCoords[0], Height = bottomRightCoords[1] - topLeftCoords[1] }); } } } darknetProcess.WaitForExit(); } // 步骤4:清理临时文件 File.Delete(tempImagePath); return detectionResults.ToArray(); } }
2. C API调用方式(高性能)
如果你的场景对性能要求很高,可以通过P/Invoke直接调用Darknet的C语言API,避免命令行的进程开销。这种方式需要你熟悉C#的指针操作和内存管理,核心思路是:
- 导入Darknet的DLL函数(如
load_network、detect_image等) - 将C#的Image对象转换为Darknet可识别的图像格式
- 调用检测函数并解析返回的检测结果
不过这种实现相对复杂,适合有一定C++和P/Invoke经验的开发者。
注意事项
- 你需要先下载Darknet的预编译版本(或者自行编译),并准备好YOLO的权重文件(如
yolov3.weights)、配置文件(yolov3.cfg)和数据集配置文件(coco.data) - Windows环境下需要确保Darknet依赖的OpenCV DLL文件存在于程序运行目录中
- 如果使用
System.Drawing,注意在.NET Core/.NET 5+环境下需要安装System.Drawing.CommonNuGet包
内容的提问来源于stack exchange,提问作者Tom Baires
相关产品推荐
相关产品推荐

