news 2026/9/2 10:59:23

飞机表面缺陷数据集:4264张5类VOC/YOLO格式详解与应用实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
飞机表面缺陷数据集:4264张5类VOC/YOLO格式详解与应用实战

简介:本资源是面向计算机视觉算法工程师与工业质检方向研究者的飞机表面缺陷检测专用数据集,聚焦裂纹、凹痕、铆钉缺失、掉漆及划伤五类典型损伤,可直接用于目标检测模型训练、验证与性能对比。压缩包共2000个文件,含1999个Pascal VOC格式XML标注文件与1个说明文档,总大小163.17MB;所有4264张JPG图像均同步提供YOLO格式TXT标签(不含分割路径),标注框总数达8768个,由labelImg工具严格按矩形框规范完成,类别分布覆盖实际产线中高频与低频缺陷场景。已有446人学习下载,数据结构清晰、格式双兼容、类别定义明确,开箱即用,特别适合快速构建端到端缺陷识别Pipeline、开展小样本迁移实验或作为教学案例讲解多类别不平衡问题的处理策略。

1. 项目概述:一份专为工业质检打造的飞机表面缺陷数据集

在工业视觉领域,尤其是航空航天这种对安全要求近乎苛刻的行业,表面缺陷的自动化检测一直是个硬骨头。传统的目视检查不仅效率低下,高度依赖老师傅的经验,还容易因疲劳产生漏检。深度学习,特别是目标检测技术,为这个问题提供了全新的解题思路。但这条路有个众所周知的起点:数据。没有高质量、标注精准的数据集,再先进的算法也是“巧妇难为无米之炊”。

今天要聊的这个数据集——“飞机表面缺陷数据集4264张5类VOC+YOLO格式”,就是针对这个痛点而生的一份宝贵资源。它包含了4264张真实或高度仿真的飞机表面图像,标注了5类常见的缺陷,并且贴心地提供了VOC和YOLO两种主流格式的标签。这意味着,无论你是用老牌的Faster R-CNN、SSD,还是当下火爆的YOLOv5、v7、v8,甚至是DETR这类Transformer模型,都能直接拿它来“喂”模型,快速启动你的训练流程。

这份数据集的核心价值,在于它极大地降低了航空器智能视觉检测的入门门槛和研究成本。对于高校和研究机构的学生、学者,它是一块绝佳的“试验田”,可以让你专注于算法创新而非数据收集;对于工业界的工程师,它是一个可靠的基准和起点,可以基于它开发原型系统,或进行迁移学习以适应自家产线的特定场景。接下来,我们就从设计思路到实操细节,完整地拆解这份数据集及其应用之道。

2. 数据集核心设计思路与场景解析

2.1 缺陷类别定义:为何是这五类?

数据集标注了5类缺陷,这个选择绝非随意,而是紧密贴合飞机维护(MRO)和制造中的实际高发问题。通常,这五类可能包括:

  1. 划痕/Scratch:这是最常见的表面损伤,可能由工具碰撞、地面设备刮蹭或飞行中细小碎片冲击造成。虽然细微,但可能成为应力集中点或腐蚀起始点。
  2. 凹痕/Dent:通常由冰雹、鸟击或较大物体撞击形成。凹痕会改变蒙皮的气动外形,并可能伴随内部结构损伤。
  3. 腐蚀/Corrosion:特别是漆层下的电化学腐蚀,是飞机老龄化的主要问题。早期发现至关重要,因为腐蚀会显著降低金属结构的强度。
  4. 漆层脱落/Paint Peeling:暴露底层金属或底漆,不仅影响美观,更是腐蚀和进一步损伤的前兆。
  5. 铆钉异常/Rivet Defect:包括铆钉凸起、凹陷、缺失或周围裂纹。铆钉是飞机结构的主要连接方式,其状态直接关系到结构完整性。

注意:具体类别名称可能因数据集发布者而异(例如可能是“裂纹”、“烧蚀”等),但设计逻辑相通:覆盖从轻微到严重、从常见到关键的缺陷类型,形成一个有代表性的缺陷谱系。

