谢韦尔钢材缺陷检测数据集:RLE转YOLO格式与训练教程
简介本资源为YOLO谢韦尔钢材缺陷检测数据集面向从事工业质检、目标检测算法学习与竞赛实践的学生、工程师及研究者帮助解决钢材表面缺陷样本获取难、标注格式不统一的问题。压缩包共2000个文件约12.38MB包含1000张真实场景高质量图片以及vocxml、cocojson和yolotxt三种格式标签另附yaml配置文件、划分脚本与教程页面可直接接入YOLO系列模型训练。资源还提供训练集、验证集、测试集划分脚本以及Windows与Linux环境搭建、训练案例教程便于按需自定义数据划分并快速跑通流程。目前已有587人学习下载适合希望快速验证缺陷检测方案、对比不同标签格式或搭建工业质检原型的读者参考使用。1. 谢韦尔钢材缺陷检测数据集到底能解决什么问题钢材表面缺陷检测是工业质检里最典型的视觉任务之一热轧板、冷轧板在轧制、卷取、运输过程中会产生夹杂、划痕、氧化铁皮压入、结疤、裂纹等缺陷。传统做法靠人眼在产线末端盯屏幕漏检率高、疲劳快、标准不统一。用 YOLO 做钢材缺陷检测核心诉求就一个把缺陷框出来并分类替代或辅助人工判级。谢韦尔钢材缺陷检测数据集Severstal Steel Defect是 Kaggle 上钢铁缺陷检测竞赛的公开数据原始标注是 RLE 编码的掩码不是现成的检测框。这个标题里的资源包做了三件事把掩码转成检测框、统一导出 VOC/COCO/YOLO 三种格式、附上划分脚本和训练教程。适合谁刚入门 YOLO 想找一个真实工业数据集练手的算法工程师以及需要快速搭一条钢材缺陷检测 baseline 的产线视觉开发者。1000 张图片不算大但足够跑通从数据到推理的完整链路也能暴露小目标、类别不平衡这些真实问题。2. 从 RLE 掩码到三种标签格式转换链路怎么走通2.1 为什么原始数据不能直接喂给 YOLO谢韦尔原始标注是ImageId_ClassId加 RLE 字符串的形式一张图对应最多四类缺陷每类一个 RLE。RLERun-Length Encoding描述的是像素级掩码而 YOLO 训练需要的是归一化的class x_center y_center width height。中间差了两步RLE 解码成二值掩码掩码再求连通域外接矩形。很多人拿到数据集直接找labels文件夹发现没有就卡住了其实标签得自己生成。常见做法是用pycocotools的frPyObjects解码 RLE再用 OpenCV 的findContours或connectedComponentsWithStats提取每个缺陷实例的边界框。这里有个关键判断一张图同一类缺陷可能有多个不连通的区域必须按连通域拆成多个框不能整张图只给一个框否则小缺陷会被大框吞掉模型学不到定位。2.2 转换脚本RLE 解码与 YOLO 标签生成下面这段脚本处理单张图的 RLE 到 YOLO txt 的转换核心是解码、连通域分析、归一化三步。import numpy as np import cv2 from pycocotools import mask as maskUtils def rle_to_boxes(rle_string, height, width, min_area20): RLE 字符串 - 二值掩码 - 连通域外接框列表 # 谢韦尔 RLE 是 start length 空格分隔的字符串 s rle_string.split() starts, lengths [np.asarray(x, dtypeint) for x in (s[0:][::2], s[1:][::2])] starts - 1 # RLE 从 1 开始计数 ends starts lengths img np.zeros(height * width, dtypenp.uint8) for lo, hi in zip(starts, ends): img[lo:hi] 1 img img.reshape((height, width), orderF) # 谢韦尔按列优先编码 # 连通域分析过滤噪点 num, labels, stats, _ cv2.connectedComponentsWithStats(img, connectivity8) boxes [] for i in range(1, num): x, y, w, h, area stats[i] if area min_area: continue boxes.append([x, y, w, h]) return boxes def boxes_to_yolo(boxes, img_w, img_h, class_id): 外接框 - YOLO 归一化格式 lines [] for x, y, w, h in boxes: xc (x w / 2.0) / img_w yc (y h / 2.0) / img_h nw w / img_w nh h / img_h lines.append(f{class_id} {xc:.6f} {yc:.6f} {nw:.6f} {nh:.6f}) return lines逻辑说明rle_to_boxes先把 RLE 展开成一维数组注意谢韦尔的掩码是按列优先Fortran orderreshape 的用错顺序框会整体旋转 90 度这是血泪经验。min_area20是过滤解码产生的孤立噪点钢材缺陷里小于 20 像素的区域基本是噪声。boxes_to_yolo做归一化YOLO 要求坐标在 0 到 1 之间且是中心点加宽高。参数上connectivity8用八连通因为缺陷边缘往往是对角相连的如果发现同一缺陷被拆成多个框可以适当做形态学闭运算再分析。2.3 VOC 与 COCO 格式的导出差异VOC 是 XML每个目标一个object存xmin ymin xmax ymax绝对坐标COCO 是单个 JSONannotations里存bbox为[x, y, w, h]绝对坐标外加category_id和image_id。三种格式的坐标语义不同转换时最容易翻车的是 VOC 的xmax是闭区间还是开区间——VOC 惯例是包含边界所以xmax x w而 COCO 的w是宽度xmax x w但语义上不包含。实际训练时这点差异影响不大但做格式互转校验时会导致框差一个像素。建议统一用 COCO 的[x, y, w, h]作为中间表示再导出 VOC 和 YOLO。导出 COCO 时category_id从 1 开始YOLO 的class_id从 0 开始这个偏移量写错会让所有标签错位一类训练 loss 直接不降。3. 数据集划分脚本别让随机种子坑了你的验证集3.1 划分比例与分层抽样钢材缺陷四类类别 1 到 4分布极不均衡类别 3 的样本远多于类别 4。如果直接random.shuffle按 8:2 切验证集里可能一个类别 4 都没有mAP 评估就失真了。正确做法是按类别分层抽样对每张图取它包含的类别集合按这个集合做分层保证每个类别在训练集和验证集里的比例接近。常见做法是用sklearn的train_test_split配合stratify参数但stratify要求每个样本一个标签多标签场景得把类别组合成字符串当标签用。import os import glob import shutil from sklearn.model_selection import train_test_split def split_dataset(img_dir, label_dir, out_dir, val_ratio0.2, seed42): 按类别组合分层划分避免验证集缺类 imgs sorted(glob.glob(os.path.join(img_dir, *.jpg))) records [] for img_path in imgs: stem os.path.splitext(os.path.basename(img_path))[0] label_path os.path.join(label_dir, stem .txt) classes set() if os.path.exists(label_path): with open(label_path) as f: for line in f: classes.add(line.split()[0]) # 用类别组合做分层键空标签归为 none key _.join(sorted(classes)) if classes else none records.append((img_path, label_path, key)) keys [r[2] for r in records] train_records, val_records train_test_split( records, test_sizeval_ratio, random_stateseed, stratifykeys ) for split, recs in [(train, train_records), (val, val_records)]: img_out os.path.join(out_dir, images, split) lbl_out os.path.join(out_dir, labels, split) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for img_path, label_path, _ in recs: shutil.copy(img_path, img_out) if os.path.exists(label_path): shutil.copy(label_path, lbl_out) print(ftrain: {len(train_records)}, val: {len(val_records)})逻辑说明stratifykeys保证每个类别组合在训练和验证里的比例一致。seed42固定随机种子保证每次划分结果可复现否则调参时验证集变了指标对比就没意义。参数val_ratio0.2是常规选择1000 张图里 200 张做验证如果类别 4 样本极少可以降到 0.15 保证训练样本量。注意空标签图片无缺陷也要参与划分它们对降低误检率有帮助不能直接丢掉。3.2 划分后的目录结构与校验YOLO 训练要求images/train、images/val、labels/train、labels/val四个目录图片和标签同名不同后缀。划分完必须做一次校验遍历所有标签文件检查每行五个值、类别在 0 到 3 之间、坐标在 0 到 1 之间。常见错误是转换时坐标没归一化或者类别从 1 开始导致越界。写个校验脚本跑一遍比训练时报错再回头查省事得多。# 快速校验统计每个类别的框数量检查坐标范围 python -c import glob from collections import Counter c Counter() for f in glob.glob(labels/train/*.txt): for line in open(f): parts line.split() assert len(parts) 5, f{f} 格式错误 cls, x, y, w, h int(parts[0]), *map(float, parts[1:]) assert 0 cls 3, f{f} 类别越界 assert all(0 v 1 for v in (x, y, w, h)), f{f} 坐标未归一化 c[cls] 1 print(c) 这段命令直接跑输出每个类别的框数量。如果某个类别为 0说明转换或划分出了问题。坐标越界会直接抛断言定位到具体文件。4. YOLO 训练教程1000 张图怎么调才不欠拟合4.1 环境与数据配置用 Ultralytics 的 YOLOv8 或 YOLO11 都行安装pip install ultralytics。数据配置文件steel.yaml长这样path: ./steel_dataset train: images/train val: images/val nc: 4 names: 0: defect_1 1: defect_2 2: defect_3 3: defect_4nc是类别数谢韦尔四类缺陷实际名称按你的业务定义改。path用相对路径避免换机器后路径失效。配置文件放项目根目录训练命令里用datasteel.yaml引用。4.2 训练命令与关键参数yolo detect train \ datasteel.yaml \ modelyolo11n.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ augmentTrue \ mosaic1.0 \ degrees10.0 \ translate0.1 \ scale0.5 \ fliplr0.5 \ namesteel_baseline参数说明modelyolo11n.pt用 nano 版1000 张图从零训容易过拟合用预训练权重迁移学习。epochs150配合patience3030 轮验证指标不升就早停省时间。imgsz640是 YOLO 默认输入尺寸钢材缺陷里小目标多如果显存够可以上 1024小缺陷召回会明显提升。lr00.01初始学习率lrf0.01最终学习率是初始的百分之一余弦退火。mosaic1.0马赛克增强对钢材缺陷有效能提升小目标检测但训练后期建议关掉否则框的分布和真实场景偏差大。degrees10.0旋转增强钢材缺陷方向随机适度旋转合理但别超过 15 度否则引入大量黑边。fliplr0.5水平翻转钢材纹理左右翻转后仍然合理可以用。4.3 训练过程看什么指标训练时重点盯三个box_loss是否稳定下降、mAP50是否上升、cls_loss是否震荡。钢材缺陷检测里cls_loss震荡常见因为类别不平衡类别 4 样本少梯度贡献小。解决办法是给类别 4 加权或者用 focal loss。Ultralytics 默认用 BCE可以在train里加cls1.5调分类损失权重但别调太大否则误检飙升。验证集mAP50到 0.6 以上算及格0.75 以上算不错具体看缺陷类型划痕这种细长目标 mAP 天然偏低。5. 避坑与排查钢材缺陷检测里最容易翻车的五件事5.1 现象训练 loss 不降mAP 始终为 0原因标签格式错误最常见的是坐标没归一化或者类别从 1 开始导致越界被忽略。YOLO 读取标签时如果坐标大于 1 会直接跳过该框等于没有标签。解决跑一遍 3.2 节的校验脚本确认所有坐标在 0 到 1、类别从 0 开始。另外检查图片和标签是否同名jpg配txt差一个字符就匹配不上。5.2 现象验证集 mAP 很高但实际推理漏检严重原因训练集和验证集划分时没有分层验证集恰好都是简单样本或者数据增强过强导致模型只学到增强后的分布。解决用 3.1 节的分层划分脚本重新切确保验证集覆盖所有类别。推理时把imgsz调到和训练一致别训练 640 推理 1280尺度不匹配会掉点。另外检查推理时的conf阈值默认 0.25钢材缺陷里小目标置信度低可以降到 0.1 看召回再权衡误检。5.3 现象同一张图同类缺陷只检出一个框原因RLE 转框时没做连通域拆分整张图同类缺陷合并成一个大框。解决回到 2.2 节的connectedComponentsWithStats确认num大于 1 时每个连通域都生成了独立框。如果缺陷本身是连通的但被拆成多个调大min_area或做形态学闭运算。这个坑在钢材缺陷里特别常见因为氧化铁皮压入往往是一片不连续的区域。5.4 现象训练到一半 loss 突然变 NaN原因学习率太大或者某张图标签坐标异常导致梯度爆炸。解决先把lr0降到 0.001 重跑如果还 NaN用校验脚本逐张检查标签重点看有没有坐标是负数或大于 1 的。另外batch16在 1000 张图里可能偏大显存够但梯度噪声小容易过拟合可以试batch8配合accumulate2。5.5 现象模型把正常纹理误检成缺陷原因负样本无缺陷图片太少或者数据增强里mosaic把不同图的缺陷拼到一起模型学到了虚假关联。解决确保训练集里有足够无缺陷图片谢韦尔数据里有些图确实没有缺陷别全过滤掉。训练后期关掉mosaic用close_mosaic10在最后 10 轮关闭。推理时提高conf到 0.4 以上牺牲一点召回换准确率产线场景误检比漏检更烦人。6. 进阶技巧用 TTA 和切片推理把钢材小缺陷召回拉上来钢材缺陷里最头疼的是小目标一张 640 输入下几个像素宽的划痕经过下采样后特征几乎消失。除了把imgsz拉到 1024还有两个实战技巧。第一个是测试时增强TTA推理时对同一张图做水平翻转、多尺度缩放把结果融合。Ultralytics 推理时加augmentTrue就开启 TTA代价是推理时间翻倍但 mAP 通常能涨 1 到 3 个点。第二个是切片推理SAHI把大图切成带重叠的小块分别检测再合并对小目标召回提升明显。钢材图片分辨率往往很高直接缩到 640 会丢细节切片推理能保留原始分辨率下的小缺陷。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/detect/steel_baseline/weights/best.pt, confidence_threshold0.2, devicecuda:0 ) result get_sliced_prediction( test_steel.jpg, detection_model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2 ) result.export_visuals(export_dirsahi_output/)参数说明slice_height和slice_width是切片尺寸512 适合钢材缺陷太小会切碎大缺陷太大失去切片意义。overlap_height_ratio0.2是切片重叠比例20% 能避免缺陷正好落在切片边界被截断。confidence_threshold0.2比常规低因为切片后每个小图里目标占比大置信度分布会变阈值要相应调整。SAHI 的代价是推理慢一张 4000 像素宽的图切完可能几十个切片产线节拍紧的话得权衡。验证 TTA 和切片是否有效别只看 mAP要单独统计小目标面积小于 32x32的召回率。我一般会写个脚本按框面积分桶对比开启前后的召回变化。如果小目标召回涨了但大目标掉了说明切片重叠比例或阈值需要调。这套组合拳在钢材缺陷检测里我踩过最大的坑是切片边界处的重复框SAHI 自带 NMS 合并但overlap设太小会导致同一缺陷在两个切片里各检一次合并后框偏大。经验是overlap不低于 0.15NMS 的iou阈值用 0.5 左右。最后说个习惯每次改完数据或增强参数先跑 10 个 epoch 看 loss 曲线和验证集前几张图的预测框别等 150 轮跑完才发现标签错了。钢材缺陷检测这活儿数据质量比模型结构重要得多1000 张图里如果有 50 张标签有问题足够把 mAP 拉低十几个点。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

