-
点按钮 加载模型;
-
点按钮 选图 → 检测 → 画框 → 把结果直接显示在主窗体的 PictureBox 里;
-
类别只有"1"、"2"两个;4. 全程用 System.Drawing + SixLabors.ImageSharp 混合绘图,已解决所有命名冲突。
【功能拆解】
模块 | 作用 |
---|---|
字段 | yolov8 (可空引用) + mylabel = {"1","2"} |
button2_Click | 手动加载模型;路径取 best1.onnx (与 exe 同目录)。 |
button1_Click | 打开图片:弹出 OpenFileDialog ,把文件路径交给 showimg 。 |
ToImageSharp | 把 System.Drawing.Image → ImageSharp.Image<Rgb24> 。 |
showimg | 核心流程 |
资源清理 | Dispose 旧图,避免句柄泄漏。 |
安装的NuGet 包:

完整代码:
cs
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using Yolov8Net;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace NetOnnx08
{
public partial class Form1 : Form
{
public IPredictor yolov8;
string[] mylabel = { "1", "2" };//模型分类标签
public Form1()
{
InitializeComponent();
}
//public void Form1_Load(object sender, EventArgs e)
//{
// //加载模型
// try
// {
// yolov8 = YoloV8Predictor.Create("best1.onnx", mylabel);
// if (yolov8 != null)
// {
// toolStripStatusLabel1.Text = ("模型加载成功\r\n");
// }
// }
// catch (System.Exception ex)
// {
// MessageBox.Show(ex.Message);
// }
//}
public void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
//dialog.Multiselect = true;//该值确定是否可以选择多个文件
dialog.Title = "请选择文件";
dialog.Filter = "图像文件(*.jpg;*.jpeg)|*.jpg;*.jpeg";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string file = dialog.FileName;
toolStripStatusLabel1.Text = file;
toolStripStatusLabel2.Text = "检测成功!";
showimg(dialog);
}
}
public static SixLabors.ImageSharp.Image<SixLabors.ImageSharp.PixelFormats.Rgb24>
ToImageSharp(System.Drawing.Image source)
{
if (source == null) throw new ArgumentNullException(nameof(source));
using var ms = new MemoryStream();
source.Save(ms, ImageFormat.Png);
ms.Position = 0;
return SixLabors.ImageSharp.Image.Load<SixLabors.ImageSharp.PixelFormats.Rgb24>(ms);
}
public void showimg(OpenFileDialog dialog)
{
string imgpath = dialog.FileName;
Image image = System.Drawing.Image.FromFile(imgpath);
Form form = new Form();
form.Text = dialog.SafeFileName + " " + image.Width + "x" + image.Height;
PictureBox pictureBox = new PictureBox();
pictureBox.Parent = form;
//格式转换
SixLabors.ImageSharp.Image img = ToImageSharp(image);
//图像预测
var predictions = yolov8.Predict(img);
// Draw your boxes
//using var graphics = Graphics.FromImage(image);
foreach (var pred in predictions)
{
var originalImageHeight = image.Height;
var originalImageWidth = image.Width;
var x = Math.Max(pred.Rectangle.X, 0);
var y = Math.Max(pred.Rectangle.Y, 0);
var width = Math.Min(originalImageWidth - x, pred.Rectangle.Width);
var height = Math.Min(originalImageHeight - y, pred.Rectangle.Height);
////////////////////////////////////////////////////////////////////////////////////////////
// *** Note that the output is already scaled to the original image height and width. ***
////////////////////////////////////////////////////////////////////////////////////////////
// Bounding Box Text
string text = $"{pred.Label.Name} [{pred.Score}]";
using (Graphics graphics = Graphics.FromImage(image))
{
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Define Text Options
Font drawFont = new Font("consolas", 11, FontStyle.Regular);
SizeF size = graphics.MeasureString(text, drawFont);
SolidBrush fontBrush = new SolidBrush(Color.Black);
Point atPoint = new Point((int)x, (int)y - (int)size.Height - 1);
// Define BoundingBox options
Pen pen = new Pen(Color.Yellow, 2.0f);
SolidBrush colorBrush = new SolidBrush(Color.Yellow);
// Draw text on image
graphics.FillRectangle(colorBrush, (int)x, (int)(y - size.Height - 1), (int)size.Width, (int)size.Height);
graphics.DrawString(text, drawFont, fontBrush, atPoint);
// Draw bounding box on image
graphics.DrawRectangle(pen, x, y, width, height);
}
}
////用pictureBox弹窗来显示
//pictureBox.Width = image.Width;
//pictureBox.Height = image.Height;
//pictureBox.Image = (Bitmap)image.Clone();
//form.AutoSize = true;
//form.Show();
//image.Dispose();
// 1. 清空旧图
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
pictureBox1.Image = null;
}
// 3. 直接赋给 PictureBox
//pictureBox1.Image = new System.Drawing.Bitmap(ms);
pictureBox1.Image = (Bitmap)image.Clone();
// 4. 自适应/原图大小任选其一
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; // 自适应
// pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; // 原图大小
}
public void button2_Click(object sender, EventArgs e)
{
try
{
string modelPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "best1.onnx");
if (!File.Exists(modelPath))
{
MessageBox.Show($"模型文件不存在:{modelPath}");
return;
}
// 25 个类别示例
string[] labels = { "1", "2"};
yolov8 = YoloV8Predictor.Create(modelPath, labels);
if (yolov8 != null)
{
toolStripStatusLabel2.Text = "模型加载成功";
}
}
catch (Exception ex)
{
MessageBox.Show("模型加载失败: " + ex.Message);
}
}
}
}
【优点】
-
不弹额外窗口,所有结果在主界面实时可见。
-
已显式区分
System.Drawing.Image
与SixLabors.ImageSharp.Image
,彻底消除"不明确的引用"。 -
支持任意 jpg/jpeg/bmp 图片。
【可改进的小提示】
-
把
pictureBox1.Image
的创建/释放封装成方法,减少重复代码。 -
如果类别多,可把
string[] labels
改成读取外部 txt,避免硬编码。 -
若图片非常大,可把
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize
并放在Panel.AutoScroll
里实现滚动查看。