目录前言项目介绍项目功能项目特点项目技术项目代码项目效果项目源码总结前言平时做桌面应用时偶尔会遇到需要处理图像或者视频流的需求比如做一个简单的安防监控工具、人流统计的小程序或者给某个管理系统加一个摄像头拍照功能。YOLOv8 是目前比较主流的目标检测模型用它来识别人像效果不错而且 ONNX 格式可以跨平台部署。本文分享一个用WinForms 做的人像检测小工具集成了图片检测和摄像头实时检测两种模式。整套代码量不大但把界面交互、模型推理、摄像头采集这几块串了起来适合拿来作为桌面端 AI 应用的起点。项目介绍项目是一个最小可运行的 WinForms 桌面程序核心功能是利用 YOLOv8 模型ONNX Runtime 推理从图片或摄像头视频流中识别人像并在画面中把检测结果框出来。项目整体结构比较清晰界面交互放在 Form 里模型推理封装在 YoloV8Predictor 类中摄像头采集部分单独抽离成了 CameraCaptureService。默认模型文件放在models/yolov8n.onnx当然程序启动后也可以手动指定其他 ONNX 模型。项目功能静态图片检测选择本地图片一键运行人像检测返回带检测框的标注图摄像头视频流检测扫描本机可用摄像头开启后持续从视频流中识别人像模型加载支持通过界面浏览选择任意 YOLOv8 导出的 ONNX 模型文件实时状态反馈每次检测会显示识别到的人像数量、推理耗时等信息自适应界面控制运行过程中自动禁用无关操作按钮避免用户误操作摄像头热插拔兼容支持刷新摄像头列表方便外接摄像头即插即用帧丢弃机制视频流模式下推理忙时自动丢弃中间帧只处理最新画面减少卡顿检测结果可视化在原始画面基础上绘制矩形框和置信度标签直观展示识别结果项目特点采用 ONNX Runtime 推理不需要安装深度学习框架模型和图片均通过文件对话框选择操作路径灵活图片推理和摄像头推理共用同一套检测逻辑代码复用率高摄像头采集服务基于 AForge.NET兼容主流 USB 摄像头界面使用 WinForms 原生控件轻量简洁没有额外 UI 库依赖异步任务处理耗时操作界面不会卡死预设了 COCO 数据集中 person 类别的索引0直接使用无需额外配置推荐的 YOLOv8 模型导出参数imgsz640, opset12写在说明里方便复现项目技术技术项说明开发框架.NET 6 / .NET Framework 4.8 以上界面技术Windows Forms (WinForms)推理引擎ONNX Runtime (Microsoft.ML.OnnxRuntime)图像处理System.Drawing.Common摄像头采集AForge.Video / AForge.Video.DirectShow目标检测模型YOLOv8 (导出为 ONNX 格式)数据集COCO (只使用 person 类别)编程语言C#异步模型async / await Task图像格式Bitmap 与 byte[] 互转项目代码YoloV8Predictor 类负责 ONNX 模型的加载和推理。输入是一张 Bitmap 图片输出是 DetectionResult 列表每个结果包含边界框和置信度。内部做了图像缩放、归一化、张量构造、后处理 NMS 等步骤。对外只暴露一个 DetectPersons 方法调用方不需要关心 ONNX 的细节。private PreparedInput PrepareInput(Bitmap originalImage) { var scale Math.Min(_inputWidth / (float)originalImage.Width, _inputHeight / (float)originalImage.Height); var resizedWidth (int)Math.Round(originalImage.Width * scale); var resizedHeight (int)Math.Round(originalImage.Height * scale); var padX (_inputWidth - resizedWidth) / 2f; var padY (_inputHeight - resizedHeight) / 2f; usingvar canvas new Bitmap(_inputWidth, _inputHeight, PixelFormat.Format24bppRgb); using (var graphics Graphics.FromImage(canvas)) { graphics.Clear(Color.FromArgb(114, 114, 114)); graphics.InterpolationMode System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.DrawImage(originalImage, padX, padY, resizedWidth, resizedHeight); } var pixels newbyte[_inputWidth * _inputHeight * 3]; var bitmapData canvas.LockBits( new Rectangle(0, 0, canvas.Width, canvas.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); try { for (var y 0; y _inputHeight; y) { var rowPtr bitmapData.Scan0 (y * bitmapData.Stride); Marshal.Copy(rowPtr, pixels, y * _inputWidth * 3, _inputWidth * 3); } } finally { canvas.UnlockBits(bitmapData); } var tensorData newfloat[_inputWidth * _inputHeight * 3]; var channelLength _inputWidth * _inputHeight; for (var y 0; y _inputHeight; y) { for (var x 0; x _inputWidth; x) { var pixelIndex ((y * _inputWidth) x) * 3; var tensorIndex (y * _inputWidth) x; var b pixels[pixelIndex] / 255f; var g pixels[pixelIndex 1] / 255f; var r pixels[pixelIndex 2] / 255f; tensorData[tensorIndex] r; tensorData[channelLength tensorIndex] g; tensorData[(channelLength * 2) tensorIndex] b; } } var tensor new DenseTensorfloat(tensorData, [1, 3, _inputHeight, _inputWidth]); returnnew PreparedInput(tensor, scale, padX, padY); }CameraCaptureService 类封装了摄像头的打开、帧获取和停止操作。通过事件FrameReady把每一帧图像推送给订阅者。这里有个小细节每一帧都是独立的 Bitmap订阅方用完需要自己释放否则内存会涨上去。private async Task CaptureLoopAsync(VideoCapture capture, CancellationToken cancellationToken) { usingvar frame new Mat(); try { while (!cancellationToken.IsCancellationRequested) { if (!capture.Read(frame) || frame.Empty()) { await Task.Delay(15, cancellationToken); continue; } var bitmap BitmapConverter.ToBitmap(frame); try { FrameReady?.Invoke(this, new CameraFrameEventArgs(bitmap)); } catch { bitmap.Dispose(); throw; } await Task.Delay(1, cancellationToken); } } catch (OperationCanceledException) { } catch (Exception) when (cancellationToken.IsCancellationRequested) { } }静态图片检测的流程更简单一些用户选择图片后_sourceImage保存原始图点击推理按钮后异步执行DetectPersons然后把结果绘制到新的 Bitmap 上替换预览控件。界面控制方面UpdateControlStates方法统一管理所有按钮和输入框的启用状态根据当前是否在运行推理或摄像头来决定哪些操作可用。这样做的好处是状态集中管理不容易出现界面混乱。项目效果程序跑起来之后主界面分成上下两个区域。上面是参数配置区可以选模型、选图片、选摄像头中间是预览区展示原始图片或者摄像头画面人像检测框用绿色矩形标出来左上角会显示person 85%这样的置信度标签。静态图片模式下加载一张多人合影点一下图片推理一两秒内就能看到所有人物被框出来状态栏会显示具体识别到的人数和耗时。摄像头模式下打开后预览区实时更新每帧的推理结果会覆盖显示响应速度基本能做到实时具体帧率取决于电脑配置和模型大小。模型文件我用的是 Ultralytics 官方导出的 yolov8n.onnx参数量小CPU 上就能跑得动。如果换成 yolov8m 或 yolov8l精度会更高但推理耗时也会相应增加这个可以根据实际场景取舍。项目源码项目的目录结构如下├── xxxx.csproj ├── Form1.cs # 主界面逻辑 ├── Form1.Designer.cs ├── YoloV8Predictor.cs # 模型推理封装 ├── CameraCaptureService.cs # 摄像头采集 ├── models/ │ └── yolov8n.onnx # 默认模型需自行下载 └── .dotnet-home/ # 本地 dotnet 环境可选运行前需要做两件事1、下载 YOLOv8 ONNX 模型。可以用官方命令导出yolo export modelyolov8n.pt formatonnx imgsz640 opset12然后把生成的 yolov8n.onnx 放到 models 目录下。2、还原 NuGet 包项目引用了 ONNX Runtime 和 AForge 相关库。启动命令dotnet restore .\xxx\xxxxWinForms.csproj dotnet run --project .\xxxWinForms\xxxWinForms.csproj如果不想装全局 dotnet也可以用项目里带的本地环境方式按开头说明设置DOTNET_CLI_HOME即可。总结这个项目把 YOLOv8 模型从 Python 环境搬到了 C# 桌面端整个流程走下来最大的感受是 ONNX Runtime 让跨语言部署变得很顺畅。WinForms 虽然是个老面孔但配合异步编程处理视频流这种实时任务也完全够用。如果大家需要做一个桌面端的人像检测或目标检测工具可以直接拿这份代码改一改。比如把 person 改成其他 COCO 类别或者把检测结果输出成日志、触发报警等等扩展起来都比较方便。当然这个项目也有不少可以优化的地方比如目前只检测 person 一个类别如果想检测多种目标需要调整逻辑摄像头采集依赖 AForge这个库已经好几年没更新了在一些新摄像头上的兼容性可能不够好可以换成 MediaCapture 或者 OpenCVSharp 的方案。感兴趣的朋友可以自己折腾了。引入地址
企业数字化 ERP 产品动态
相关推荐
Ajenti Core Push 推送服务解析:基于 Socket.IO 的实时消息广播架构 后端运维 【免费下载链接】ajenti Ajenti Core and stock plugins 项目地址: https://gitcode.com/gh_mirrors/aj/ajenti 点击查看 免费下载 Ajenti 的 aj.plugins.core.api.push 模块提供了一个向浏览器客户端推送实时消息的服务,是任务进度、系统事件… · 2026/9/27 7:13:45
mini-SWE-agent 的 Bubblewrap 环境:无特权沙箱下的轻量级命令执行与隔离配置详解 人工智能大模型AI Agent代码智能体 【免费下载链接】mini-swe-agent The 100 line AI agent that solves GitHub issues or helps you in your command line. Radically simple, no huge configs, no giant monorepo—but scores >74% on SWE-bench verified! 项目地址&… · 2026/9/27 7:13:39
做网站怎么穿插元素避坑指南:5个方案实测 做网站怎么穿插元素避坑指南:5个方案实测 很多老板找我们做站,第一句话往往是:“域名买好了,服务器选了个最便宜的,结果网站打开像蜗牛,还老掉线。”这就是典型的 域名服务器搞不懂… · 2026/9/27 7:13:33
5步搞定html5网站检测,从零搭建避开90%的坑 5步搞定html5网站检测,从零搭建避开90%的坑 网站做好了没人访问,这不仅仅是流量玄学,很多时候是底子没打牢。很多新手朋友问,明明页面挺好看,为什么百度搜不到,甚至打开速度还慢?问题往往出在代码结构和标准兼容性上。今天不聊虚的,直接拿一… · 2026/9/27 7:57:33
FastAPI + PostgreSQL 实战:做一个重启后还能继续的审批流程 FastAPI PostgreSQL 实战:做一个重启后还能继续的审批流程 《企业级 Workflow 实战:从审批流到 AI Agent》|第 03 篇 / 共 24 篇 本篇成果:提交客户服务申请、创建运营待办、完成审批、查询流程历史,并实测应用进程重… · 2026/9/27 7:57:33
LeetCode 1096.花括号展开 II:一个一百行的解题方法(DFS) 【LetMeFly】1096.花括号展开 II:一个一百行的解题方法(DFS)
力扣题目链接:https://leetcode.cn/problems/brace-expansion-ii/
如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符… · 2026/9/27 7:57:27
Amethyst 瓦片地图实战:从 Tile 特征实现到 TileMap 组件创建完整指南 【免费下载链接】amethyst Data-oriented and data-driven game engine written in Rust 项目地址: https://gitcode.com/gh_mirrors/ame/amethyst 点击查看 免费下载 本篇技术指南围绕 Amethyst 游戏引擎(Rust 编写的数据驱动游戏引擎)的 a… · 2026/9/27 7:57:21
AutoBangumi 解析器配置指南:RSS 标题解析引擎、语言与全局过滤规则 后端前端音视频 【免费下载链接】Auto_Bangumi AutoBangumi - 全自动追番工具 项目地址: https://gitcode.com/gh_mirrors/au/Auto_Bangumi 点击查看 免费下载 AutoBangumi 的解析器(Parser)负责从 RSS 条目标题中抽取结构化的番剧元数据&am… · 2026/9/27 7:57:21
换机照片怎么迁移才靠谱?6种方案对比,原图与备份一次讲清 换手机时,照片迁移最需要关注的不是单纯的“速度”,而是文件有没有完整过去、原始信息有没有变化,以及迁移完成后有没有备用副本。如果只有几百张照片,手机直连通常就能解决;但面对几千甚至上万张照片,尤其… · 2026/9/27 7:57:21
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01