PCB飞针测试全流程指南:从原理、编程到调试的实用手册

PCB飞针测试全流程指南:从原理、编程到调试的实用手册

PCB做出来之后,怎么快速知道它有没有短路、断路?这是每个硬件工程师和PCB工程师都会遇到的问题。飞针测试就是解决这个问题的关键手段之一。去年我系统性梳理了一遍从零开始学习PCB飞针测试的流程,从测试理论、文件准备、程序生成到上机调试都…

2026/10/7 6:33:54 阅读更多 →
智能体Skills本质:Kubernetes CRD驱动的可编排能力单元

智能体Skills本质:Kubernetes CRD驱动的可编排能力单元

1. 这不是“技能列表”,而是一套可执行、可验证、可进化的智能体能力操作系统你搜“skills”时看到的那些词——Google Cloud、GKE、Gemini、Agent Platform、Claude、Codex、分镜、自动挖洞、写论文、MacBook下载……它们根本不是零散的工具名或功能点,…

2026/10/7 6:33:54 阅读更多 →
大模型上下文管理实战:context-mode 策略、实现与踩坑指南

大模型上下文管理实战:context-mode 策略、实现与踩坑指南

直接从一次真实的困惑说起。前阵子一个做 AI 应用的朋友问我:"你的 context-mode 到底怎么写的?"我一开始以为他说的是某个库,聊了半天才明白,他指的是应用里对对话上下文的组织与取舍方式。这个词在圈子里越来越常出现…

2026/10/7 6:33:54 阅读更多 →

最新新闻

Kimi 浏览器扩展升级:把网页操作录成可复用的 Skill

Kimi 浏览器扩展升级:把网页操作录成可复用的 Skill

Kimi WebBridge 发布约 4 个月后,被改头换面重新命名为 Kimi 浏览器扩展,并在原有能力之上做了两处关键升级: 在浏览器侧边栏可以直接登录对话,让 Kimi 操作当前网页;新增将网页操作录制成 Skill 的能力,方…

2026/10/7 8:14:04 阅读更多 →
亲测体验|横向实测多款 AI 学术工具,为什么我最终选择 Paperxie 搞定毕设全流程

亲测体验|横向实测多款 AI 学术工具,为什么我最终选择 Paperxie 搞定毕设全流程

前言 临近毕业,不少同学都在找 AI 学术工具帮忙减轻毕设压力。 这段时间我前后试了好几个热门产品,踩了不少坑。有的工具只能润色文字,做参考文献直接翻车;有的绘图效果不错,但文献翻译能力很差;还有通用大…

2026/10/7 8:14:04 阅读更多 →
【C++面试】堆内存与栈内存:string、vector和对象到底存在哪里

【C++面试】堆内存与栈内存:string、vector和对象到底存在哪里

一、堆内存和栈内存到底有什么区别 先看最简单的代码: void fun() {int a 10;int *p new int(20);delete p; } 这里一般可以理解成: 栈:┌──────────────┐ │ a 10 │ ├──────────────┤ │ p …

2026/10/7 8:14:04 阅读更多 →
XSS跨站脚本攻击完全指南:从原理到实战的保姆级教程,一文搞懂XSS!

XSS跨站脚本攻击完全指南:从原理到实战的保姆级教程,一文搞懂XSS!

一、什么是XSS XSS(Cross-Site Scripting,跨站脚本攻击)是指攻击者向Web页面中注入恶意的客户端脚本代码(如JavaScript、HTML),当其他用户访问该页面时,恶意脚本在用户浏览器中执行&#xff0c…

2026/10/7 8:14:04 阅读更多 →
机械设备官网的产品参数结构化:数据建模、站内检索与 Schema 落地

机械设备官网的产品参数结构化:数据建模、站内检索与 Schema 落地

机械设备类官网普遍有一个通病:产品中心是一堆图片。型号、参数、工况都写在设计稿里导出的 JPG 上,人眼能看,机器读不到。结果是用户搜不到型号,搜索引擎和 AI 也摘不出任何可用信息。 这篇讲把产品参数做成"可被检索的结构…

2026/10/7 8:14:04 阅读更多 →
【专知智库】专知智库,让数据驱动增长

【专知智库】专知智库,让数据驱动增长

专知智库,让数据驱动增长一、数据驱动增长,关键在“什么数据”今天,几乎每家公司都在说“数据驱动增长”。但真正的问题是:什么数据? 驱动谁的增长? 怎么驱动?如果数据只是躺在报表里、散落在系…

2026/10/7 8:13:04 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

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

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

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

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

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

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/6 6:26:51 阅读更多 →

月新闻

我发现了一个新思路:用 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/6 8:21:32 阅读更多 →
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/6 4:21:51 阅读更多 →
黑夜航拍船只数据集训练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/6 1:18:13 阅读更多 →