选择这五类,平衡了问题的普遍性和检测的挑战性。例如,划痕和漆层脱落属于细长、低对比度的目标,对算法的边缘检测和特征提取能力要求高;而凹痕和腐蚀区域可能对比度变化缓慢、边界模糊,考验模型对纹理和上下文信息的理解。

2.2 数据来源与采集:真实性与多样性的权衡

4264张图像的规模,在专业领域数据集中属于中等偏上,足以支持一个有监督模型进行有效学习而不至于严重过拟合。其来源无外乎以下几种,各有优劣:

  • 真实航拍/机库拍摄:最具价值,但获取成本极高。需要协调飞机、专业摄影设备(如高分辨率工业相机、无人机),并在不同光照(晨昏、阴晴)、不同背景(机坪、机库、天空)、不同飞机型号和部位(机翼、机身、尾翼)下拍摄,以确保多样性。
  • 高保真3D渲染与模拟:这是目前生成高质量合成数据的主流技术。通过CAD模型引入缺陷,并渲染出不同视角、光照和材质效果的图像。优点是可控性强,可以生成极端、罕见但重要的缺陷样本,且标注完全准确。本数据集很可能混合了真实与合成数据。
  • 公开数据整合与增强:从有限的公开图片、视频中截帧,并经过严格的清洗、去标识和增强处理。

数据的多样性是模型泛化能力的基石。一个好的数据集应在以下维度有充分体现:

  • 尺度多样性:既有展现大面积机翼的远景,也有聚焦单个铆钉的特写。
  • 光照与天气多样性:顺光、逆光、阴影、高光过曝、阴天、雨天(表面有水膜)等条件。
  • 缺陷状态多样性:同一类缺陷的不同形态、大小、严重程度。

2.3 双格式标签:VOC与YOLO的并存之道

提供VOC和YOLO两种格式,是这份数据集非常实用的一点,照顾了不同技术栈的用户。

  • VOC格式:源于PASCAL VOC竞赛,采用XML文件存储标注。每个XML文件对应一张图片,其中以像素坐标明确记录每个缺陷目标的左上角和右下角坐标(xmin, ymin, xmax, ymax),以及类别名称。这种格式人类可读性强,易于理解和校验,且被许多早期框架(如Caffe、原始TensorFlow Object Detection API)广泛支持。

    <!-- 示例:VOC格式XML片段 --> <object> <name>scratch</name> <bndbox> <xmin>100</xmin> <ymin>50</ymin> <xmax>300</xmax> <ymax>70</ymax> </bndbox> </object>
  • YOLO格式:这是当前最流行的格式之一,尤其随着Ultralytics YOLO系列的崛起。它将标注信息存储在纯文本.txt文件中,每行代表一个目标,格式为:<class_id> <x_center> <y_center> <width> <height>。这里的坐标是归一化的(除以图像宽高),取值在0到1之间。这种格式紧凑,读写速度快,直接适配YOLO系列训练代码。

    # 示例:YOLO格式TXT内容 0 0.5 0.2 0.4 0.05 # 假设 class_id 0 对应 scratch, 表示一个中心在(0.5,0.2),宽高为0.4和0.05的缺陷。

为什么同时提供两种?

  1. 兼容性:确保无论用户的老项目基于何种框架,都能无缝使用。
  2. 灵活性:用户可以根据需要轻松转换。例如,用YOLO格式训练时,如果想可视化检查标注,可以临时转成VOC格式用LabelImg等工具查看。
  3. 学习价值:对于初学者,对比两种格式能更好地理解目标检测中边界框的不同表示方法。

3. 数据预处理与增强实战策略

拿到数据集压缩包后,直接扔进模型训练往往不是最佳实践。一套规范的数据预处理流程能显著提升数据质量,进而影响模型性能。

3.1 数据解压与结构校验

首先解压飞机表面缺陷数据集4264张5类VOC+YOLO格式.zip。标准的目录结构应类似于:

aircraft_defect_dataset/ ├── images/ # 存放所有4264张JPG/PNG图像 │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── annotations_voc/ # VOC格式XML标注文件 │ ├── 000001.xml │ ├── 000002.xml │ └── ... └── labels_yolo/ # YOLO格式TXT标注文件 ├── 000001.txt ├── 000002.txt └── ...

第一步是进行完整性校验:检查图像与标注文件是否一一对应,有无损坏文件,以及标注文件是否为空。一个简单的Python脚本就能完成:

import os from PIL import Image img_dir = ‘./images‘ voc_dir = ‘./annotations_voc‘ yolo_dir = ‘./labels_yolo‘ # 检查对应关系 img_files = set([f.split(‘.‘)[0] for f in os.listdir(img_dir)]) voc_files = set([f.split(‘.‘)[0] for f in os.listdir(voc_dir)]) yolo_files = set([f.split(‘.‘)[0] for f in os.listdir(yolo_dir)]) assert img_files == voc_files == yolo_files, “图像与标注文件不匹配!“ # 检查图像能否正常打开 for img_name in os.listdir(img_dir): try: with Image.open(os.path.join(img_dir, img_name)) as img: img.verify() except Exception as e: print(f“损坏图像: {img_name}, 错误: {e}“)

3.2 数据集划分的科学比例

切忌将所有数据随机划分。对于工业缺陷数据,更推荐分层抽样,确保训练集、验证集、测试集中,各类缺陷的比例与全集基本一致,避免某个稀有缺陷在某个集合中缺失。 常见的划分比例是 7:2:1 或 8:1:1。对于4264张的数据集,8:1:1意味着:

  • 训练集:约3411张
  • 验证集:约426张
  • 测试集:约427张

验证集用于训练过程中的超参数调优和模型选择,测试集则用于最终评估,在训练过程中绝对不可见

3.3 针对飞机缺陷的专项数据增强

数据增强是扩充数据集、提升模型鲁棒性的利器。对于飞机表面缺陷,需要选择贴合实际物理可能性的增强方式,避免引入不现实的畸变。

强力推荐增强方法:

  • 几何变换
    • 旋转(小角度):±15度以内。飞机在图像中可能有轻微倾斜。
    • 平移:小幅平移,模拟拍摄时的不完全对齐。
    • 水平翻转:完全合理,飞机左右对称。
    • 缩放:随机缩放至0.9~1.1倍,模拟拍摄距离变化。
  • 像素变换
    • 亮度/对比度调整:模拟不同时间、天气的光照变化。
    • 添加高斯噪声:模拟传感器噪声,提升模型抗干扰能力。
    • 模糊:轻微的高斯模糊或运动模糊,模拟对焦轻微不准或拍摄抖动。
  • 色彩空间变换:在HSV空间随机调整色调(H)、饱和度(S)、明度(V),模拟不同漆面反光和环境光色温影响。

需谨慎或避免的增强方法:

  • 大角度旋转(如90°、180°):飞机在图像中倒置或垂直的情况极少。
  • 垂直翻转:不符合物理常识。
  • 严重的剪切、扭曲:会破坏缺陷的形态特征,产生不真实的图像。
  • 过度的饱和度调整:可能导致漆面颜色失真,超出真实范围。

实操心得:我习惯使用albumentations库来定义增强管道,它支持与标注(边界框)的同步变换,且速度很快。

import albumentations as A transform = A.Compose([ A.HorizontalFlip(p=0.5), A.RandomRotate90(p=0.2), # 小概率90度旋转,应对特殊视角 A.Rotate(limit=15, p=0.5), A.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.5), A.GaussNoise(var_limit=(10.0, 50.0), p=0.3), A.Blur(blur_limit=3, p=0.2), ], bbox_params=A.BboxParams(format=‘yolo‘, label_fields=[‘class_labels‘]))

3.4 类别平衡与困难样本挖掘

检查数据集中5类缺陷的实例数量。如果出现严重不平衡(如“划痕”有3000个实例,“铆钉异常”只有200个),模型会偏向于学习多的类别。解决方法:

  1. 重采样:对少数类别的图像进行复制或增强。
  2. 重加权:在损失函数中给少数类别分配更大的权重。
  3. 困难样本挖掘:在训练初期,模型会对某些样本(如背景复杂、缺陷模糊的)判断不准。将这些样本加入重点训练集,能有效提升模型在“硬骨头”上的表现。

4. 基于YOLOv8的模型训练全流程详解

我们以当前最流行的Ultralytics YOLOv8为例,展示从数据准备到模型训练、评估的完整流程。YOLOv8提供了极其简洁的API和强大的性能。

4.1 环境配置与项目结构

首先,创建一个清晰的项目目录:

aircraft_defect_project/ ├── data/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/ ├── dataset.yaml ├── train.py └── runs/ (训练后自动生成)

将之前划分好的训练集、验证集的图像和YOLO格式标签,分别放入data/images/train/,data/labels/train/和对应的val文件夹。

4.2 数据集配置文件(dataset.yaml)的编写

这是告诉YOLOv8数据在哪、有哪些类的关键文件。

# dataset.yaml path: /path/to/your/aircraft_defect_project/data # 数据集根目录 train: images/train # 训练集图像相对路径 val: images/val # 验证集图像相对路径 # 类别列表,顺序必须与YOLO标签中的class_id对应 names: 0: scratch 1: dent 2: corrosion 3: paint_peeling 4: rivet_defect # 可选:类别数量 nc: 5

4.3 模型选择与训练启动

YOLOv8提供了不同尺寸的预训练模型,从轻量化的ns到高精度的lx。对于缺陷检测,通常sm能在精度和速度间取得良好平衡。

# train.py from ultralytics import YOLO # 加载预训练模型 model = YOLO(‘yolov8s.pt‘) # 使用小模型,可根据需要换为 ‘yolov8m.pt‘ 等 # 开始训练 results = model.train( data=‘dataset.yaml‘, epochs=100, # 训练轮数,可根据早停策略调整 imgsz=640, # 输入图像尺寸 batch=16, # 批次大小,取决于GPU内存 workers=4, # 数据加载线程数 device=‘0‘, # 使用GPU 0,如果是CPU则设为 ‘cpu‘ project=‘runs/train‘, # 结果保存目录 name=‘exp1‘, # 实验名称 pretrained=True, # 使用预训练权重 optimizer=‘AdamW‘, # 优化器 lr0=0.001, # 初始学习率 augment=True, # 启用默认数据增强 patience=20, # 早停耐心值,验证集指标连续20轮不提升则停止 save_period=10, # 每10轮保存一次检查点 val=True, # 训练中验证 )

启动训练:python train.py

4.4 训练过程监控与关键指标解读

训练开始后,YOLOv8会在终端打印日志,并在runs/train/exp1目录下生成大量有用文件,其中最重要的是results.csv和可视化图表。

需要重点关注的指标:

  • 损失函数train/box_loss,train/cls_loss,val/box_loss,val/cls_loss。训练损失应稳步下降,验证损失在后期应趋于平稳或轻微波动。若验证损失上升,可能是过拟合。
  • 精度指标
    • metrics/mAP50-95:这是核心指标,表示在IoU阈值从0.5到0.95(步长0.05)下的平均精度均值。值越高越好,综合反映了模型在不同严格程度下的性能。
    • metrics/mAP50:IoU阈值为0.5时的平均精度,较为宽松,通常值最高。
    • metrics/precisionmetrics/recall:精确率和召回率。在缺陷检测中,我们往往更追求高召回率(宁可错检,不可漏检),然后通过后续工艺或人工复核来排除误检。可以通过调整预测时的置信度阈值来平衡二者。

实操心得:训练初期,每隔几轮就用验证集跑一下推理,可视化一些预测结果。这能帮你直观感受模型在学习什么,以及是否存在明显的错误模式(例如,总是把某些阴影误检为缺陷)。

5. 模型评估、优化与部署考量

5.1 全面评估与错误分析

训练完成后,使用保留的测试集进行最终评估:

yolo val model=runs/train/exp1/weights/best.pt data=dataset.yaml split=test

评估报告会详细列出各类别的AP(平均精度)、精确率、召回率等。错误分析是更关键的一步:

  1. 假阴性(漏检)分析:哪些缺陷没被检测出来?是尺寸太小(小目标问题)?对比度太低?还是与背景过于相似?
  2. 假阳性(误检)分析:模型把什么误认为缺陷?是铆钉的规则排列?漆面的正常反光?还是图像边缘的纹理?

针对这些分析结果,可以反哺数据预处理和增强策略。例如,如果小目标漏检多,可以增加随机裁剪(zoom in)增强,或在模型结构上使用更精细的特征金字塔。

5.2 模型优化与剪枝

对于工业部署,模型大小和推理速度至关重要。

  • 模型剪枝:移除网络中冗余的通道或神经元,在几乎不损失精度的情况下大幅减小模型体积、提升速度。可以使用Torch-Pruning等工具。
  • 量化:将模型权重从FP32转换为INT8,能显著减少内存占用和加速推理。YOLOv8支持导出为INT8格式的ONNX或TensorRT引擎。
  • 知识蒸馏:用训练好的大模型(教师模型)去指导一个小模型(学生模型)训练,让小模型获得接近大模型的性能。

5.3 部署到生产环境的思考

将训练好的模型集成到实际的飞机检测系统中,还需要考虑:

  • 推理流水线:图像采集(无人机/机器人/固定摄像头)→ 预处理(尺寸缩放、归一化)→ 模型推理 → 后处理(NMS非极大值抑制)→ 结果输出(标注、生成报告)。
  • 硬件选型:根据实时性要求选择硬件。云端服务器可用GPU(NVIDIA T4, A10等),边缘端可用Jetson系列、华为Atlas等AI加速卡,甚至一些高性能CPU。
  • 软件框架:常用方案包括将模型导出为ONNX,然后用ONNX Runtime或TensorRT进行高性能推理;或者使用OpenVINO(针对Intel硬件)、TFLite(移动端/嵌入式)进行部署。
  • 持续学习与更新:在实际应用中收集新的、模型判断不准的案例,定期进行增量训练,使模型能适应新的缺陷类型或环境变化。

6. 常见问题与排查技巧实录

在实际使用该数据集和训练过程中,你几乎一定会遇到下面这些问题。这里是我踩过坑后总结的排查清单。

6.1 数据与标注相关

问题1:训练时Loss(损失)为NaN或突然变得巨大。

  • 可能原因:标注文件有错误。例如,YOLO格式的归一化坐标值超过了[0,1]的范围;或者XML文件中有非法字符。
  • 排查:写一个脚本,遍历所有标注文件,检查坐标值是否在有效范围内(VOC格式的像素坐标应为正整数且在图像尺寸内;YOLO格式应在0~1之间)。同时检查图像文件是否都能正常解码。

问题2:某个类别的AP(平均精度)始终为0或极低。

  • 可能原因:该类别的样本数量严重不足;或者该类别的缺陷在图像中极其难以辨认(与背景几乎无区别)。
  • 解决
    1. 检查该类别的实例数量。如果过少,使用前面提到的重采样或数据增强专门针对该类生成更多样本。
    2. 可视化该类别的所有训练样本,看是否标注质量有问题(框不准、漏标)。
    3. 考虑修改模型,例如为该类别在分类损失上增加权重。

问题3:模型总是将背景中的特定纹理(如云层、地面纹理)误检为缺陷。

  • 可能原因:训练数据中缺乏此类“困难负样本”。
  • 解决:进行“困难负样本挖掘”。用初始模型在包含这些背景的图片(可以是没有缺陷的飞机图片)上推理,将模型高置信度误检的区域,作为负样本(背景)加入到训练集中重新训练。

6.2 训练过程相关

问题4:验证集指标波动很大,不稳定。

  • 可能原因:批次大小(Batch Size)设置过小;学习率可能太高。
  • 解决:在GPU内存允许的情况下,增大Batch Size(如从8增至16、32)。这会使梯度估计更稳定。同时,尝试降低学习率(如从1e-3降至5e-4或1e-4),并使用学习率预热(Warmup)和余弦退火(Cosine Annealing)调度器。

问题5:训练很快过拟合,训练集精度很高,但验证集精度上不去。

  • 可能原因:模型容量过大(如用了YOLOv8x)而数据量相对不足;数据增强不够强。
  • 解决
    1. 换用更小的模型(如从l换到s)。
    2. 增强数据增强的强度,特别是加入随机遮挡(RandomErasing)、MixUp、CutMix等更强的正则化增强。
    3. 使用早停(Early Stopping),根据验证集指标提前终止训练。

6.3 推理与部署相关

问题6:模型在测试集上效果不错,但部署到真实场景中漏检严重。

  • 可能原因:领域差异。训练数据(可能是合成数据或特定环境拍摄)与真实场景(光照、相机型号、角度)差异太大。
  • 解决:进行领域自适应。收集少量真实场景的未标注图片,通过风格迁移等技术,使训练数据分布接近真实场景。或者,在真实场景中标注少量数据,进行微调。

问题7:边缘设备上推理速度不达标。

  • 可能原因:模型仍然太大;推理框架未优化。
  • 解决
    1. 对模型进行更激进的剪枝和量化。
    2. 使用针对特定硬件优化的推理引擎,如TensorRT(NVIDIA)、OpenVINO(Intel)、CoreML(Apple)。
    3. 降低推理时的输入图像分辨率(如从640降到480),但这可能会影响小目标检测精度,需要权衡。

这份“飞机表面缺陷数据集”是一个强大的起点,但它不是终点。工业AI的真正挑战,在于如何将实验室里表现良好的模型,稳健、高效、可靠地部署到复杂多变的生产环境中去。这中间每一个环节——从数据清洗、增强策略设计,到模型调优、错误分析,再到最终的工程化部署——都需要像对待飞机安全一样,秉持严谨细致的态度。希望这份超详细的拆解,能帮你避开我当年踩过的那些坑,更顺畅地驶入工业视觉智能检测的赛道。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 10:55:14

从张柏芝机场事件看算法推荐与情感分析的技术原理

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

作者头像 李华
网站建设 2026/9/2 10:54:44

城市管理执法文书管理系统:从手工填表到智能生成的数字化转型实践

简介&#xff1a;本资源是一款面向城市管理执法一线人员与信息化建设者的轻量级文书管理工具&#xff0c;聚焦执法文书制作、打印、查询与统计等核心业务痛点&#xff0c;解决传统手工填表效率低、易出错、难追溯等问题。系统融合人工智能技术实现模板化智能生成&#xff0c;支…

作者头像 李华
网站建设 2026/9/2 10:54:02

Rufus:免费USB启动盘制作工具,5分钟做出Windows 11安装盘

Rufus&#xff1a;免费USB启动盘制作工具&#xff0c;5分钟做出Windows 11安装盘 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus 系统崩溃要重装、想试试新发行版、旧电脑装不上新系统——第一步…

作者头像 李华
网站建设 2026/9/2 10:53:10

动车组重联运行解析:从D3803次看CRH2A编组与调度逻辑

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

作者头像 李华
网站建设 2026/9/2 10:52:33

Python异步机器人框架:订阅推送架构、源码部署与性能优化

简介&#xff1a;haruka-bot-1.2.3 是一个轻量级 Python Telegram Bot 框架库&#xff0c;面向 Python 初中级开发者及自动化运维、消息通知类项目实践者&#xff0c;旨在简化 Telegram 机器人开发流程&#xff0c;支持插件化扩展与快速部署。资源包共20个文件&#xff0c;含16…

作者头像 李华
网站建设 2026/9/2 10:52:32

深信服升级工具zip报错could not find eocd?固件升级避坑指南

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

作者头像 李华