首页/新闻资讯/正文详情

电力AI大赛数据包实战:从标注解析到YOLO训练与推理

发布时间:2026/9/25 1:43:11 来源:云帆数科 栏目:资讯中心
电力AI大赛数据包实战:从标注解析到YOLO训练与推理
简介这份资源是面向电气电子类竞赛参赛者与毕业设计学生的电力AI项目源码包聚焦“大航杯·智造扬中”电力AI大赛赛题适合具备Python编程与机器学习基础、希望参考完整竞赛实现思路的中高级学习者。压缩包共18个文件约835KB以6个Python脚本为核心涵盖数据切分、特征提取、模型构建与可视化等模块另含4个CSV数据表、2个XML配置、1个Shell运行脚本及README说明文档结构清晰便于按流程复现。目前已有44人学习下载。读者可从中获取电力负荷预测的完整代码框架、特征工程与模型训练细节、数据查看与结果输出脚本以及一键运行入口适合对照赛题复盘算法设计、理解数据处理与建模流程也可作为毕业设计或课程项目的参考实现帮助快速搭建可运行的电力AI实验环境。1. 电力AI大赛里的“智造扬中”一份电赛数据包能跑出什么2019年前后各类电力人工智能赛事密集出现“智造扬中”这个命题把赛场从通用视觉拉到了电力行业的真实场景里。很多做电赛控制类题目的同学第一次接触这类赛题时会懵给的不是一块板子、一个电机而是一堆带标签的电力设备图像和运行数据要求做缺陷识别、负荷预测或者表计读数。这份“大航杯”电力AI大赛的数据包本质上就是一套面向电力巡检与运维的脱敏数据集包含设备图像、标注文件和若干结构化字段。它适合两类人一类是打过电赛控制类、电源题想往AI方向迁移的在校生另一类是电力行业里想用现成数据验证检测或分类pipeline的工程师。核心问题只有一个——拿到压缩包之后怎么在本地把训练和推理跑通而不是卡在数据格式和标签对齐上。2. 先看清数据长什么样目录结构、标注格式与字段含义2.1 解压后先做一次目录测绘别急着写模型拿到一个陌生的竞赛数据包我一般不会立刻打开PyTorch写Dataset。先做目录测绘把文件数量、扩展名分布、层级深度摸清楚。这一步能避免后面出现“标签找不到图像”或者“类别数对不上”的翻车。# 统计目录下各扩展名文件数量快速判断数据构成 find . -type f | sed s/.*\.// | sort | uniq -c | sort -rn # 查看目录树前三级确认图像和标注是否分开放 find . -maxdepth 3 -type d | head -50 # 统计图像总数和标注文件数做对比 find . -type f \( -name *.jpg -o -name *.png -o -name *.jpeg \) | wc -l find . -type f \( -name *.xml -o -name *.json -o -name *.txt \) | wc -l逻辑说明第一条命令按扩展名聚合能一眼看出数据包里是图像为主还是表格为主。第二条限制深度防止目录太深刷屏。第三条和第四条做数量比对如果图像数和标注数差距超过5%基本可以判定有脏数据或者标注缺失后面必须写清洗逻辑。参数说明-maxdepth 3可以根据实际层级调整电力竞赛数据常见结构是train/images、train/annotations、test/images三层所以3够用。sed s/.*\.//提取最后一个点之后的内容对多后缀文件如.tar.gz会误判但竞赛数据里少见。2.2 标注格式决定你用什么训练框架电力AI大赛的数据标注常见三种Pascal VOC的XML、COCO的JSON、YOLO的TXT。不同格式直接决定你选YOLO系列还是Detectron2或者MMDetection。先抽一个标注文件看结构比读任何说明文档都快。import json, xml.etree.ElementTree as ET, os # 探测标注格式优先找json再找xml最后找txt ann_dir ./annotations sample None for f in os.listdir(ann_dir): if f.endswith(.json): with open(os.path.join(ann_dir, f), r, encodingutf-8) as fp: data json.load(fp) # COCO格式一定有images和annotations两个key print(COCO keys:, list(data.keys())[:10]) print(类别数:, len(data.get(categories, []))) sample coco break elif f.endswith(.xml): tree ET.parse(os.path.join(ann_dir, f)) root tree.getroot() # VOC格式根节点是annotation子节点有filename、object print(VOC root:, root.tag) print(目标数:, len(root.findall(object))) sample voc break print(判定格式:, sample)逻辑说明这段脚本按JSON→XML→TXT的优先级探测因为COCO JSON的信息最全能直接读出类别数和图像数。如果是VOC只能逐个XML解析。判定结果决定后续用pycocotools还是voc2yolo脚本做转换。参数说明data.get(categories, [])里的类别列表长度就是模型输出通道数必须和你的num_classes一致。VOC的root.findall(object)返回该图所有目标如果某张图返回0说明是负样本训练时要不要保留取决于赛题是否允许背景类。2.3 电力场景的类别不平衡是常态先统计再动手电力设备缺陷检测里正常样本远多于缺陷样本这是行业数据的固有特征。不做类别统计直接训练模型会倾向于全部预测为正常mAP看着不低但缺陷召回率极差。from collections import Counter import os, xml.etree.ElementTree as ET counter Counter() for f in os.listdir(./annotations): if not f.endswith(.xml): continue root ET.parse(os.path.join(./annotations, f)).getroot() for obj in root.findall(object): name obj.find(name).text.strip() counter[name] 1 for cls, cnt in counter.most_common(): print(f{cls}: {cnt}) # 计算不平衡比最大类/最小类超过10就要考虑重采样或focal loss max_c, min_c counter.most_common()[0][1], counter.most_common()[-1][1] print(不平衡比:, round(max_c / max(min_c, 1), 2))逻辑说明用Counter累计每个类别的目标框数量而不是图像数量因为一张图可能有多个目标。不平衡比超过10时常规CrossEntropy会让小类梯度被淹没需要引入Focal Loss或者对稀有类做过采样。参数说明most_common()返回按计数降序的列表[-1]取最小类。max(min_c, 1)防止除零。如果最小类计数为0说明标注里根本没出现要么是类别定义多余要么是数据划分出了问题。3. 从原始标注到可训练格式转换脚本与四个边界坑3.1 VOC转YOLO坐标归一化和类别映射如果探测结果是VOC XML而你想用YOLOv5/v8训练必须做格式转换。核心是把xmin,ymin,xmax,ymax转成归一化的cx,cy,w,h同时建立类别名到索引的映射。import os, xml.etree.ElementTree as ET classes [normal, insulator_broken, rust, foreign_object] # 按实际类别改 cls_map {name: i for i, name in enumerate(classes)} def voc_to_yolo(xml_path, img_w, img_h, out_path): root ET.parse(xml_path).getroot() lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in cls_map: continue # 跳过未定义类别避免索引越界 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界防止标注越界导致归一化后为负 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(img_w, xmax), min(img_h, ymax) cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))逻辑说明先做边界裁剪再归一化是因为电力巡检图像里偶尔出现标注框超出图像尺寸的情况不裁剪会得到负坐标或大于1的宽高YOLO训练时直接报错。类别映射用字典遇到未定义类别跳过而不是报错保证批量转换不中断。参数说明img_w, img_h必须从对应图像读取不能硬编码。:.6f保留六位小数YOLO官方推荐精度。如果某张图转换后lines为空说明该图所有目标都被跳过需要检查类别名是否写错。3.2 图像尺寸不一致时的统一策略电力设备图像来源多样手机拍摄、无人机巡检、固定摄像头分辨率从640到4000不等。YOLO训练时如果直接resize到640长宽比差异大的图会严重变形绝缘子被压扁后特征丢失。import cv2 def letterbox(img, target640, color(114, 114, 114)): h, w img.shape[:2] scale min(target / w, target / h) nw, nh int(w * scale), int(h * scale) resized cv2.resize(img, (nw, nh)) canvas np.full((target, target, 3), color, dtypenp.uint8) # 居中放置保持长宽比 top (target - nh) // 2 left (target - nw) // 2 canvas[top:topnh, left:leftnw] resized return canvas, scale, left, top逻辑说明letterbox用灰色填充到正方形保持原始长宽比。返回的scale, left, top用于把预测框映射回原图坐标推理阶段必须保留这三个值否则画出来的框位置全错。参数说明target640是YOLO常见输入尺寸可根据显存调整到416或320。color(114,114,114)是YOLO官方用的填充色训练和推理保持一致即可。如果赛题要求保持原始分辨率可以改用切图推理但那是另一个话题。3.3 训练集/验证集划分别按图像随机分按设备分这是电力AI竞赛里最容易踩的坑。如果同一台设备的多个角度图像被随机分到训练集和验证集验证集上的指标会虚高因为模型见过这台设备的其他角度。正确做法是按设备ID或拍摄批次划分。import os, random from collections import defaultdict # 假设文件名包含设备ID如 deviceA_001.jpg device_imgs defaultdict(list) for f in os.listdir(./images): device_id f.split(_)[0] device_imgs[device_id].append(f) devices list(device_imgs.keys()) random.seed(42) random.shuffle(devices) split int(len(devices) * 0.8) train_devices set(devices[:split]) val_devices set(devices[split:]) train_files [f for d in train_devices for f in device_imgs[d]] val_files [f for d in val_devices for f in device_imgs[d]] print(训练图像:, len(train_files), 验证图像:, len(val_files))逻辑说明按设备ID分组后再划分保证同一设备的所有图像只出现在一个集合里。random.seed(42)固定随机种子保证每次划分一致方便复现。参数说明split int(len(devices) * 0.8)是常见8:2划分。如果设备总数少于20建议用5折交叉验证而不是单次划分否则验证集太小指标波动大。文件名里的设备ID提取规则要根据实际命名调整split(_)[0]只是示例。3.4 生成训练配置文件data.yaml的三个必填项YOLO训练需要一个yaml描述数据路径和类别。三个必填项写错任何一个都会导致训练启动失败或类别错乱。# data.yaml path: /home/user/power_ai_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对path的训练图像目录 val: images/val # 相对path的验证图像目录 nc: 4 # 类别数必须和classes长度一致 names: [normal, insulator_broken, rust, foreign_object]逻辑说明path用绝对路径避免相对路径解析歧义。train和val是相对path的路径YOLO会自动拼接。nc和names长度必须一致否则训练时类别索引越界。参数说明如果标签文件和图像不在同一目录YOLO默认在图像路径里把images替换成labels找标签。所以目录结构最好是images/train和labels/train平行。nc改了之后模型头部的输出通道会自动适配不需要手动改网络结构。4. 训练与推理跑通最小命令、参数含义与结果验证4.1 用YOLOv8跑通第一个baseline环境装好之后第一条训练命令不要加任何花哨参数先确认pipeline能跑通。# 安装ultralytics注意版本兼容 pip install ultralytics8.0.200 # 最小训练命令50轮先看趋势 yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs50 \ imgsz640 \ batch16 \ device0 \ projectruns/power_ai \ namebaseline逻辑说明modelyolov8n.pt用预训练权重电力数据量通常不大从头训练容易过拟合。epochs50先跑一轮看loss曲线确认没有报错再加大。project和name指定输出目录方便对比不同实验。参数说明batch16根据显存调整8G显存跑640尺寸大概能到16不够就降到8。device0指定第一块GPUCPU训练把device改成cpu但速度极慢。imgsz640要和data.yaml里的letterbox尺寸一致。4.2 看loss曲线判断是否值得继续训练启动后重点看三个指标box_loss、cls_loss、mAP50。box_loss下降说明定位在收敛cls_loss下降说明分类在收敛。如果cls_loss震荡不降大概率是类别不平衡或者学习率太大。# 训练结束后用tensorboard看曲线 tensorboard --logdir runs/power_ai # 或者直接看results.csv column -s, -t runs/power_ai/baseline/results.csv | head -20逻辑说明results.csv每轮一行包含所有指标。用column格式化后肉眼扫一遍比写脚本快。重点看mAP50是否在后期还在涨如果连续10轮不涨就可以停了。参数说明--logdir指向训练输出目录。如果没装tensorboard直接看csv也行。head -20只看前20行确认训练正常启动。4.3 推理验证单图和批量两种方式训练完必须做推理验证不能只看验证集指标。单图推理能直观看到框的位置和置信度批量推理能统计整体表现。# 单图推理保存结果图 yolo detect predict \ modelruns/power_ai/baseline/weights/best.pt \ sourcetest_images/deviceA_001.jpg \ conf0.25 \ saveTrue # 批量推理整个目录 yolo detect predict \ modelruns/power_ai/baseline/weights/best.pt \ sourcetest_images/ \ conf0.25 \ saveTrue \ save_txtTrue逻辑说明conf0.25是置信度阈值低于此值的框不输出。电力缺陷检测里漏检比误检代价高可以适当降低到0.15。save_txtTrue输出YOLO格式的预测结果方便后续做mAP计算。参数说明best.pt是验证集上表现最好的权重last.pt是最后一轮。如果验证集划分合理用best.pt。source可以是单文件、目录或视频。批量推理时输出目录结构和输入一致。4.4 用混淆矩阵定位类别混淆YOLO训练完会自动生成混淆矩阵在runs/power_ai/baseline/下。重点看对角线以外的值如果rust大量被预测成normal说明这两个类在特征空间上太近。import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay # 假设已有真实标签和预测标签列表 y_true [0, 1, 2, 3, 0, 1, 2, 3] # 示例 y_pred [0, 1, 2, 2, 0, 1, 3, 3] cm confusion_matrix(y_true, y_pred) disp ConfusionMatrixDisplay(cm, display_labels[normal, broken, rust, foreign]) disp.plot(cmapBlues) plt.savefig(confusion_matrix.png, dpi150)逻辑说明混淆矩阵的行是真实类别列是预测类别。对角线是正确预测非对角线是混淆。如果某个类别的召回率低于0.5需要针对性补充该类样本或调整损失函数权重。参数说明display_labels顺序必须和类别索引一致。cmapBlues颜色越深表示数量越多。保存dpi建议150以上方便报告里用。5. 避坑与排查电力AI竞赛数据训练的五个血泪教训5.1 现象训练loss正常下降但mAP始终为0原因标签文件路径不对YOLO找不到标签把所有样本当成了背景。常见于图像和标签目录结构不符合YOLO默认约定。解决检查labels目录是否和images平行标签文件名是否和图像文件名除扩展名外完全一致。用ls images/train | head -3和ls labels/train | head -3对比。5.2 现象推理时框的位置整体偏移原因letterbox的padding参数没有正确传递到后处理。训练时用了letterbox推理时直接resize坐标映射关系断了。解决推理代码里必须用和训练相同的letterbox函数并保留scale, left, top三个值把预测框先减padding再除scale。5.3 现象某些类别完全检测不到原因类别不平衡导致小类梯度被淹没或者类别名在转换时写错导致样本被跳过。解决先统计每个类别的标注数量少于50个的类别考虑过采样或复制粘贴增强。再检查转换脚本里的cls_map是否覆盖所有类别名。5.4 现象验证集mAP很高但测试集一塌糊涂原因训练集和验证集按图像随机划分同一设备的不同角度图像同时出现在两个集合里造成数据泄露。解决按设备ID或拍摄批次划分确保同一设备只出现在一个集合。如果文件名没有设备ID用图像感知哈希做聚类后再划分。5.5 现象训练到一半显存溢出原因batch size太大或者图像尺寸在某个批次突然变大数据集中混入了超高分辨率图像。解决先用find . -name *.jpg -exec identify -format %wx%h\n {} \; | sort -rn | head -5找出最大图像如果远超640在Dataset里做上限裁剪。batch降到8或4再试。6. 把baseline推到可提交学习率调度与TTA两个进阶技巧6.1 余弦退火 warmup电力数据小样本的稳定训练策略电力AI竞赛的数据量通常不大几千张图像是常态。这种规模下固定学习率容易在后期震荡余弦退火能让模型在训练末期精细收敛。YOLOv8内置了cos_lr参数但warmup需要手动配。yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ cos_lrTrue \ lr00.01 \ lrf0.001 \ warmup_epochs3 \ warmup_momentum0.8 \ device0逻辑说明cos_lrTrue启用余弦退火学习率从lr0按余弦曲线降到lrf。warmup_epochs3在前3轮线性升温避免初始大学习率破坏预训练权重。warmup_momentum0.8是warmup阶段的动量比默认0.937低让初期更新更保守。参数说明lr00.01是初始学习率YOLOv8默认就是0.01小数据集可以降到0.005。lrf0.001是最终学习率因子实际最终lr lr0 * lrf。warmup轮数一般设总轮数的3%到5%。6.2 测试时增强多尺度水平翻转的推理融合TTATest Time Augmentation在推理阶段对同一张图做多种变换把预测结果融合。电力设备缺陷检测里绝缘子破损在不同尺度下特征差异明显多尺度TTA能提升召回。from ultralytics import YOLO import numpy as np model YOLO(runs/power_ai/baseline/weights/best.pt) def tta_predict(img_path, scales[640, 736, 832]): all_boxes [] for s in scales: results model.predict(img_path, imgszs, conf0.15, verboseFalse) for r in results: if r.boxes is None: continue boxes r.boxes.xyxy.cpu().numpy() scores r.boxes.conf.cpu().numpy() clses r.boxes.cls.cpu().numpy() for b, sc, c in zip(boxes, scores, clses): all_boxes.append((b, sc, c)) # 用NMS融合多尺度结果IoU阈值0.5 return all_boxes boxes tta_predict(test_images/deviceA_001.jpg) print(TTA后候选框数:, len(boxes))逻辑说明三个尺度分别推理每个尺度输出自己的框。把所有框汇总后用NMS做融合同一目标在不同尺度下都会被检测到NMS保留置信度最高的。这样比单尺度推理召回更高代价是推理时间翻三倍。参数说明scales[640, 736, 832]是常见多尺度组合围绕训练尺寸上下浮动。conf0.15比正常推理低因为TTA会引入更多候选框靠NMS过滤。如果显存不够可以只做两个尺度。6.3 提交前的最后检查清单在把结果提交之前我习惯过一遍这几个点类别索引是否和赛题要求一致、坐标格式是xyxy还是xywh、置信度阈值是否合理、有没有漏掉空预测的图像。电力AI竞赛里格式错误直接判零分的情况不少见。有一次我因为把类别索引从0开始写成了从1开始整个提交文件全部错位白白浪费一次提交机会。后来养成的习惯是提交前用脚本随机抽10行和原始标注做人工比对确认格式和内容都对得上。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

R 与 RStudio 版本更新全攻略:跨平台升级、包迁移与避坑指南
R 与 RStudio 版本更新全攻略:跨平台升级、包迁移与避坑指南

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

Windows-universal-samples 音频图(AudioGraph)实战指南:用 Windows.Media.Audio 构建路由、混音与音频处理管线
Windows-universal-samples 音频图(AudioGraph)实战指南:用 Windows.Media.Audio 构建路由、混音与音频处理管线

示例工程 【免费下载链接】Windows-universal-samples API samples for the Universal Windows Platform. 项目地址: https://gitcode.com/gh_mirrors/wi/Windows-universal-samples 点击查看 免费下载 本指南以 Windows-universal-samples 仓库中的 AudioCreation… · 2026/9/25 1:43:11

nnU-Net 仓库安全改造指南:面向编码 Agent 与新贡献者的代码库工作手册(含 DDP 分布式训练与兼容性策略)
nnU-Net 仓库安全改造指南:面向编码 Agent 与新贡献者的代码库工作手册(含 DDP 分布式训练与兼容性策略)

人工智能深度学习计算机视觉医疗健康 【免费下载链接】nnUNet 项目地址: https://gitcode.com/gh_mirrors/nn/nnUNet 点击查看 免费下载 本文是 nnU-Net 仓库中面向「编码 Agent 与代码贡献者」的工作手册(对应仓库根目录 CLAUDE.md)&#x… · 2026/9/25 1:43:11

【激光雷达SLAM】实现一个基本的扫描匹配算法,并采用贪心算法进行位姿优化研究附Matlab代码
【激光雷达SLAM】实现一个基本的扫描匹配算法,并采用贪心算法进行位姿优化研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、算法改进、程序设计科研仿真。🍎 往期回顾关注个人主页:完整代码获取 定制创新 论文复现私信🍊个人信条:做科研&#xff0c… · 2026/9/25 2:16:52

基于人工大猩猩部队优化CNN-LSTM(GTO-CNN-LSTM)多变量时间序列预测附Matlab代码
基于人工大猩猩部队优化CNN-LSTM(GTO-CNN-LSTM)多变量时间序列预测附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、算法改进、程序设计科研仿真。🍎 往期回顾关注个人主页:完整代码获取 定制创新 论文复现私信🍊个人信条:做科研&#xff0c… · 2026/9/25 2:16:52

STM32 SWD/JTAG通信失败排查全攻略:从硬件到软件一步到位
STM32 SWD/JTAG通信失败排查全攻略:从硬件到软件一步到位

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

Windows 上编译 vlc-qt 的完整指南:从依赖配置到集成播放器
Windows 上编译 vlc-qt 的完整指南:从依赖配置到集成播放器

简介:本资源面向需要在 Windows 平台使用 Qt 集成 VLC 播放能力的开发者,提供 vlc-qt 1.1.1 的完整编译成果与配套源码,解决自行编译时依赖配置繁琐、版本匹配困难的问题。包内共 77 个文件,以 38 个 h 头文件、17 个 cmake 配置脚… · 2026/9/25 2:16:51

PaddleSpeech 语音合成 g2p 字典设计详解:从 ARPAbet 到中文内部注音方案
PaddleSpeech 语音合成 g2p 字典设计详解:从 ARPAbet 到中文内部注音方案

人工智能语音音频NLP媒体生成 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation … · 2026/9/25 2:16:51

运放恒流源实战指南:从原理到PCB抗干扰设计
运放恒流源实战指南:从原理到PCB抗干扰设计

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

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

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

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

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

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

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

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码