C#部署YOLOv8-OBB:旋转框解析与OpenVINO推理实战
简介这份C#源码工程基于Intel OpenVINO工具包实现Yolov8-OBB旋转目标检测面向需要在文档识别、条码扫描或交通标志检测中定位倾斜目标的开发者解决普通矩形边界框难以表达旋转物体方向的问题。整个压缩包共337个文件大小约307.77MB包含Visual Studio解决方案与C#工程源码、119个dll运行库、2个onnx模型文件、png测试图片、xml配置、txt说明及NuGet依赖包等结构完整可直接打开编译运行验证。已有724人学习下载。通过该工程可以学习C#调用OpenVINO完成模型加载、预处理与推理的完整流程理解带角度边界框的坐标与角度回归原理并学会将预训练深度学习模型集成到Windows应用项目中。对于希望提升C#与深度学习结合能力、从事旋转目标检测相关开发的初中级开发者这是一份兼顾源代码、依赖库和工程配置的实用参考。1. C# 接 YOLOv8-OBB旋转目标的部署困难不在模型而在输出解析普通 YOLOv8 检测只能给出“四四方方”的边界框遥感楼宇、OCR 文本行、无人机俯拍车辆这类目标一旦倾斜水平框里就会同时塞进前景和背景。YOLOv8-OBB 在原有边界框基础上增加一个角度维度输出带朝向的旋转框。用 C# 做上位机或桌面视觉的人最常遇到的尴尬是网上开源几乎都是 Python 版自己拿 C# 调 OpenVINO 推理模型能跑起来但旋转框的解析、坐标回算、画框这一套后处理却容易翻车。这篇笔记就把这条链路完整拆开从模型导出讲到 C# 推理源码的每一行再把角度符号这类坑一个个填平。2. 模型准备把 YOLOv8-OBB 的权重导出为 OpenVINO IR2.1 为什么选 OpenVINO给 C# 上位机团队的三点理由常见部署方式有 ONNX Runtime、TensorRT、OpenVINO 三种。TensorRT 只对 NVIDIA 显卡友好在工控机上经常没显卡可跑ONNX Runtime 通用但 CPU 上的速度一般OpenVINO 由 Intel 维护对 x86 CPU 和 Intel 核显做了深度优化在无独立显卡的工控机上也能跑出可用帧率。对 C# 上位机团队来说OpenVINO 的优势还能再列两条第一是动态形状支持。YOLOv8-OBB 模型的输入尺寸经常要按业务切换OpenVINO 的 C# 绑定支持在运行时指定输入形状不需要像某些框架那样在导出模型时把尺寸锁死。第二是部署体积。OpenVINO IR 格式只有一个 .xml 加一个 .bin拷到目标机器上不需要额外运行时Int16 量化后的模型体积也能压到几 MB 级别。比较容易被忽视的是 OpenVINO 对 CPU 指令集的自适应。它会在加载模型时检测当前 CPU 支持哪些指令集自动选择最优内核这意味着同一份 .xml 在不同代际的工控机上都能跑只是速度不同。对于 C# 上位机项目这个特性省去了为不同 CPU 分别编译的麻烦。2.2 用 Ultralytics 导出 OpenVINO 模型一条命令与产物清单如果你手头有训练好的 .pt 权重比如 yolov8n-obb.pt导出 OpenVINO 格式只需要一条命令pip install ultralytics openvino yolo export modelyolov8n-obb.pt formatopenvino imgsz640导出完成后当前目录下会出现一个yolov8n-obb_openvino_model文件夹里面包含三个文件文件作用yolov8n-obb.xml模型结构描述包含输入输出节点的名称和形状信息yolov8n-obb.bin模型权重和 .xml 配套使用metadata.yaml训练时的元信息包含类别名称、超参数等imgsz640 指的是训练时使用的输入尺寸如果你训练时用的是 1024这里也要改成 1024。OpenVINO 允许动态输入但保持和训练时一致通常精度最稳。导出时还可以加--half参数将权重转为 FP16在 CPU 上有时能获得小幅性能提升代价是精度略微下降建议先用 FP32 跑通全流程后再对比测试。2.3 检查输入输出张量别让 7 个通道的索引成为黑匣子YOLOv8-OBB 和普通 YOLOv8 在导出后最关键的差异在输出张量。普通检测输出是 4 类别数个通道而 OBB 版本是 5 类别数个通道前 5 个是旋转框的 cx、cy、w、h、angle后面跟着各个类别的置信度。不先确认输出形状就去写 C# 解析代码很容易掉进通道顺序的坑。用一段简单的 Python 脚本查看输入输出信息from openvino import Core core Core() model core.read_model(yolov8n-obb_openvino_model/yolov8n-obb.xml) for inp in model.inputs: print(input:, inp.any_name, inp.partial_shape) for out in model.outputs: print(output:, out.any_name, out.partial_shape)正常情况会看到类似output: output [1, 7, 8400]的形状。这里的 7 代表 5 个旋转框参数加 2 个类别置信度8400 是 640x640 输入下三个检测头合并后的候选框总数。不同 Ultralytics 版本导出的输出可能变成[1, 8400, 7]也就是候选框维在前、通道维在后这个差异直接决定 C# 端遍历索引的方式在避坑章节会专门展开。看到[1, 7, 8400]后要记住一件事C# 端拿到的是连续的一维 float 数组必须知道内存是按通道优先还是候选框优先排列才能正确解析出每个候选框的参数。3. C# 推理实现从图片到 8400 个原始候选框3.1 预处理Letterbox 缩放、RGB 顺序和 float 数组布局C# 端最常见的做法是用 OpenCvSharp 读图和做预处理。YOLOv8 系列在训练时对图片做了 letterbox 缩放即等比例缩放到 640x640剩余区域用灰色填充推理时也必须复现这一步否则检测精度会明显下降。using OpenCvSharp; var src Cv2.ImRead(test.jpg, ImreadModes.Color); const int modelSize 640; float scale Math.Min((float)modelSize / src.Width, (float)modelSize / src.Height); int newW (int)Math.Round(src.Width * scale); int newH (int)Math.Round(src.Height * scale); var resized new Mat(); Cv2.Resize(src, resized, new Size(newW, newH)); int top (modelSize - newH) / 2; int bottom modelSize - newH - top; int left (modelSize - newW) / 2; int right modelSize - newW - left; var letterbox new Mat(); Cv2.CopyMakeBorder(resized, letterbox, top, bottom, left, right, BorderTypes.Constant, new Scalar(114, 114, 114)); var rgb new Mat(); Cv2.CvtColor(letterbox, rgb, ColorConversionCodes.BGR2RGB);这段代码里要注意两个点。第一CopyMakeBorder 的 padding 必须左右或上下对称如果不对称后面坐标回算公式会多一个偏移量容易出错。第二Ultralytics 训练时用的是 RGB 通道顺序C# 端读图得到的是 BGR必须做一次转换否则模型看到的颜色通道是反的检测精度会下降但不会完全失效这种问题很难排查。接下来把图像数据填入 float 数组。这里涉及一个 C# 工程师容易忽视的细节模型期望的输入张量布局是 NCHW即先按通道维连续存储再是高度和宽度。OpenCvSharp 的 Mat 内存布局是 HWC不能直接塞给模型。float[] inputData new float[3 * modelSize * modelSize]; int index 0; for (int c 0; c 3; c) { for (int y 0; y modelSize; y) { for (int x 0; x modelSize; x) { var pixel rgb.AtVec3b(y, x); inputData[index] pixel[c] / 255f; } } }Pixel[c] 按照 RGB 顺序取值除以 255 是 YOLOv8 训练时采用的归一化方式。很多网上流传的代码先除以 255 再做 HWC 转 CHW容易把索引搞乱。这里直接用双层循环逐像素读取再按通道填充虽然速度略慢但逻辑一目了然。追求性能的话可以用指针操作或者先提取 Mat 的连续数据再重排但要注意 Mat 如果不是连续的直接data指针会读到脏数据。3.2 创建 OpenVINO 输入张量并执行推理OpenVINO 的 C# 绑定有多个版本接口方法命名略有差异。下面代码按常见的 NuGet 包写法给出你在自己工程里以实际包为准核心步骤是读模型、编译、创建推理请求、设置输入、执行推理。using OpenVinoSharp; var core new Core(); var model core.ReadModel(yolov8n-obb_openvino_model/yolov8n-obb.xml); var compiled core.CompileModel(model, CPU); var infer compiled.CreateInferRequest(); var inputTensor infer.GetInputTensor(0); inputTensor.SetData(inputData); infer.Infer(); var outputTensor infer.GetOutputTensor(0); float[] outputData outputTensor.GetDatafloat();这段代码里CompileModel 的第二个参数是设备名称常见值是 CPU如果你的目标机器有 Intel 核显可以试 GPU但要注意核显驱动和 OpenVINO 版本的兼容性。GetInputTensor(0) 表示拿第一个输入节点如果之前用 Python 检查过输入节点只有一个这里就固定写 0。SetData 会把 float 数组整体拷贝到张量内部不需要手动管理内存。推理完成后outputData 就是包含全部 8400 个候选框参数的线性数组。这个数组的长度应该是 7 乘以 8400乘以 1 再乘以 batch size。拿到数组后不要急着遍历先确认输出张量的形状再看下面一节怎么正确解析。3.3 解析输出通道优先布局下拆出 cx、cy、w、h、angle以最常见[1, 7, 8400]的输出举例。这段代码要解决的问题是从一维数组中按照通道优先的内存布局把每个候选框的 5 个旋转参数和类别置信度拆出来。int numCandidates 8400; int numClasses (outputData.Length / numCandidates) - 5; int channelStride numCandidates; var boxes new Listfloat[](); var scores new Listfloat(); var classIds new Listint(); for (int i 0; i numCandidates; i) { float cx outputData[i]; // 通道 0 float cy outputData[channelStride i]; // 通道 1 float w outputData[2 * channelStride i]; float h outputData[3 * channelStride i]; float angle outputData[4 * channelStride i]; float maxScore 0f; int bestClass -1; for (int c 0; c numClasses; c) { float score outputData[(5 c) * channelStride i]; if (score maxScore) { maxScore score; bestClass c; } } if (maxScore 0.25f) continue; boxes.Add(new float[] { cx, cy, w, h, angle }); scores.Add(maxScore); classIds.Add(bestClass); }关键在 channelStride 上。通道优先布局意味着第一个通道的 8400 个值连续排在数组开头第二个通道的 8400 个值紧跟其后所以访问第 c 个通道的第 i 个候选框下标是c * 8400 i。如果你的模型导出来是[1, 8400, 7]同样的数据布局完全不同需要把访问方式改成i * 7 c。判断方式是看输出张量的形状或者直接在 C# 里打印 outputTensor.Shape 确认。这里的 0.25 是置信度阈值可以在后续调参但代码里先写死保证解析逻辑能跑通。这套解析代码的精髓在于不依赖任何 OBB 专用库完全靠数组下标手动拆解。原因在于 C# 生态里针对旋转框的库很少而且每个 Ultralytics 版本的输出布局都可能变自己写解析逻辑反而最好维护。4. 旋转框后处理坐标回算、NMS 参数与避坑清单4.1 把模型坐标还原回原图scale 与 pad 的回算公式模型输出的 cx、cy、w、h 是相对于输入图像 640x640含 letterbox padding的归一化坐标需要还原到原始图像尺寸。还原公式和预处理时的 scale、pad 一一对应一个都不能错float originalCx (cx - left) / scale; float originalCy (cy - top) / scale; float originalW w / scale; float originalH h / scale; float angleDeg angle * 180f / (float)Math.PI;left 和 top 是预处理时 CopyMakeBorder 填充的像素数scale 是等比缩放系数。注意 padding 不对称时公式里的 left 和 top 必须分别使用各自的值不能混用。不少人在这一步翻车原因是预处理时计算 padding 用的整数除法而回算时忘记了 top 和 left 是实际填充值。angle 输出是弧度制转换成角度用于画框。但这里有一个让人头疼的地方Ultralytics OBB 模型预测的角度定义是“长边与 X 轴正方向的夹角”弧度范围在 -π/2 到 π/2 之间而 OpenCV 的 RotatedRect 使用“顺时针为正、范围 0 到 90 度”两者直接转换经常差 90 度或正负相反。标准做法是先用一张单目标图片对比验证确认转换规则后再统一封装。4.2 三个必调参数conf、IoU 与旋转 IoU 的选择旋转框后处理里三个参数直接决定检测效果。第一个是置信度阈值建议设在 0.25 到 0.5 之间遥感目标通常较小且密集阈值太高容易漏检。第二个是 NMS 的 IoU 阈值旋转框之间即使中心点接近真实交叠可能很小所以 IoU 阈值可以比水平框检测更宽松0.5 到 0.7 比较常见。第三个是 NMS 的类型选择。参数建议范围说明conf_thres0.25 ~ 0.5低于该值的候选框直接丢弃iou_thres0.5 ~ 0.7旋转框的 NMS 阈值NMS 方式旋转 IoU水平框 NMS 会误杀相邻的斜框关于旋转 IoU最简单的做法是给每个旋转框算出四个顶点再计算两个四边形相交面积与并集面积的比值。用 OpenCvSharp 的 RotatedRect 可以拿到四个顶点但 C# 生态里没有直接的多边形相交面积函数。一个省事的替代方案是在目标比较稀疏的场景下用旋转框的最小外接水平矩形做近似 IoU但在密集场景下必须用真正的旋转 IoU否则两个并排的斜框会被误判为交叠而互相抑制。4.3 避坑清单5 个高频翻车点踩坑一输出全是 0 或 NaN。现象是 C# 端推理结果全为 0或者偶尔出现 NaN。原因通常是输入张量数据没按 NCHW 排列或者归一化时忘了除以 255。解决方法是先打印 inputData 前几个值和 Python 端预处理后的值对比确认输入数据一致再往下排查。踩坑二输出形状是[1, 8400, 7]但代码按[1, 7, 8400]解析。现象是检测框坐标完全错乱有的框在图像外。原因是 Ultralytics 不同版本导出 OpenVINO 模型时输出布局不同。解决方法是先用 2.3 节的 Python 脚本确认输出形状再选择对应的解析方式。C# 端建议预留一个静态变量来控制布局模式。踩坑三画出来的旋转框方向不对、长边和短边颠倒。现象是框确实旋转了但和目标方向差 90 度。原因是模型输出的角度定义与 OpenCV RotatedRect 不一致尤其涉及弧度转角度和正方向时容易出问题。解决方法是先拿一张带标注的图对比再把角度加上 90 度的倍数哪个方向对就封装哪个。踩坑四密集目标大量漏检。现象是置信度阈值调低后框变多但好的框不见了。原因是用水平框 NMS 处理旋转框相邻斜框之间被错误抑制。解决办法是换成旋转 IoU 的 NMS至少也应按四顶点多边形算交叠面积。踩坑五OpenVINO C# 绑定 API 名称编译不过。现象是从网上抄的代码和自己下载的 NuGet 包方法对不上。原因是 OpenVINO 官方 C# 绑定在 2023 年后经历过多次 API 重构旧代码不能直接用。解决方式是下载包时看其附带的 example 代码以你当前版本的实际方法名为准不要硬套旧博客。5. 画框可视化与结果对齐最后 10 分钟的验证技巧5.1 用 OpenCvSharp 画出旋转框解析和坐标回算都完成之后画框是最直观的验证方式。OpenCvSharp 内置的 RotatedRect 可以直接用中心点、尺寸、角度构造不用自己去算四个顶点static void DrawRotatedBox(Mat img, float cx, float cy, float w, float h, float angleDeg) { var rect new RotatedRect( new Point2f(cx, cy), new Size2f(w, h), angleDeg); Point2f[] pts rect.Points(); for (int i 0; i 4; i) { Cv2.Line(img, (Point)pts[i], (Point)pts[(i 1) % 4], new Scalar(0, 255, 0), 2); } }画框时注意 RotatedRect 的 angle 单位是度传入前确认已经转换。OpenCvSharp 的 RotatedRect.Points() 返回的四个顶点是按逆时针排列的直接用顺序连线就能得到闭合框不需要自己使用 orderCorners 排序。这里有个小经验先用单通道灰度图做测试画框结果叠加在原图上再人工判断角度是否与目标朝向一致。5.2 和 Python 推理结果对齐把“玄学”变成回归测试写完 C# 端代码后如果检测结果和预期有偏差不要急着调参数。先拿同一张测试图用 Ultrlytics 的 Python 推理脚本跑一遍记录输出框的坐标、角度、置信度再把 C# 端的输出打印出来逐项对比。这个步骤花费十分钟能帮你快速定位问题是出在模型转换还是 C# 解析。我自己做这个方案时最大的教训就是直接跳过对齐环节结果折腾了一下午发现角度符号反了 90 度。后来固定下来一个习惯每换一个模型文件先在 Python 端跑一次基线再在 C# 端跑同样图片比较前三个置信度最高的框的坐标误差误差超过一个像素就检查预处理和坐标回算。这个习惯帮助我在后续换了多个 OBB 模型时都快速定位问题希望帮到你。本文还有配套的精品资源点击获取

相关新闻

AnyPS5 技术拆解:输入设备泛化与协议桥接实战

AnyPS5 技术拆解:输入设备泛化与协议桥接实战

1. 从“AnyPS5”这个名字说起:它到底想解决什么问题第一次看到“AnyPS5”这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕 PlayStation 5 生态做“泛化接入”或“跨端能力扩展”的项目。为什么这么判断?因为“Any”这个…

2026/10/11 7:02:35 阅读更多 →
DLSS5与多帧插值协同实现144Hz无闪帧生成

DLSS5与多帧插值协同实现144Hz无闪帧生成

1. 这个“6倍帧生成DLSS5”到底在解决什么真实痛点?先说结论:这不是营销噱头,而是针对《原神》这类高画质、高动态场景下,GPU瓶颈与显示器刷新率不匹配这一长期被忽视的底层矛盾,所给出的一套可落地的工程化解法。我最…

2026/10/11 7:02:35 阅读更多 →
《执行控制工程》作者手记 04|当所有条件都已成立,谁真正决定现实

《执行控制工程》作者手记 04|当所有条件都已成立,谁真正决定现实

本文是《执行控制工程》(Execution Control Engineering)的作者手记。 它不是书籍正文的摘要或重写,而是围绕本章问题、工程背景与写作之后的进一步思考。 在过去的软件工程实践中,我们已经建立了许多用于管理权力的机制。身份认证…

2026/10/11 7:02:35 阅读更多 →

最新新闻

OpenClaw接入飞书/钉钉/QQ/企微:四平台IM机器人配置指南与排坑实战

OpenClaw接入飞书/钉钉/QQ/企微:四平台IM机器人配置指南与排坑实战

Openclaw记录写到第二篇。上一篇把基础服务部署完,Openclaw跑起来之后,我干的第一件事就是把手机里的几个IM全接了上去——飞书、钉钉、QQ、企业微信,一个都没落下。这个开源网关服务说白了就是把大模型能力接入各种聊天软件,让你…

2026/10/11 7:49:01 阅读更多 →
nanoMuse: An Open-Source Personal Agent for Every Device You Own——一个属于你所有设备的开源个人智能体

nanoMuse: An Open-Source Personal Agent for Every Device You Own——一个属于你所有设备的开源个人智能体

文章的核心是提出并实现一个开源、个人拥有、可本地运行的“个人智能体”,作为Meta闭源产品Muse的开放对等物。以下是对其主要研究内容的全面总结: 一、研究背景与问题 2026年9月,Meta发布Muse,标志着“个人智能体”产品形态的成…

2026/10/11 7:49:01 阅读更多 →
主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式

主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式

主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式:厂商一键收集诊断信息命令解释Cisco(思科)show tech-support该命令将生成包括所有路由器和交换机配置、接口和协议状态等在内的详细技术支持信息。Juniper Networks&a…

2026/10/11 7:49:01 阅读更多 →
VS2010 MFC Socket实战:CAsyncSocket客户端与服务器端完整实现

VS2010 MFC Socket实战:CAsyncSocket客户端与服务器端完整实现

简介:基于 VS2010 的 MFC Socket 编程示例压缩包,包含 SocketTest_Client 与 SocketTest_Server 两个完整工程,面向学习 Windows 网络编程的初学者,以及需要快速搭建客户端/服务器通信框架的开发者。压缩包共 48 个文件&#xff0…

2026/10/11 7:49:01 阅读更多 →
二、Spring AI Alibaba · ChatModel

二、Spring AI Alibaba · ChatModel

整理时间:2026-10-09 适用版本:Spring AI 1.1.0 / Spring AI Alibaba 1.1.2.x(spring-ai-alibaba-starter-dashscope)一、整体定位 ChatModel API 的作用:把"发一段自然语言给模型、拿回一段补全文本"这件事…

2026/10/11 7:49:01 阅读更多 →
基于SSM框架的体育器材管理系统设计与实现:从数据库到权限控制全解析

基于SSM框架的体育器材管理系统设计与实现:从数据库到权限控制全解析

1. 项目概述与需求拆解“体育器材管理系统”这个题目,在Java相关的毕业设计和课程设计选题里,算是一个经久不衰的经典款。我前前后后帮人看过不少套这个题目的代码,也回答过很多“SSM怎么整合”“借还流程怎么写”这类问题。选它的人理由其实…

2026/10/11 7:48:00 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23: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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →