C#上位机集成YOLO实现产线视觉检测:从ONNX部署到PLC联调的全流程实践
几个月前我们团队接手了一个产线级视觉检测项目需求本身不复杂C#上位机控制工业相机拍照调用YOLO模型做缺陷检测再把结果同步给PLC实现自动分拣。从实验室里跑通Demo到产线上稳定运行这中间踩的坑远比想象中多。很多人觉得YOLO部署无非就是拿个ONNX模型用C#调用一下推理引擎实际上线一小时就会被打脸——相机触发、图像传输、推理耗时、结果判定、通信握手任何一个环节都可能让整个系统卡壳。这篇博文就把我们从理论到产线的完整过程拆开来讲包括方案选型、关键代码逻辑、调试思路、踩坑记录和避坑技巧给正在做或者准备做类似项目的朋友一个参考。适合谁看如果你正在用C#做上位机、想把YOLO视觉方案落地到实际产线、或者已经在做但被各种隐藏问题折磨这篇文章应该能帮你省下不少时间。1. 项目背景与整体架构选型1.1 为什么选择C#上位机YOLO这套组合先说背景我们的检测目标是某工厂产线上的零部件外观缺陷包括表面划痕、缺料、边缘毛刺三类。产线节拍要求单件检测时间不超过2秒检测精度要求召回率在95%以上。团队之前有C#开发经验算法部分则用YOLO系列模型做了大量验证。说实话选C#做上位机在当时几乎是唯一选择工控领域的主流PLC通信库、工业相机SDK比如海康、大华的官方驱动C#封装都很成熟而且WinForm/WPF开发效率高产线操作工培训成本也低。至于视觉算法这块YOLO已经是工业视觉里绕不开的方案检测速度快、精度高而且模型导出和部署路径非常清晰PyTorch训练完导出ONNXC#侧直接调用。很多人纠结要不要用Python直接做全套我的建议是如果只是做实验、调算法Python完全没问题。但如果要对接产线设备、做长期维护、和MES系统交互C#上位机的生态优势太明显了。我们项目里PLC用的是MODBUS TCP协议上位机用C#写一个通信类库几百行代码就搞定了换成Python还得额外处理很多边界问题。1.2 系统整体架构与数据流设计整个系统的硬件组成很简单一台工控机i5处理器、16GB内存、无独立显卡算力全靠CPU、一个千兆网工业相机、光源控制器、PLC和执行机构。软件架构上分成三层界面层C# WinForm负责参数配置、实时画面显示、检测结果统计业务逻辑层负责相机触发、图像采集、推理调用、结果判定、PLC通信算法服务层封装YOLO推理提供图像输入、结果输出的标准接口数据流是这样的PLC给上位机发送拍照信号电平触发→ 上位机控制相机采集图像 → 图像送入推理模块 → 推理结果返回 → 上位机根据判定规则决定OK/NG → 结果写入PLC寄存器 → PLC驱动分拣机构动作。这里有个关键设计决策我们把YOLO推理放在独立线程池中而不是和UI线程混在一起。否则图像推理期间界面会卡死操作工一旦误操作整个流程就乱了。线程池队列容量可以配置默认是10个任务超出后丢弃并记录日志防止内存暴涨。2. 核心模块设计与关键细节2.1 工业相机采集与图像预处理产线视觉项目里相机采集是最容易出问题但又最容易被忽视的环节。我们用的是某国产工业相机200万像素黑白相机配了一个16mm定焦镜头工作距离大概280mm视野范围调到刚好覆盖零部件整个表面。采图这块有几个点必须说明第一相机触发模式。我们用的是硬触发模式PLC通过IO卡发一个脉冲信号给相机的触发线相机收到信号后立即曝光采集。比软触发上位机发指令触发可靠得多因为软触发存在线程调度延迟在高节拍下容易丢帧。硬触发延迟可以控制在微秒级别完全满足工业需求。第二图像格式。工业相机默认输出的可能是Bayer原始格式在C#里要用SDK转换我们直接设置相机输出Mono8格式也就是每个像素8位灰度省去转换环节。YOLO模型输入也需要归一化到0-255的灰度图直接用Mono8最方便。预处理方面踩过一个坑YOLO输入尺寸一般要求640×640但相机原图分辨率是1920×1200。直接Resize会丢失小目标细节后来我们改成先按长边等比缩放再对剩余区域填充灰色相当于Letterbox处理。这样小缺陷的特征保留度比直接拉伸好很多前期测试阶段漏检率直接降了3个百分点。2.2 YOLO推理引擎的集成方案C#调用YOLO推理主流方案有两个一个是ONNX Runtime微软官方维护跨平台、支持CPU和GPU另一个是OpenVINOIntel家的对自家硬件优化好。我们工控机是Intel CPU理论上OpenVINO推理速度更快但这个项目里工控机算力还算够用而且ONNX Runtime的部署更通用后续换硬件不用改代码所以最终选了ONNX Runtime。模型导出这一步坑也不少。训练好的YOLO模型用PyTorch导出ONNX时要注意几个参数opset_version建议用17以上动态轴要显式声明否则C#侧导出时输入尺寸写死就麻烦了。我们用的是import torch import torch.onnx model torch.load(best.pt, map_locationcpu)[model].float() model.eval() dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export( model, dummy_input, best.onnx, opset_version17, input_names[images], output_names[outputs], dynamic_axes{images: {0: batch_size}} )C#侧加载模型时我用的是ONNX Runtime的.NET API直接以NuGet包引入即可。关键代码逻辑using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; var session new InferenceSession(best.onnx); var inputMeta session.InputMetadata.First(); var inputName inputMeta.Key; var inputTensor new DenseTensorfloat(new[] { 1, 3, 640, 640 }); // 填充图像数据... var inputs new ListNamedOnnxValue { NamedOnnxValue.CreateFromTensor(inputName, inputTensor) }; using (var results session.Run(inputs)) { var output results.First().AsTensorfloat(); // 解析output四个值分别是x1, y1, x2, y2, confidence, class_id }这里有个重要的点YOLOv5的ONNX输出是一个[1, 25200, 6]的张量其中25200是三个尺度feature map的anchor总数6表示x1、y1、x2、y2、confidence、class_id。需要在这些候选框上做非极大值抑制NMS筛掉重叠的框。如果不做NMS同一个缺陷会被框三四次计数器直接爆掉。2.3 结果判定逻辑与PLC交互设计算法的输出只是“检测框坐标置信度”上位机的职责是把这些转换为产线能执行的动作。这里不能只根据置信度判定OK/NG因为实际产线上一次拍照可能出现多个缺陷也可能同一个位置有多个重叠框。我们制定了三层判定逻辑第一层对每个检测框做NMS保留最终确定的框第二层根据置信度阈值默认0.5筛掉低质量框第三层业务规则判定比如同一零部件上出现任何缺陷类别中置信度最高的框即判定为NG细化到我们项目里如果检测到1个划痕框但置信度只有0.45单独看它可能没到阈值。缺陷往往在临界状态下是模糊的——光照稍微一变同一位置有时检出0.6有时0.4。所以我们的业务规则是只要存在任何一个框的置信度超过阈值就判定NG而不是要求所有框都超过。为避免重复计数对同一坐标附近的多个框我们把它们合并成一个缺陷记录。PLC通信我们用的是MODBUS TCP这是工业现场最常见的协议。上位机作为ClientPLC作为Server。上位机周期性地读取PLC的寄存器区地址30001其中第1个寄存器存放PLC发送的“拍照请求信号”第2个寄存器用于上位机返回检测结果1OK2NG第3个寄存器是握手信号。这块的通信协议看似简单实际调试中踩了不少坑后面常见问题章节会展开说。3. 从Demo到产线的实操落地过程3.1 环境搭建与通信验证项目开始的第一周主要在搭环境、验证通信链路。先把工控机系统装好Windows 10专业版然后装.NET运行时我们用的是.NET Framework 4.8因为相机SDK和老代码兼容性更好。装环境时有个小坑ONNX Runtime的NuGet包有原生依赖需要确保VC运行库已安装否则运行时会报找不到DLL的错误。接着做通信链路验证。先测上位机到PLC的MODBUS TCP连接——用Modbus Poll工具先测好寄存器读写确认PLC地址映射正确之后再用我们C#的通信类去读。这个阶段发现一个重要问题PLC那边的寄存器地址分配是工程师预先定义好的必须严格按照他们的地址表来一个位写错整个信号就乱了。建议拿到PLC地址表后先在程序里写一个“寄存器自检”功能启动时自动读一遍所有寄存器显示在界面上方便排查。相机SDK验证设置相机IP和子网掩码时注意工业相机和工控机要在同一个网段否则Camera SDK扫描不到。我们当时就是把IPC的IP设成了192.168.0.2工控机网卡还保留设成192.168.0.1结果扫描不到相机。后来发现网卡驱动默认开启了“巨型帧”导致图像数据传输丢包关掉就正常了。3.2 推理服务与上位机的数据对接环境稳定后开始正式写推理模块。我把YOLO推理封装成一个独立的YoloDetector类构造函数加载模型提供Detect(Bitmap image)方法返回一个ListDetectionResult每个结果包含类别、置信度和矩形区域。这样UI层、业务逻辑层都依赖这个统一接口后续换模型或者换推理后端都只改一处。封装完推理模块再写一个生产者-消费者模式的检测服务类。生产者是PLC发来的拍照信号消费者是推理线程。每当PLC发来信号上位机就采图、推理这个过程在消费者线程里完成。代码结构大概是这样private void PlcSignalLoop() { while (true) { // 读取PLC拍照请求信号 int req plc.ReadRegister(30001); if (req 1) { // 采集图像 Bitmap frame camera.GetImage(); // 推理 var detections detector.Detect(frame); // 判定 int result Judge(detections); // 写回PLC plc.WriteRegister(30002, result); plc.WriteRegister(30003, 1); // 握手完成信号 // 更新界面统计 UpdateUi(detections); } Thread.Sleep(30); } }这个循环里用的Thread.Sleep(30)是轮询PLC的间隔。实际产线对实时性要求没那么高30毫秒足够快到人眼看不出延迟。但如果产线节拍更快就需要改成消息队列事件通知的方式否则轮询会成为瓶颈。界面设计上我加了一个实时检测结果面板左边是一块大画面区域直接把相机图像实时显示检测框以不同颜色覆盖红色NG绿色OK右边是统计数据包括总检测数、OK数、NG数、通过率以及一个扇形图显示各类缺陷占比。操作工不需要任何培训一眼就能看出当前产线状态。3.3 产线节拍优化与UI设计Demo阶段跑通后就要开始抠时间因为产线要求单件2秒以内。我们先做了分阶段的耗时分析结果发现问题集中在三块图像采集耗时约350ms曝光时间太长、推理约900ms、PLC通信和逻辑判断约200ms单件总耗时1.45秒理论上是够的。但实际连续跑起来偶尔会出现2.5秒的情况说明存在偶发阻塞。排查之后发现三个原因一是推理线程和UI线程共用同一个内存中的Bitmap对象UI更新画面时锁定了图像推理线程就得等二是相机SDK内部有个默认的重传机制偶尔网络抖动时会阻塞三是PLC通信用了同步读写如果某个时刻PLC有不响应的情况会占用线程。解决办法很简单给图像数据加一把独立的锁UI显示时复制一份缩略图而不是直接引用原图把PLC通信改为异步模式同时增加一个看门狗如果PLC通信超时3秒就自动重连。优化后单件耗时稳定在1.3-1.6秒满足产线要求。4. 实际产线调试中的踩坑记录4.1 漏检与误检问题排查系统上线第一天就发现两个致命问题漏检率飙升有些明显的划痕居然没检出来同时误检率也高得离谱有些完全正常的零件被标成NG。先说漏检。逐一排查后发现跟训练时的图像分布有关。训练样本大多是均匀光照下拍的清晰图像但产线上的实际场景复杂得多——零件位置有偏差、光线角度有变化、甚至相机镜头上有点灰。YOLO模型的鲁棒性没有想象中好之前测试时的85%准确率在真实产线上可能直接掉到70%。解决办法是现场采集1000张真实产线图像人工标注后重新训练模型。这一步是必经之路光靠实验室数据集上线的视觉系统十个有九个会在现场翻车。重新训练的模型漏检率才压到了5%以内。误检问题更隐蔽。后来发现是光源闪烁导致图像亮度周期性变化YOLO对亮度极其敏感稍有偏移就把高频纹理误判成划痕。解决方法是调整光源控制器的频率把频闪模式改为常亮模式同时加了一个自动曝光校准策略——每隔一段时间用一张标准白板校正相机的曝光时间保证亮度一致。4.2 高延迟问题的根源分析排查延迟时发现一个很有意思的问题生产Electron架构的软件用久了会延迟高但我们的C#程序也会偶发高延迟原因出在垃圾回收上。推理过程需要申请大量内存来存放图像数据和结果频繁的GC会让推理线程卡顿。解决方案有三个一是减少内存分配比如图像数据用byte[]复用而不是每次采集都新建对象二是使用GC.TryStartNoGCRegion在关键推理期间临时禁GC让推理线程不被中断三是把推理线程的优先级调到最高虽然这样做UI在推理期间会有一点卡顿但产线场景UI本来就不需要那么流畅可以接受。实测这三个方案组合使用后推理线程的最大停顿时间从原先的300ms降到了50ms以内。如果不想这么复杂一个更简单的方案是直接加一块便宜的GPU卡推理主要扔到GPUCPU几乎不参与GC影响就小多了。4.3 相机标定与光照环境的影响还有个大坑是相机安装角度导致的坐标偏差。我们在实验室里用的相机是正对着零件的俯视角度产线上由于结构限制相机只能倾斜安装结果就是同一个缺陷在图像里的位置和实际位置存在偏移。检测框倒是能框住但如果需要精确的机械手定位这个偏移就是大麻烦。用棋盘格标定板做了一次完整的相机标定得到内参和畸变系数然后校正图像。YOLO推理在校正后的图像上运行。如果不需要机械手定位只是做OK/NG判定其实可以不标定。但如果有定位需求这一步必须做否则就是反复试错。光照这块产线车间的环境光影响非常大。窗户边的产线和封闭车间的产线亮度差好几倍。我们最终用的是条形光源漫射板的组合把入射光打散极大减少了零件表面反光引起的误检。光源的角度要反复试最佳位置是让反射光不直接进入相机镜头否则图像里会出现大面积高光区域YOLO完全找不到特征。5. 常见问题速查表与独家避坑技巧5.1 问题速查表问题现象可能原因排查方向解决建议相机SDK扫描不到设备网段不一致/IP冲突检查工控机网卡和相机IP统一网段关闭巨型帧推理速度慢CPU过热降频/模型过大监控CPU温度与负载升级硬件或采用OpenVINO偶尔漏检模型鲁棒性不足分析漏检样本特征重新采集现场数据训练检测结果有延迟GC阻塞/线程争用观察推理线程停顿内存复用、调整线程优先级PLC通信超时寄存器映射错误/网线松动用Modbus Poll验证增加看门狗自动重连误检率偏高光源波动/反光查看图像亮度分布改进光源角度稳定曝光5.2 给后来者的避坑清单第一别拿Demo直接上线。Demo和产线的差距是巨大的产线的光照、抖动、粉尘、网络波动每一个都会让准确率跳水。一定要先花时间在真实产线上采集数据重新训练或微调模型。第二通信协议一定要提前确认。PLC工程师给的寄存器表和上位机开发者理解的往往有偏差最早拿到地址表就逐位核对实测通信没问题再进行下一步。第三日志系统必须做好。产线出问题的时候没有日志就等于抓瞎。我习惯在每个关键步骤都写日志拍照时间、图像保存路径、推理结果、PLC写入状态。这样排查问题的时候只需要打开日志文件就能还原整个流程。第四UI别搞花哨。产线上操作工大多是初学者界面越简单越好。我见到过有人把检测画面做得像游戏界面各种图表动效结果操作工根本看不懂。一个大画面三个统计数字就是最好的界面。第五对异常情况要有兜底逻辑。比如PLC发了拍照信号但相机采集超时不能就这么卡死推理结果出现异常值不能直接当成NG或者OK要有第三个状态“异常报警”。系统稳定运行之后我个人最大的体会是这类项目的难点不在技术本身而在工程化思维。YOLO模型训练、C#写上位机都是成熟技术但把它们组合起来在恶劣环境里可靠运行靠的是对细节的打磨和对异常的预判。如果你在做类似的系统建议多留出一点时间做现场测试宁可前期慢一点也别让产线停线等你调代码。好用的系统都是慢慢磨出来的。

相关新闻

信息化教学设计高端模板:从框架到视觉的实战指南

信息化教学设计高端模板:从框架到视觉的实战指南

简介:信息化教学设计高端模板是一份面向教师、教研员及师范生的演示文稿,围绕教学分析、教学设计、教学过程、教学反思四个环节搭建完整备课框架。模板将课程结构、教学内容、教学目标、教学重点、学情分析与教学难点系统梳理,帮助使用者在课…

2026/10/18 15:49:14 阅读更多 →
猫抓资源嗅探扩展:网页视频怎么保存,M3U8 分片如何合并下载

猫抓资源嗅探扩展:网页视频怎么保存,M3U8 分片如何合并下载

猫抓资源嗅探扩展:网页视频怎么保存,M3U8 分片如何合并下载 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓&#xff0…

2026/10/18 15:48:14 阅读更多 →
noisereduce音频去噪实战:谱门控原理与参数调优指南

noisereduce音频去噪实战:谱门控原理与参数调优指南

简介:noisereduce-master.zip 是一份基于 Python 的音频降噪开源资源,面向需要处理语音、音乐或野外录音噪声的开发者与数据预处理人员。核心解决思路是先截取待处理音频中的一段纯噪声样本,再通过 noisereduce 库的 reduce_noise 接口对整段…

2026/10/18 15:48:14 阅读更多 →

最新新闻

Transformer时序预测全链路实践:从嵌入到反变换的可调试实现

Transformer时序预测全链路实践:从嵌入到反变换的可调试实现

简介:本资源是一份面向深度学习初学者与时间序列分析实践者的Transformer长期预测实战项目,聚焦将NLP领域经典模型迁移至时序预测任务,解决传统RNN/LSTM难以建模长程依赖的痛点。压缩包共38个文件,含13个核心Python源码&#xff0…

2026/10/18 16:47:42 阅读更多 →
寄大件/重物整个过程中避坑指南

寄大件/重物整个过程中避坑指南

干了八年的快递物流行业, 从最基层的那个网点一直工作到调度中心, 所有的相关岗位都亲身经历过了那种寄送大件以及寄送重物的时候会出现的很多坑我都已经看惯了很多, 今天把所有的这些工作经验全部都摊开来讲给你听, 只要你按照这个方法去操作的话, 基本上就不会吃任何亏。寄之…

2026/10/18 16:47:42 阅读更多 →
hexview:专为车载ECU S19固件解析设计的命令行字节显微镜

hexview:专为车载ECU S19固件解析设计的命令行字节显微镜

简介:本资源是一款面向车载电子工程师的S19/HEX文件解析与转换工具集,专为英飞凌MCU固件开发与调试场景设计,解决汽车电子领域常见的S19格式烧录文件可视化查看、校验及向标准Intel HEX格式转换的实际需求。压缩包共22个文件,含核…

2026/10/18 16:47:42 阅读更多 →
低显存本地跑大模型:AirLLM分层推理原理与实测指南

低显存本地跑大模型:AirLLM分层推理原理与实测指南

AirLLM是我最近折腾本地大模型推理时偶然撞见的一个项目,第一反应是怀疑,第二反应才是真香。它的核心卖点一句话就能讲清:让显存很小的机器也能跑超大参数模型。按常规认知,跑一个70B量级的模型,光权重就要占一百多GB&…

2026/10/18 16:47:42 阅读更多 →
Python实现S参数去嵌:替代ISD闭源软件的T矩阵全流程指南

Python实现S参数去嵌:替代ISD闭源软件的T矩阵全流程指南

简介:针对AtaiTec公司的ISD去嵌入软件永久授权费用超过10万元、且无法二次开发的现实痛点,这份代码包提供了一套基于Matlab的自主替代方案。方案面向射频微波测试、信号完整性分析及高速互连设计等领域的工程师与开发团队,可解决传统去嵌入工…

2026/10/18 16:47:42 阅读更多 →
Vibe Coding 优缺点全解析:用 TaoToken 统一 Key 实测 AI 编程体验

Vibe Coding 优缺点全解析:用 TaoToken 统一 Key 实测 AI 编程体验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 16:46:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →