YOLOv5+海康相机工业视觉落地:C++ DLL封装与部署实战
做工业视觉项目的朋友应该都遇到过类似情况模型在笔记本上跑得飞快一到现场就各种“水土不服”——客户上位机是C#写的现场电脑没有Python环境相机SDK和深度学习推理代码互相抢资源再加上产线节拍要求压着眼看着Demo能用真正落地却要脱层皮。我最近做一个项目就是典型的“Yolov5 海康相机”组合图片目标检测模型跑在C封装好的DLL里供上位机调用。整个过程踩了不少坑也有很多值得记录的经验。这篇就围绕这个方案从需求拆解、相机配置、模型选型与导出、DLL封装、到现场问题排查完整梳理一遍。这个方案适合谁做工业视觉集成、自动化设备上位机开发的朋友或者准备把深度学习检测能力封装成通用模块的团队。看完你至少能理清一条从相机取图到算法推理、再到交付DLL的完整链路知道每一步该怎么选、为什么不这么选。1. 项目背景与需求拆解这套方案到底在解决什么1.1 从“Python能跑通”到“产线能交付”的距离很多团队在前期验证阶段都是用Python写推理脚本加载Yolov5模型对着几张测试图片画框效果不错就觉得项目差不多了。实际到了产线集成阶段问题全冒出来了。先不说Python环境在工控机上有多难维护就说接口这件事。产线上的上位机软件通常是用C#或LabVIEW开发的它们怎么调用你的Python推理脚本进程通信文件共享临时写个HTTP服务听起来都能实现但每一个都不够稳定而且速度根本跟不上产线节拍。C封装DLL的意义就在于把算法推理、图像预处理、相机取流这些底层操作全部封装成一个标准动态库对外暴露几个简洁的接口函数。上位机只需要加载DLL、传一张图片进去、拿回检测结果其他一概不用管。接口稳定了部署环境干净了还顺手解决了Python解释器带来的性能损耗。1.2 项目需求拆解与系统架构划分拿到这个标题第一步是把它拆成几个独立模块海康相机图像采集模块负责相机初始化、参数配置、图像抓取输出原始图像数据。Yolov5推理模块负责加载模型、图像预处理、前向推理、后处理输出检测框。C封装层将上面两个模块整合对外提供DLL接口管理内部线程和资源。这三个模块在逻辑上必须严格分层。最容易犯的错误就是把相机采集和算法推理搅在一起结果换一台相机要把推理代码一起改换个模型又要把采集代码动一遍。一个稳妥的架构是底层相机SDK负责拉流模型推理引擎负责算两者互不感知中间层C封装层负责调度、格式转换、结果回传上层客户上位机只管调用接口拿到结果。这样后续扩展也容易今天接海康相机明天换其他品牌只需要替换底层SDK封装层接口保持不变。1.3 为什么选Yolov5而不是其他检测方案工业视觉里常见的目标检测路线有几条传统机器视觉模板匹配、边缘检测、Blob分析、两阶段检测器Faster R-CNN、单阶段检测器Yolo系列再加上新兴的Transformer检测方案。传统机器视觉对打光稳定、位置固定的场景很有效但一旦目标形态多变、背景复杂、存在遮挡传统方法就会崩。典型的例子是零部件表面缺陷检测同一个缺陷在不同角度、不同光照下长得完全不一样模板匹配根本抓不住。Yolov5在这个场景里的优势很实在单阶段结构推理速度快满足产线实时性要求模型体积适中在普通工控机上的GPU上跑起来很轻松工程化生态成熟从训练到导出再到推理部署的链路短坑相对少PyTorch训练的权重可以转成TorchScript或者ONNX方便接入C推理后端。我做这个项目时还对比过Yolov8但考虑到客户现场硬件是老一代GPUTensorRT优化生态对Yolov5的支持更成熟最终选了Yolov5。这个选择后面证明是划算的。2. 海康工业相机侧的关键配置与采集流程2.1 相机SDK初始化与设备选择海康相机的SDK核心流程其实很固定枚举设备、创建句柄、打开设备、开始取流、取图、停止取流、关闭设备。有一点需要注意相机SDK的接口大部分是C风格的和C封装层对接时最好再包一层C类把句柄和设备信息封装成成员变量避免裸指针满天飞。初始化阶段最容易翻车的地方是设备枚举和权限冲突。工业相机经常遇到两个软件同时抢占设备——比如调试用的MVS客户端还开着你的程序就去打开设备直接报访问冲突。写代码之前一定要先关掉调试工具或者在代码里做设备占用检测。另外某些工控机上USB接口供电不足会导致相机枚举失败这种问题排查起来特别费时间。2.2 触发模式、曝光与图像格式的参数取舍工业视觉场景和普通拍照最大的区别在于对图像采集的时序和稳定性有硬要求。相机触发模式一般分连续采集和硬触发。连续采集适合做实时视频流检测只要帧率够、检测速度跟得上就一直采一直检。硬触发则适合配合传感器、编码器使用的工位检测比如产品走到指定位置传感器给一个电平信号相机才拍一张。这个项目里客户要求是软触发模式下的连续采集。曝光时间根据现场光照环境和被测物运动速度来定。运动速度越快曝光时间必须越短否则图像拖影模型检测率直线下降。我当时的做法是先查看现场产线速度估算出物体在一个像素内移动的时间再反推最大允许曝光时间。图像格式这个参数非常关键。海康相机SDK默认输出的可能是Mono8、BayerRG8、YUV422等格式但Yolov5训练时通常用的是RGB三通道图片。中间必须做格式转换。Mono8转RGB很简单三通道复制同一个灰度值就行Bayer格式需要做插值去马赛克这一步处理不好图像会出现明显的伪彩条纹直接影响检测精度。2.3 图像缓冲区和回调线程的设计海康SDK取流有两种主要模式回调模式和主动取流。回调模式下相机每采集一帧图像SDK就调用一次回调函数把图像数据传给你主动取流则是你循环调用取图接口。工业视觉里我建议用回调模式内部缓存队列的方案。原因在于回调函数里绝对不能做耗时操作比如推理、保存图片、打印日志这些都会阻塞SDK内部线程导致丢帧。正确的做法是回调函数只做一件事把图像数据拷贝到预分配的内存缓冲里塞进队列然后立即返回。我项目里的实现是分配一个环形缓冲队列队列长度设置成5~10帧回调线程只负责写入推理线程从队列另一头取图。这样即使某帧推理耗时突然变长缓冲队列能兜住上位机感受到的实时性不会瞬间崩塌。3. Yolov5模型选择、导出与工业侧调优3.1 数据采集与标注的工业项目实战工业项目里模型效果的上限一半在数据上。很多人拿来训练的数据是现场随手拍的几十张图标注还参差不齐最终效果不好就开始调模型结构、调超参数方向完全跑偏了。我踩过的坑是不同类型缺陷的数量分布要刻意控制不能相差太大。比如某类缺陷现场出现频率很低标注样本可能就20张模型学不到特征另一类缺陷占了80%的训练数据模型会有严重的偏置。补数据的操作是对少数类做离线增强调亮度、加噪声、随机裁剪把数量拉到接近多数类的三分之一以上效果立竿见影。标注还有一个值得说的细节工业场景里的目标往往有遮挡、模糊、极小尺寸的问题。XViewer和LabelImg这类标注工具虽然能用但标注时要格外注意边界框是否贴合目标有几个像素的误差都会影响小目标的检测精度。3.2 模型训练与导出格式选择TorchScript还是ONNX训练完的Yolov5模型要部署到C环境必须脱离PyTorch的Python环境。常见的导出格式有两种TorchScript和ONNX。TorchScript可以保留完整的PyTorch算子结构加载时直接用LibTorchPyTorch C版本运行。好处是算子支持完整几乎不会出现不支持报错坏处是LibTorch库体积比较大而且对GPU显存占用稍微高一些。ONNX则需要额外选择推理后端比如ONNX Runtime或OpenCV DNN。ONNX Runtime跨平台性好、库体积更小但导出时可能遇到某些自定义算子不支持的问题。我在这个项目里用的是ONNX Runtime主要原因是可以方便地在CPU和CUDA之间切换部署灵活性更高。导出时有一个细节一定要检查Yolov5的导出脚本默认会做模型简化去掉训练相关的分支保留推理结构。导出后用Netron打开ONNX文件确认输出节点确实是三个尺度的检测头而不是把后处理一起缝合进去。这样在C端做后处理时输入输出结构都比较清晰。3.3 部署推理时OpenCV DNN与TensorRT的取舍C环境里跑Yolov5 ONNX有三个常见选择OpenCV DNN模块、ONNX Runtime、TensorRT。OpenCV DNN的好处是依赖最少——很多工业项目本来就要用OpenCV做图像处理直接引过来就行。缺点是推理速度和ONNX Runtime比还是有差距尤其在老显卡上差了将近一倍。TensorRT是NVIDIA专门优化的推理引擎速度最快但有两个麻烦一是需要额外做模型转换和序列化二是不同显卡、不同CUDA版本之间兼容性差换台工控机可能要重新生成TensorRT引擎文件。我最终选了ONNX Runtime路线原因是交付现场的工控机配置不稳定既要有CUDA加速又不能在换机器时搞出各种兼容性问题。ONNX Runtime提供一套统一的API可以在初始化时选择EPExecution ProviderCUDA可用就优先CUDA不可用就自动回落CPU。这种容错机制在工业现场是刚需。4. C封装DLL的接口设计与线程模型4.1 DLL导出接口设计的三个原则工业场景的DLL一定不是给程序员用的而是给不确定用什么语言写上位机的工程师用的。接口设计需要尽量傻、尽量好调用。以我的项目为例最终暴露的接口很简单/// 初始化传入模型路径、模型类型、GPU设备ID等参数 int VIS_Init(const char* modelPath, int deviceId, int useCuda); /// 推理一帧输入图像数据、宽高、格式输出检测结果 int VIS_DetectImage(const unsigned char* imgData, int width, int height, int channels, float confThres, float iouThres, DetectResult* results, int* resultCount); /// 释放资源 int VIS_Release();三个原则第一接口只传必要参数禁止暴露内部结构。模型路径、图像指针、检测结果够了。不要让上位机关心预处理、归一化、锚框、NMS这些概念。第二内存管理规则要写在注释里。比如检测结果框坐标是相对像素坐标还是归一化坐标、结果数组由谁负责释放这些必须写清楚。我第一次交付时没写清楚内存归属客户直接按自己理解释放了程序闪退来回排查了很久。第三必须做线程安全。上位机可能多线程同时调检测接口如果DLL内部不加锁并发调用时模型推理状态会被破坏。我的做法是在检测接口里加一个递归互斥锁保证同一时刻只有一个线程进入推理。4.2 采集线程、推理线程、通信线程怎么协作一个典型的工业C DLL内部至少有三类线程在工作采集线程这里其实是海康SDK的回调负责把图像塞进缓冲队列推理线程从缓冲队列取图做预处理、推理、后处理生成结果通信线程DLL与上位机之间的交互一般由上位机主动调用触发的但在实时推送场景下需要DLL有独立的回调线程向上位机报告结果。在设计上要理清楚每条线程之间通过什么数据结构通信。我的方案是采集回调 → 环形队列图像帧推理线程 → 条件变量等待队列有数据推理结果 → 结果队列 回调通知上位机注册回调函数推理完成立刻通知。用条件变量比用空转循环轮询要高效得多CPU占用率能压到很低。实测下来一个空转轮询队列的程序CPU占用能到15%改成条件变量之后掉到1%以下。4.3 内存管理与回调机制的避坑经验工业项目运行时间长达数月内存泄漏是绝对不能容忍的。但Yolov5推理涉及到的内存点特别多图像数据拷贝、预处理后张量、后处理数组、结果返回结构体每个环节都可能漏。我排查内存泄漏时用了一招把所有与外部交互的内存分配归到少数几个固定位置并且在接口注释里写清楚“谁分配、谁释放”。比如推理接口内部用了智能指针管理模型输入输出张量结果结构体里的坐标数组用std::vector管理在上位机拿完数据后调用一个专门的释放函数。回调机制这里有个很容易踩的坑DLL调用上位机注册的回调函数时如果上位机内部实现不是线程安全的可能会崩溃。所以DLL内部做回调通知时最好用一个独立的消息队列先通知给上层一个“新结果来了”的信号而不是直接把推理地址传过去。这样即使上层反应慢了也不会阻塞推理线程。5. 集成测试与常见问题排查实录5.1 图像格式搞错引发的“灾难”印象很深的一次相机SDK输出的是BGR格式Yolov5模型是用RGB训练和预处理的我没有做通道转换直接把图像数据送进模型结果检测率直接从90%掉到30%。花了一整天排查最后打印了图像的均值才发现通道顺序不对。类似的格式陷阱还有很多图像宽度是否做了四字节对齐、行尾是否包含填充字节、内存排列是连续还是交错。工业相机SDK出来的图像经常有padding如果不处理网络输入的前几层卷积看到的数据就是歪的。解决方案很简单在封装层统一做一个预处理函数把所有格式来源的图片统一转成模型需要的RGB连续内存布局。这个函数里做完整性校验比如图像尺寸、通道数、行字节数是否匹配不匹配就直接抛错。5.2 相机掉线、帧堆积与实时性冲突工业现场电磁环境复杂相机偶尔掉线是常态。千万不要以为SDK重新打开设备就能恢复很多老版本SDK在异常断开后句柄状态是残留的。我的处理是做一个看门狗机制单独一个监控线程定期查询相机连接状态一旦发现断开就执行全套重新初始化流程——释放旧句柄、重新枚举、创建句柄、打开设备、恢复参数设置。整套逻辑封装成TryReconnect函数实测能在300~500毫秒内恢复取流。帧堆积是另一个常见问题。当推理速度跟不上相机帧率时缓冲队列会越堆越多延迟越来越大最终导致检测结果严重滞后于实际产线。我的做法是队列深度限制加丢帧策略队列满了直接丢掉最旧的一帧。实时性优先于完整性这是工业检测的铁律。5.3 部署环境差异显卡、运行库、杀毒软件同一个DLL在不同工控机上表现可能完全不同。模型推理速度、内存占用、启动时间都可能出现数倍差异。显卡差异是最难预判的有的工控机是老旧显卡不支持CUDA有的装了显卡但驱动的CUDA版本和DLL内置的不匹配一加载就崩溃。现在我的做法是发布时带上ONNX Runtime的CPU版作为兜底动态检测显卡能力不支持就自动切CPU。虽然后者速度可能差5倍但至少不崩。运行库也是个坑。VC运行库版本不对DLL加载时报错这是工业电脑上的高发问题。交付清单里必须写明依赖的运行时版本最好直接跟客户确认目标机已经装了对应运行库。还有一次很意外客户的杀毒软件把DLL加载时的模型文件当成可疑行为直接隔离了导致程序启动时报模型加载失败。后来建议客户在杀毒软件里加白名单才算彻底解决。6. 几个值得留档的实战经验做这个项目我个人在现场调试中总结了几条经验写成清单放在最后工业检测项目的第一步永远是把数据采集环节做扎实。模型没训练之前先把相机、光照、夹具全部调好保证拍到的图像质量稳定。图像不稳定后面模型再调也没用。C封装DLL时头文件的注释要多写。客户上位机开发者不是算法工程师他需要清清楚楚知道接口参数的含义和内存管理规则。把这些写在注释里比写文档管用得多。推理速度测试要放在目标工控机上做不要在开发机上自嗨。开发机上跑30毫秒一帧现场工控机上可能变成80毫秒一旦不满足节拍需求就得提前换方案。交付时除了DLL和模型文件还要交付一个简单的命令行示例程序。这个程序能直接加载DLL、跑通一次检测、打印结果用来验证环境是否正常非常省事。很多现场问题最后都是在命令行示例程序里排查定位的。Yolov5模型训练时验证集一定要按现场实际情况拍摄不能用网图或实验室图片凑数。模型对光照、角度、材质非常敏感训练集和现场图像分布不一致时检测率会有肉眼可见的落差。这个方案后续还可以扩展的方向很多比如把海康相机的取流后处理放到GPU上做减少一次内存拷贝模型换成Yolov8或者RT-DETR配合TensorRT做优化再加一个配置文件让上位机不用改代码就能切换不同模型。做工业视觉项目就是这样每做一个项目踩一遍坑沉淀出来的东西就多一分复用价值。

相关新闻

矩阵置零原地算法详解:从暴力解法到O(1)空间最优解

矩阵置零原地算法详解:从暴力解法到O(1)空间最优解

矩阵置零这道题我太熟了,LeetCode 第 73 题,也是我面试时特别喜欢拿出来考候选人的一道。题面简单到不能再简单:给你一个 mn 的矩阵,矩阵里只要有格子是 0,就把这一整行和这一整列全部变成 0。限制条件就一个&#xff…

2026/10/18 11:05:57 阅读更多 →
贝叶斯网络与Simulink在电力系统故障诊断中的应用实践

贝叶斯网络与Simulink在电力系统故障诊断中的应用实践

简介:这份基于贝叶斯的电力系统故障诊断仿真资料包,面向电力系统研究者、工程师及相关专业学生,针对故障识别与定位中的噪声、不完整数据问题,提供一套可运行的判别方案。资料利用贝叶斯概率框架,通过先验概率与观测数…

2026/10/18 11:05:57 阅读更多 →
单目RGB端到端3D目标检测:YOLOv5双头结构+相机几何解算

单目RGB端到端3D目标检测:YOLOv5双头结构+相机几何解算

简介:本资源是一套面向计算机视觉初学者与算法工程师的3D目标检测实战项目,聚焦于YOLO框架与单目深度估计融合的轻量级三维检测方案,适用于自动驾驶感知模块验证、机器人环境理解等实际场景。压缩包共7个文件,含5个核心Python脚本…

2026/10/18 11:05:57 阅读更多 →

最新新闻

开源Code Review解决方案:从规范到工具的全流程实践

开源Code Review解决方案:从规范到工具的全流程实践

1. 为什么我会专门做一个开源的 Code Review 项目先交代一下背景。我所在的团队大概三十来人,前后端、算法、质量都混在一起,日常迭代节奏很快。Code Review 这件事一直都有,但长期处于一种"有等于没有"的状态:PR 挂着两…

2026/10/19 15:03:58 阅读更多 →
open-code-review实践:从规则配置到团队代码质量提升

open-code-review实践:从规则配置到团队代码质量提升

写代码这事,写得越多越觉得“review”才是真正拉开差距的环节。我自己维护过几个开源小项目,也在团队里带过人,最深的体会是:代码审查做得好不好,直接决定一个项目是越改越顺还是越改越乱。但人工review的问题也很明显…

2026/10/19 15:03:58 阅读更多 →
工业级仪表OCR系统:抗模糊、防跳变、可追溯的数字读数自动采集方案

工业级仪表OCR系统:抗模糊、防跳变、可追溯的数字读数自动采集方案

简介:本资源是一套基于计算机视觉的智能测量仪器数字识别与检定数据自动化记录系统,面向计量检测人员、自动化测试工程师及高校测控/仪器仪表方向学习者,旨在解决传统人工读数、手动录入导致的效率低、易出错、难追溯等核心痛点。系统通过摄像…

2026/10/19 15:03:58 阅读更多 →
CNN花卉识别毕设实战:数据准备、模型训练与Web/PyQt双端部署

CNN花卉识别毕设实战:数据准备、模型训练与Web/PyQt双端部署

最近有朋友聊起他带的本科毕设,题目是“基于CNN卷积神经网络的11种花卉识别小程序,Web端和PyQt双端交付”。这个课题我太熟了,自己当年就是从零开始,数据集自己整理、CNN模型搭了好几版、Web端和PyQt端各写一套前端,最…

2026/10/19 15:03:58 阅读更多 →
U盘格式化失败?用cmd命令行diskpart彻底修复与格式化指南

U盘格式化失败?用cmd命令行diskpart彻底修复与格式化指南

1. 什么时候必须用 cmd 格式化 U 盘,而不是右键点“格式化”平时想格式化 U 盘,大家的第一反应肯定是:插上 U 盘,打开“此电脑”,右键,选“格式化”,确认一下就完事。这个方法确实管用&#xff…

2026/10/19 15:03:58 阅读更多 →
千笔·降AIGC助手实测:本科论文如何有效降低AI检测痕迹

千笔·降AIGC助手实测:本科论文如何有效降低AI检测痕迹

不少本科同学写论文,走到最后一步才发现真正卡脖子的不是文献、不是框架、不是数据,而是满屏“AI味”的表述。辛辛苦苦列提纲、喂材料、分段生成,最后成稿拿去审,导师一眼扫过就丢回来一句“机器写的,改人话”。这种感…

2026/10/19 15:02:52 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →