OpenCV 5 DNN引擎升级:ONNX模型支持与GPU推理优化实践
OpenCV 5 这次更新可以说是计算机视觉领域的一个重要里程碑作为自 2018 年以来的最大版本升级它带来了全新的 DNN 引擎架构在模型推理性能、硬件支持范围和开发便捷性方面都有显著提升。对于需要在实际项目中部署深度学习模型的开发者来说这次更新意味着更高效的推理速度和更低的部署门槛。新版本最值得关注的是 DNN 模块的全面优化特别是在 ONNX 模型支持、GPU 推理加速和多后端兼容性方面的改进。从测试情况看OpenCV 5 的 DNN 引擎现在能够更好地处理现代视觉模型包括 YOLO 系列、分割网络等复杂架构同时在 CPU 和 GPU 上的性能表现都有明显提升。1. 核心能力速览能力项说明项目类型计算机视觉库核心模块升级主要功能深度学习模型推理、图像处理、视频分析DNN 引擎改进ONNX 模型支持增强、GPU 推理优化、多后端兼容硬件要求支持 CPU 推理GPU 需要 CUDA 环境显存占用根据模型大小和输入分辨率动态变化支持平台Windows、Linux、macOS启动方式代码集成、命令行工具API 支持C、Python 接口批量任务支持批量图像处理适合场景边缘设备部署、实时推理、传统视觉项目升级2. 适用场景与使用边界OpenCV 5 的 DNN 模块特别适合需要在资源受限环境中部署深度学习模型的场景。比如嵌入式设备、边缘计算节点或者对延迟要求严格的实时应用。与专门的深度学习框架相比OpenCV 的优势在于轻量级和易于集成适合已经使用 OpenCV 进行传统图像处理的项目平滑升级。对于 YOLO 系列模型的使用OpenCV 5 提供了更稳定的 ONNX 模型支持。从网络反馈看之前版本在 GPU 推理时可能存在输出结果异常的问题新版本在这方面做了重点优化。但需要注意的是OpenCV 主要专注于模型推理环节模型训练仍然需要依赖 PyTorch、TensorFlow 等框架。在合规使用方面部署涉及人脸、人体等敏感信息的模型时必须确保有合法的数据授权和隐私保护措施。商业项目中使用的模型需要确认许可证合规性。3. 环境准备与前置条件在开始测试 OpenCV 5 的新 DNN 引擎前需要确保环境满足以下要求操作系统支持Windows 10/11Visual Studio 2019 或更高版本Ubuntu 18.04 / CentOS 7macOS 10.14Python 环境如果使用 Python 接口Python 3.7-3.11pip 20.0GPU 支持可选但推荐NVIDIA GPUCompute Capability 3.5CUDA 11.0-12.0cuDNN 8.0磁盘空间基础安装500MB-1GB包含完整贡献模块2-3GB依赖检查清单# 检查 CUDA 是否可用 nvidia-smi nvcc --version # 检查 Python 环境 python --version pip --version4. 安装部署与启动方式OpenCV 5 提供了多种安装方式根据具体需求选择最合适的方案。方法一pip 快速安装推荐初学者# 安装基础版本 pip install opencv-python5.0.0 # 安装包含贡献模块的版本 pip install opencv-contrib-python5.0.0方法二源码编译需要自定义配置# 下载源码 git clone https://github.com/opencv/opencv.git cd opencv git checkout 5.0.0 # 创建构建目录 mkdir build cd build # 配置编译选项 cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH../../opencv_contrib/modules \ -D WITH_CUDAON \ -D ENABLE_FAST_MATHON \ -D CUDA_FAST_MATHON \ -D WITH_CUDNNON \ -D OPENCV_DNN_CUDAON \ -D WITH_OPENMPON \ -D BUILD_EXAMPLESON .. # 编译安装 make -j$(nproc) sudo make install方法三Docker 方式适合测试和部署FROM ubuntu:20.04 RUN apt-get update apt-get install -y \ python3-pip \ libopencv-dev RUN pip3 install opencv-python5.0.0 # 验证安装 CMD [python3, -c, import cv2; print(cv2.__version__)]5. 功能测试与效果验证5.1 基础环境验证安装完成后首先验证 OpenCV 5 是否正确安装以及 DNN 模块是否可用import cv2 import numpy as np print(fOpenCV 版本: {cv2.__version__}) print(fDNN 模块可用: {hasattr(cv2, dnn)}) # 检查 GPU 支持 print(fCUDA 设备数量: {cv2.cuda.getCudaEnabledDeviceCount()}) # 测试基础功能 net cv2.dnn.readNetFromONNX(path/to/model.onnx) print(f网络加载成功: {not net.empty()})5.2 ONNX 模型加载测试使用 YOLOv8 模型测试新的 ONNX 支持能力def test_onnx_loading(): # 从 Ultralytics 导出 ONNX 模型 # from ultralytics import YOLO # model YOLO(yolov8n.pt) # model.export(formatonnx) # 加载 ONNX 模型 net cv2.dnn.readNetFromONNX(yolov8n.onnx) # 设置推理后端 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) # 或者使用 GPU # net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) # net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) return not net.empty() print(fONNX 模型加载测试: {test_onnx_loading()})5.3 CPU 与 GPU 推理对比测试基于网络反馈的问题重点测试 GPU 推理的正确性def compare_cpu_gpu_inference(image_path, model_path): # 读取图像和模型 image cv2.imread(image_path) net cv2.dnn.readNetFromONNX(model_path) # 准备输入 blob cv2.dnn.blobFromImage(image, 1/255.0, (640, 640), swapRBTrue) # CPU 推理 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) net.setInput(blob) cpu_output net.forward() # GPU 推理 if cv2.cuda.getCudaEnabledDeviceCount() 0: net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) net.setInput(blob) gpu_output net.forward() # 比较结果 diff np.abs(cpu_output - gpu_output) print(fCPU/GPU 输出差异: {np.max(diff)}) return cpu_output, gpu_output else: print(GPU 不可用仅返回 CPU 结果) return cpu_output, None # 运行测试 cpu_result, gpu_result compare_cpu_gpu_inference(test.jpg, yolov8n.onnx)5.4 批量处理性能测试测试 OpenCV 5 在批量任务中的表现def batch_inference_test(image_paths, model_path, batch_size4): net cv2.dnn.readNetFromONNX(model_path) net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) batches [image_paths[i:ibatch_size] for i in range(0, len(image_paths), batch_size)] results [] for batch in batches: batch_blobs [] for img_path in batch: image cv2.imread(img_path) blob cv2.dnn.blobFromImage(image, 1/255.0, (640, 640), swapRBTrue) batch_blobs.append(blob) # 批量推理 batch_input np.concatenate(batch_blobs, axis0) net.setInput(batch_input) batch_output net.forward() results.append(batch_output) return results6. 接口 API 与批量任务OpenCV 5 的 DNN 模块提供了完整的 C 和 Python API便于集成到各种应用中。6.1 Python API 调用示例class OpenCVDNNInference: def __init__(self, model_path, backendcpu): self.net cv2.dnn.readNetFromONNX(model_path) if backend cuda and cv2.cuda.getCudaEnabledDeviceCount() 0: self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) else: self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) def preprocess(self, image): return cv2.dnn.blobFromImage(image, 1/255.0, (640, 640), swapRBTrue) def inference(self, image): blob self.preprocess(image) self.net.setInput(blob) return self.net.forward() def batch_inference(self, images): blobs [self.preprocess(img) for img in images] batch_input np.concatenate(blobs, axis0) self.net.setInput(batch_input) return self.net.forward() # 使用示例 detector OpenCVDNNInference(yolov8n.onnx, backendcpu) result detector.inference(cv2.imread(test.jpg))6.2 C API 调用示例#include opencv2/opencv.hpp #include opencv2/dnn.hpp class OpenCVDNNWrapper { public: bool loadModel(const std::string modelPath) { net cv::dnn::readNetFromONNX(modelPath); if (net.empty()) { return false; } net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); return true; } cv::Mat inference(const cv::Mat image) { cv::Mat blob cv::dnn::blobFromImage(image, 1/255.0, cv::Size(640, 640), cv::Scalar(0, 0, 0), true, false); net.setInput(blob); return net.forward(); } private: cv::dnn::Net net; };6.3 批量任务队列设计对于生产环境的批量处理需求可以设计任务队列import queue import threading from concurrent.futures import ThreadPoolExecutor class BatchInferenceQueue: def __init__(self, model_path, batch_size8, max_queue_size100): self.model OpenCVDNNInference(model_path) self.batch_size batch_size self.task_queue queue.Queue(maxsizemax_queue_size) self.result_dict {} self.lock threading.Lock() def add_task(self, task_id, image): self.task_queue.put((task_id, image)) def process_batch(self): while True: batch [] task_ids [] # 收集一个批量的任务 for _ in range(self.batch_size): try: task_id, image self.task_queue.get(timeout1) batch.append(image) task_ids.append(task_id) except queue.Empty: break if batch: # 批量推理 results self.model.batch_inference(batch) # 存储结果 with self.lock: for i, task_id in enumerate(task_ids): self.result_dict[task_id] results[i] def start_processing(self, num_workers2): with ThreadPoolExecutor(max_workersnum_workers) as executor: for _ in range(num_workers): executor.submit(self.process_batch)7. 资源占用与性能观察OpenCV 5 在资源优化方面做了大量工作以下是性能观察的关键点7.1 显存占用监控import psutil import GPUtil def monitor_resources(): # CPU 使用率 cpu_percent psutil.cpu_percent(interval1) # 内存使用 memory psutil.virtual_memory() # GPU 使用情况如果可用 gpus GPUtil.getGPUs() gpu_info [] for gpu in gpus: gpu_info.append({ id: gpu.id, load: gpu.load, memoryUsed: gpu.memoryUsed, memoryTotal: gpu.memoryTotal }) return { cpu_percent: cpu_percent, memory_percent: memory.percent, gpus: gpu_info } # 在推理过程中定期监控 def inference_with_monitoring(image, model, interval1): import time start_time time.time() result model.inference(image) end_time time.time() # 记录资源使用 resources monitor_resources() inference_time end_time - start_time print(f推理时间: {inference_time:.3f}s) print(fCPU 使用率: {resources[cpu_percent]}%) print(f内存使用率: {resources[memory_percent]}%) if resources[gpus]: for gpu in resources[gpus]: print(fGPU {gpu[id]}: 负载 {gpu[load]*100:.1f}%, f显存 {gpu[memoryUsed]}/{gpu[memoryTotal]}MB) return result7.2 性能优化建议基于测试经验提供以下性能优化建议模型优化使用 ONNX 模型的简化版本export with simplifyTrue考虑模型量化FP16 或 INT8以降低显存占用根据实际需求选择合适大小的模型推理参数调优# 设置合适的推理参数 net cv2.dnn.readNetFromONNX(model.onnx) # 对于实时应用可以降低精度要求 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) # 启用快速数学运算如果支持 net.enableWinograd(True)批量大小调整根据可用显存调整批量大小测试不同批量大小下的吞吐量考虑使用动态批量处理8. 常见问题与排查方法问题现象可能原因排查方式解决方案ONNX 模型加载失败模型文件损坏或版本不兼容检查模型文件大小和格式重新导出模型确保 ONNX 版本兼容GPU 推理结果异常后端配置问题或驱动不兼容对比 CPU/GPU 推理结果更新显卡驱动检查 CUDA 版本匹配显存不足模型太大或批量设置过大监控显存使用情况减小批量大小使用模型量化推理速度慢后端配置不当或硬件瓶颈检查后端设置和硬件使用率切换到 GPU 推理优化模型结构端口冲突如果使用网络服务端口被其他进程占用检查端口占用情况更换端口或结束冲突进程8.1 详细排查步骤ONNX 模型加载问题排查def debug_onnx_loading(model_path): import onnx try: # 检查 ONNX 模型是否有效 model onnx.load(model_path) onnx.checker.check_model(model) print(ONNX 模型验证通过) # 检查输入输出维度 for input in model.graph.input: print(f输入: {input.name}, 形状: {input.type.tensor_type.shape}) for output in model.graph.output: print(f输出: {output.name}, 形状: {output.type.tensor_type.shape}) except Exception as e: print(fONNX 模型检查失败: {e})GPU 推理问题排查def debug_gpu_inference(): # 检查 CUDA 可用性 print(fCUDA 设备数: {cv2.cuda.getCudaEnabledDeviceCount()}) if cv2.cuda.getCudaEnabledDeviceCount() 0: # 检查每个设备的信息 for i in range(cv2.cuda.getCudaEnabledDeviceCount()): device cv2.cuda.getDevice(i) print(f设备 {i}: {device.name()}) # 测试简单的 GPU 操作 try: gpu_mat cv2.cuda_GpuMat() cpu_mat cv2.imread(test.jpg) gpu_mat.upload(cpu_mat) print(GPU 内存操作测试通过) except Exception as e: print(fGPU 操作测试失败: {e})9. 最佳实践与使用建议基于 OpenCV 5 DNN 模块的实际使用经验总结以下最佳实践模型准备阶段使用最新版本的模型导出工具在导出 ONNX 模型时启用简化选项测试模型在不同硬件上的兼容性# 模型导出最佳实践 from ultralytics import YOLO model YOLO(yolov8n.pt) # 启用简化优化模型结构 model.export(formatonnx, simplifyTrue, dynamicTrue)部署配置优化根据目标硬件选择合适的前后端配置设置合理的批量处理大小实现优雅降级GPU失败时自动切换到CPUdef create_robust_inference_engine(model_path): net cv2.dnn.readNetFromONNX(model_path) # 尝试 GPU失败时回退到 CPU try: if cv2.cuda.getCudaEnabledDeviceCount() 0: net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) print(使用 GPU 推理) else: raise Exception(GPU 不可用) except: net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) print(使用 CPU 推理) return net生产环境建议实现完整的错误处理和日志记录添加资源监控和告警机制定期更新 OpenCV 版本以获取性能改进import logging class ProductionInferenceService: def __init__(self, model_path): self.logger logging.getLogger(__name__) self.model self._load_model(model_path) def _load_model(self, model_path): try: net cv2.dnn.readNetFromONNX(model_path) # 生产环境配置 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) self.logger.info(模型加载成功) return net except Exception as e: self.logger.error(f模型加载失败: {e}) raise def inference(self, image): try: start_time time.time() result self.model.inference(image) inference_time time.time() - start_time self.logger.info(f推理完成耗时: {inference_time:.3f}s) return result except Exception as e: self.logger.error(f推理失败: {e}) return NoneOpenCV 5 的 DNN 引擎升级为深度学习模型部署提供了更强大的工具链特别是在边缘计算和传统视觉项目升级场景中表现突出。通过合理的配置和优化可以在保持易用性的同时获得显著的性能提升。建议在实际项目中从小规模测试开始逐步验证功能完整性和性能表现确保满足具体应用需求。

相关新闻

逐光标讯:专为中小投标团队打造的轻量化免费全域标讯平台

逐光标讯:专为中小投标团队打造的轻量化免费全域标讯平台

2026 年招投标数字化赛道快速扩容,各类标讯服务工具层出不穷,但大部分产品存在明显门槛壁垒:要么年费定价高昂,中小团队难以长期承担;要么功能繁杂冗余,大量企业用不上的重型模块拉高学习成本;还…

2026/10/14 15:00:10 阅读更多 →
Midjourney实战:技术博客配图生成的提示词工程与风格控制

Midjourney实战:技术博客配图生成的提示词工程与风格控制

Midjourney实战:技术博客配图生成的提示词工程与风格控制 技术配图的核心矛盾:专业感与个性化的平衡 技术博客需要配图。但配图的质量和风格一致性,直接影响读者对内容专业度的判断。 早期我用的配图方案是: 截图:代码…

2026/10/15 20:11:57 阅读更多 →
以太网PHY寄存器配置:从硬件接口到软件驱动的全景解析

以太网PHY寄存器配置:从硬件接口到软件驱动的全景解析

1. 以太网PHY寄存器配置:从硬件接口到软件驱动的全景解析 搞嵌入式网络开发,尤其是用到像TI Tiva™这类带MACPHY的微控制器,PHY寄存器的配置绝对是绕不开的坎。很多人觉得,现在都有成熟的驱动库了,直接调API不就行了&a…

2026/10/16 18:53:00 阅读更多 →

最新新闻

MATLAB实现Elman神经网络电力负荷预测:时序建模与工程实践

MATLAB实现Elman神经网络电力负荷预测:时序建模与工程实践

1. 项目概述与核心需求解析电力负荷预测这个题目,在电力系统里是老生常谈,但真正把它做好的人不多。我接触过不少相关项目,也见过很多人拿历史负荷数据直接塞进神经网络里就跑,结果训练集误差看着挺漂亮,一到验证集就原…

2026/10/17 12:54:09 阅读更多 →
帧同步原理与实现:从输入同步到确定性保障

帧同步原理与实现:从输入同步到确定性保障

/* 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 12:54:09 阅读更多 →
算法OJ作业Lecture(4):四重能力压力测试与破题心法

算法OJ作业Lecture(4):四重能力压力测试与破题心法

1. 这不是一节普通课,而是一次算法能力的“压力测试”“程序设计与算法 | (8) Lecture(4) OJ作业”——看到这个标题,很多刚接触算法训练的同学第一反应是:又到在线判题系统(OJ)交作业的时间了。但如果你真这么想&…

2026/10/17 12:54:09 阅读更多 →
North-Micro-Vision-Instruct-bf16 图像输入完全攻略:从本地图片到 URL 的多模态实战

North-Micro-Vision-Instruct-bf16 图像输入完全攻略:从本地图片到 URL 的多模态实战

【免费下载链接】North-Micro-Vision-Instruct-bf16 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/North-Micro-Vision-Instruct-bf16 点击查看 免费下载 North-Micro-Vision-Instruct-bf16 是一款面向 Apple Silicon 的多模态视觉语言模型&#xf…

2026/10/17 12:54:09 阅读更多 →
为什么你的小模型推理变慢了?SmolLM-Instruct_rai_1.8.0_medusa_1.0_npu 性能调优 10 个技巧

为什么你的小模型推理变慢了?SmolLM-Instruct_rai_1.8.0_medusa_1.0_npu 性能调优 10 个技巧

大模型基础模型 【免费下载链接】SmolLM-Instruct_rai_1.8.0_medusa_1.0_npu 项目地址: https://ai.gitcode.com/hf_mirrors/amd/SmolLM-Instruct_rai_1.8.0_medusa_1.0_npu 点击查看 免费下载 小模型推理明明应该飞快,为什么跑起来却越来越慢&#xff…

2026/10/17 12:54:09 阅读更多 →
Docker Harbor 安装配置全解析:从部署到运维的镜像治理实践

Docker Harbor 安装配置全解析:从部署到运维的镜像治理实践

做容器化落地的人迟早会碰到一个问题:镜像越来越多,靠 Docker 自带的 Registry 管不住权限,也管不住审计和复制。Docker Harbor安装配置就成了绕不开的一环——把 Harbor 部署起来,给团队一个靠谱的镜像中心。尤其是当团队规模超过…

2026/10/17 12:53:09 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →