YOLOv10舌象检测与DeepSeek诊断分析:从数据标注到工程落地
1. 舌象检测的特殊性这个任务和通用目标检测根本不是一回事1.1 舌象数据的三重难点做舌象检测之前我以为它就是继承了一个普通单类目标检测任务。把任务拆开来看你会发现问题远不止把舌头框出来这么简单。第一重难点是颜色即特征。通用目标检测里颜色只是辅助线索决定一个检测对象是人还是摩托车主要靠形状和纹理。但在舌象场景中舌质颜色、舌苔颜色本身就是诊断的核心依据——淡红舌和红绛舌的边界往往是渐变的一个像素差不多的色差在检测模型看来是噪声在后续分析中却是关键信息。这意味着你在训练检测器时不能做太重度的颜色增强否则模型会把舌头和肤色接近的嘴唇、面部区域混在一起。第二重难点是姿态和遮挡高度不稳定。伸舌状态、张口的程度、舌头的卷曲方式、上颚是否遮挡舌根、牙齿是否咬住舌尖都会让同一个人的舌象在画面里呈现出完全不同的几何形态。更离谱的是边缘情况舌尖朝上还是朝下、舌头向左歪还是向右歪、是否只有舌尖露出这些都会显著影响检测框的稳定性。我实测下来正常伸舌的状态检测很稳一旦舌体卷曲或者只露出半截漏检率立刻往上走。第三重难点是拍摄环境和设备的方差极大。手机摄像头、摄像头采集的色温、室内灯光偏黄还是偏白、是否开了美颜滤镜都直接影响图像分布。稍微有点图像处理经验的朋友应该明白训练集和测试集的拍摄条件不一致时模型表现下降得特别快。所以做舌象检测脱离数据采集标准谈模型调参基本都是白搭。1.2 数据集自建方案拍摄、筛选与标注我先说结论公开的舌象数据集在数量和多样性上都不够支撑工程化最可行的路线上还是自己搭一套受控环境下的拍摄采集方案。采集阶段建议使用单反或高解析度手机后摄固定机位让被测者坐在均匀光源前面部正对镜头舌头自然伸出超过嘴唇。注意两个细节第一是光源色温固定尽量控制在4000K到5000K的日光色温区间避免暖黄灯光造成的偏色第二是舌头伸出后停顿1到2秒再拍摄因为不少人在伸舌瞬间会下意识回缩拍到的是半截舌头。每人可以拍摄3到5张连同舌头的姿态变化一起纳入候选集。筛选阶段去掉三类图过度模糊的、舌体被牙齿或嘴唇遮挡超过三分之一的、以及曝光严重过曝或过暗导致舌苔纹理不可辨的。这些图即使强行标注训练出来也会拖累模型不如直接丢弃。标注阶段用LabelMe或者CVAT都可以导出YOLO格式。标注标准要提前固定框的边界从哪里开始算我的规则是以舌根后缘舌体与舌咽交界处为下边界舌尖为上边缘左右以舌体轮廓外切为准不包含嘴唇。这个标准必须统一否则不同标注员之间的框差异会成为模型训练中的噪声来源。我实际标注下来总共用了1600多张有效图像单类目标框的质量比数量重要得多。1.3 数据增强取舍颜色类增强要克制数据增强这块我踩过不少坑核心原则一句话几何增强可以放开颜色类增强必须克制。几何增强方面小角度旋转正负15度内、水平翻转、轻微缩放和裁剪都能有效提升模型对姿态变化的鲁棒性。舌象基本左右对称水平翻转不会破坏语义放心用。颜色增强方面HSV色相扰动、随机亮度和对比度调整这些常规手段要非常小心。色相扰动一旦范围过大出现不符合真实舌象的奇异颜色模型会把颜色这条路走偏——它不是去理解纹理和结构而是试图在颜色上做无意义的泛化。我的参数是色相扰动限制在正负5以内饱和度和亮度扰动控制在正负10以内只用来模拟不同设备、不同光线下的轻微偏移而不是大范围造数据。另外还需要一个针对性增强模拟肤色和舌色混淆。可以从训练集里挑一些含脸部和手部区域的负样本图参与训练。模型如果只在舌头单独出现的图上训练到了真实画面里看到人脸和手就容易误检。2. YOLOv10选型与训练调参记录2.1 为什么是YOLOv10选模型时我考虑了YOLOv5、YOLOv8、RT-DETR和YOLOv10。最终选择YOLOv10的理由有三点。第一无NMS的端到端结构。YOLOv10通过双重标签分配和一致匹配机制把NMS从后处理里彻底去掉。这对工程落地非常友好——少一个后处理环节少一类因为NMS参数设置不当带来的玄学问题。常规推理直接输出就是最终结果排查问题更干净。第二推理效率在精度同等水平下有明显优势。我拿相同精度的v8和v10做对比在检测单类、的画面、不太复杂的背景下v10的推理延迟大约低15%到20%。做实时摄像头检测时这几毫秒的差距会直接影响到整体帧率的观感。第三模型体积梯度完善。YOLOv10从n、s、m、l到x都有对应权重n版本权重只有不到6MB完全可以放到嵌入式或低算力设备上。对于舌象检测这种单类目标相对固定场景的任务用n或s版本已经足够不需要上大模型。2.2 训练配置与关键参数复盘我的环境如下PyTorch 2.x单块消费级GPU显存16GB左右CUDA 12.x。代码直接用官方仓库的YOLOv10训练脚本改动不大主要调整的是数据配置和超参数。训练配置上我用了随机初始化的模型和预训练模型各做了一组对比。结果符合预期加载预训练权重的模型收敛快很多最终精度也更高。在1600张的小规模数据下从零训练很容易陷入过拟合预训练权重带来的通用特征尤其有用。关键超参数如下参数设置值说明输入尺寸640x640兼顾精度与速度不盲目上更高分辨率batch size16显存允许范围内尽量大稳定BNepoch200小数据集需要更长训练周期配早停初始学习率0.01用warmup余弦衰减优化器SGD with momentum 0.937Adam在检测头里不如SGD稳数据增强见1.3颜色增强收敛几何增强正常训练中我用的是warmup策略——前3个epoch学习率从0.0001线性升到0.01避免模型在早期就剧烈震荡。200个epoch大概练了3个多小时。2.3 训练中处理过的三个问题问题一过拟合mAP在验证集上波动巨大。第一轮训练到120个epoch时训练集mAP50已经到98%以上但验证集只有82%左右。我把颜色增强进一步收紧同时增加了随机裁剪和Scale验证集mAP稳定提升到接近93%。问题二漏检卷曲舌头。训练集里卷曲样本太少模型对这类形态几乎没见过。解决方法是去原始视频数据里截取卷舌、歪舌、半含舌的帧补充标注集而不是寄希望于增强能凭空造出这种形态。问题三误检面部区域。模型偶尔会把嘴部和下巴区域一起框进去。我把人脸、嘴唇、手等含有肤色和类似形状的照片作为负样本加入训练同时调整了置信度过滤阈值让误检框的置信度普遍低于0.25实际使用时过滤掉低分框即可。最终模型的mAP50达到92.6%mAP50-95在78%左右。对单类舌象检测来说这个精度已经足够支撑后续裁剪和分析流程。3. 检测结果到诊断建议DeepSeek接入的工程化设计3.1 为什么选择大模型生成建议而不是规则引擎检测模型输出的是一堆坐标框。从检测到舌头到生成诊断建议中间有一条巨大的鸿沟。传统做法是把检测到的舌头区域做颜色特征统计然后根据若干阈值写规则舌质偏红则输出舌质红舌苔偏白且厚则输出舌苔白厚。这种方案的问题在于阈值的选取非常脆弱。不同拍摄环境下舌质的LAB色值分布差异极大你为设备A调出来的阈值在设备B上完全失效。更别说舌象属性非常多舌色、苔色、苔厚、润燥、裂纹、齿痕、胖瘦每个属性都要单独定规则规则之间还会相互作用写到最后就是一团乱麻。大模型的好处在于它能接受多维度的特征描述基于训练中获得的医学经验常识输出综合性的分析文本。你不需要为每一种表现写死规则只需要把结构化特征喂给它它就能组织成自然语言描述和参考建议。不过要泼一盆冷水大模型在这个场景中只能做辅助参考分析不能替代专业诊断。这是底线问题后面在接口设计里也要体现。3.2 结构化特征提取与Prompt构造我是怎么把一张裁剪好的舌头图片转成大模型能理解的信息的这里采用了文本结构化方案。我使用OpenCV对检测框内的舌头图像做颜色统计转换到LAB色空间计算L、A、B通道的均值和标准差计算舌质区域与舌苔区域的色差判断舌苔覆盖程度边缘密度统计间接判断裂纹和齿痕的显著程度舌苔厚度用图像纹理的能量和对比度估算这些数值连同一小段自然语言描述组成一个结构化的输入文本。举个实际例子舌体区域LAB均值L54.3A21.6B14.8。舌苔覆盖面积为全舌的40%苔色偏白边缘清晰舌质底色偏红纹理粗糙度中等未见明显裂纹。Prompt设计上我会在system prompt里明确角色和约束设定为传统医学知识参考助手要求输出三部分内容——舌象特征概括、可能的健康状态参考、生活调理建议最后必须附带以上内容仅供参考不能替代专业医疗诊断的提示。User prompt就是结构化特征文本加用户补充的体质信息可选。这里有一个要点不要把所有特征数值都一股脑塞给模型。特征越多模型越容易在无关维度上过度解读。我最终只传了五个核心维度舌质色、苔色、苔量、纹理状态、综合说明让模型有足够信息生成建议又不至于被数据噪声带偏。3.3 接口调用容错与输出约束工程化调用大模型接口不能像写脚本一样直接调函数就完事。我在接入设计中做了三层防护。第一层是用同步阻塞改成带超时的异步调用。检测模型推理和接口调用放在同一个线程里一旦接口响应慢整个检测流程都会被卡住。我用单独的线程池管理接口调用设置20秒超时超时后返回重试。图片和视频分析对实时性要求不同摄像头模式下直接显示检测框不阻塞UI分析结果滞后返回。第二层是输出解析与格式兜底。模型返回的结果可能是JSON格式也可能因为对话历史累积变成纯文本。我在解析时做了两层校验先尝试按JSON解析失败则直接作为纯文本显示。即使解析失败也不影响整体功能保证程序不崩溃。第三层是内容安全约束。我在接口调用前增加了一个过滤层如果检测置信度过低或者裁剪出的舌头区域实在太模糊就不调用大模型直接返回图像质量不足建议重新拍摄。这样避免大模型在低质量输入上产生不稳定输出也减少了不必要的接口调用成本。4. 图像、视频、摄像头三种模式的统一架构4.1 推理引擎的抽象与统一输出很多初学者做这类项目喜欢为图像、视频、摄像头各写一套逻辑结果代码里到处是cv2.imread、cv2.VideoCapture的重复调用改一个功能要动三处。我一开始也是这么干的后来重构了一次把所有检测逻辑收敛到一个统一的推理引擎类里。核心设计是detect_img、detect_video、detect_camera其实共用同一个detect(frame)方法返回统一的检测结果对象。结果对象里包含检测框坐标、置信度、裁剪后的舌头区域图像、以及状态标记是否适合调大模型分析。图像模式负责读取单张图视频和摄像头模式负责按帧率把画面喂给这个统一引擎。这样做的好处是图像模式下验证过的检测和后处理逻辑在别的模式下天然一致不会出现同一张图片在不同模式下检测结果不同的怪异情况。4.2 视频模式抽帧与触发策略视频模式最容易犯的错是每帧都做检测每个检测结果都调用大模型。视频帧之间存在大量冗余信息连续帧的检测结果几乎一模一样逐帧分析纯属浪费计算资源逐帧调大模型接口更是直接把成本拉爆。我的方案是设计了一个触发式分析策略视频读取线程以较快帧率做检测比如每秒检测5到6帧但只有当连续若干帧检测结果稳定坐标偏移小于阈值、置信度大于0.7、舌体面积占画面比例合理时才抽取该帧送入大模型分析并且同一段视频只分析一次后续帧直接沿用分析结果。这样做有两个效果一是整体响应速度大幅提升二是输出结果不会因为相邻几帧的微小差异而反复跳变。实际跑下来一段5分钟的视频只需要调用一两次大模型接口即可画面里的检测框却始终是实时更新的。4.3 摄像头模式多线程与实时显示摄像头实时检测是这个项目里对工程要求最高的部分因为它的运行模式是相机采集、模型推理和画面显示必须在同一秒内完成多次一旦某一步阻塞画面就会卡顿。我在摄像头模式下用了双线程结构。主线程负责OpenCV读取摄像头帧并显示画面推理线程从队列里取到最新帧后跑模型检测检测结果返回给显示层叠加画框。队列里只保留最新的一帧过期帧直接丢弃避免积压。另外摄像头模式下有一个人机交互细节值得注意不要一检测到舌头就弹窗显示诊断建议那会打断用户的实时观察体验。我的做法是画面中实时显示检测框和置信度用户在图像稳定后按空格键或点击开始分析按钮系统才触发大模型调用分析结果展示在侧边栏。这个交互既保留了实时检测的流畅感又让用户掌控分析的主动权逻辑上更符合使用场景。分辨率方面摄像头输入我直接从1280x720缩放到640x640再推理。在普通的消费级GPU上YOLOv10n的推理速度轻松做到60到80毫秒一帧加上显示和采集的延迟整体流畅度足够使用。5. 实测表现、翻车场景与后续扩展5.1 几组真实场景下的表现在受控拍摄条件下这个系统的表现让我满意。一张光照均匀、舌头自然伸出的照片检测框非常稳定舌根到舌尖完整覆盖置信度基本在0.9以上。裁剪出的舌头区域送入大模型分析输出的舌象描述和人工观察高度一致。室内自然光场景下正常伸舌2到3秒摄像头模式下检测框的抖动幅度很小。置信度在0.75到0.9之间浮动触发分析的稳定帧能在一个呼吸周期内成功抽取。分析结果从调用到显示大约3到5秒。我把不同时段的采集数据做了对比发现色温变化的影响确实存在。同一人早上在窗边自然光下和晚上在暖黄台灯下拍摄舌质的LAB统计差异能超过10%但生成的文字描述仍然保持一致。这说明大模型对特征文本的容忍度比我想象中要高只要特征提取环节不过度依赖单一场景的阈值整体输出的稳定性是可靠的。5.2 最容易被忽略的失败场景翻车场景主要集中在两个地方。第一个是背景色与舌体颜色高度接近。如果被测者穿红色衣服或者身后有大面积红色背景模型会把背景区域误检成舌头置信度甚至超过0.6。这是因为舌质本身的红色通道特征太强模型学到的部分特征其实和颜色绑定。我通过增加背景多样的负样本以及在后处理中增加一条检测框内颜色标准差过低则过滤的规则把这类误检压到了可接受范围。第二个是过度用来分析模糊帧。刚开始做摄像头模式时我直接把置信度0.8以上就送入大模型结果有几次画面轻微运动模糊大模型输出的描述出现明显偏差比如把正常舌象描述成舌体胖大。后来我在触发条件里加上了图像清晰度判断使用拉普拉斯方差过低就直接跳过这类问题基本消失。5.3 这套架构还能往哪扩展走完这一整套流程最大的收益不只是实现了一个舌象诊断系统而是沉淀了一套检测大模型分析的通用架构。同样的思路换一个检测目标、换一组特征提取方式完全可以直接迁移到其他视觉分析场景。具体的扩展方向可以考虑这些换用YOLOv10-seg做舌体实例分割把舌质和舌苔区域精确分割出来比检测框裁剪更适合做精细特征分析用RGB以外的色彩空间特征Lab、HSV直方图做更丰富的特征输入检测和分析逻辑打包成一个服务通过HTTP或者gRPC对外提供API前端只负责传图接收结果。我实际运行这套系统的经验是检测模型训练再怎么花时间都是值得的因为后续所有分析的质量上限都由它决定。好的检测结果是稳定提示词、稳定输出的前提检测框稍微偏一点裁剪出来的舌头区域就会混入嘴唇或牙齿大模型的分析质量立刻下降。把这层地基打好后面接什么模型都会顺畅很多。

相关新闻

AI辅助论文写作全攻略:专科生如何选对工具避开坑

AI辅助论文写作全攻略:专科生如何选对工具避开坑

每年三四月,我的朋友圈里就开始涌现一批“论文焦虑”患者,而我这两年被问得最多的一个问题,就是“有没有靠谱的AI论文网站可以照着用”。专科生写毕业论文这件事,难度其实一点都不比本科低:时间更紧、实习任务压身、学…

2026/10/18 14:47:45 阅读更多 →
JQuickExcel 批量导入:用 importDataInBatch 控制大文件消费边界

JQuickExcel 批量导入:用 importDataInBatch 控制大文件消费边界

JQuickExcel 批量导入:用 importDataInBatch 控制大文件消费边界 tags: #JQuickExcel #JavaExcel #开源 #POI #Excel工具 更多示例: JQuick-Excel 官网示例 https://www.jquick.org/jquick-excel/#demo-formulas0005 简介 我处理大 Excel 导入时,最先…

2026/10/18 14:47:45 阅读更多 →
Vue3+FastAPI+Neo4j知识图谱网页应用全栈开发实践

Vue3+FastAPI+Neo4j知识图谱网页应用全栈开发实践

简介:知识图谱以图结构组织实体与关系,是现代智能应用的重要基础设施。图数据库作为其核心存储引擎,通过节点和边原生表达复杂关联,避免关系型数据库多表JOIN的性能瓶颈。Cypher查询语言则提供声明式图遍历能力,让深度…

2026/10/18 14:47:45 阅读更多 →

最新新闻

寄存器分配与内存访问模型:pto-isa编译器后端核心设计解析

寄存器分配与内存访问模型:pto-isa编译器后端核心设计解析

1. 项目概述:为什么要在 CACC 体系里单独拧出“指令集后端”来说先说结论:寄存器分配和内存访问模型,是编译器后端里最接近“物理真实”的一层。你写的算子代码再漂亮,调度策略想得再周全,最后都要落到“哪个值放哪个寄…

2026/10/18 15:32:06 阅读更多 →
一颗芯片如何从想法变成可出货的硅片,全流程解析

一颗芯片如何从想法变成可出货的硅片,全流程解析

由于自己一直想做FPGASDR实现一个蓝牙功能,就顺便发散下:一颗芯片如何从想法变成可出货的硅片下面按真实产业顺序,把芯片从规格、行为/架构、RTL、验证、综合、DFT、物理设计、掩模、晶圆制造,到封装测试和量产写完整。1. 全流程总…

2026/10/18 15:32:06 阅读更多 →
163MusicLyrics:从粘贴歌曲链接到整库扫描导入的LRC歌词下载

163MusicLyrics:从粘贴歌曲链接到整库扫描导入的LRC歌词下载

163MusicLyrics:从粘贴歌曲链接到整库扫描导入的LRC歌词下载 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 163MusicLyrics 是一款基于 .NET 的开源歌词下载…

2026/10/18 15:32:06 阅读更多 →
实时数仓从入门到落地:架构演进、分层设计与技术选型全解析

实时数仓从入门到落地:架构演进、分层设计与技术选型全解析

做了这么多年数据,我最经常被问到的一句话是:我们的报表为什么不能实时看?以前我还能解释“离线条路最快也要T1”,但这两年再拿这个理由搪塞业务,基本没人买账。实时大屏、实时风控、实时库存预警、实时供需调度&#…

2026/10/18 15:32:06 阅读更多 →
小型工厂ERP源码部署与制造流程闭环实践

小型工厂ERP源码部署与制造流程闭环实践

简介:这是一套专为小型工厂定制的轻量级ERP系统源码,面向Java初/中级开发者及中小型制造企业IT人员,解决传统工厂在销售、采购、生产、库存等环节数据割裂、流程低效的问题。资源包仅5KB,含3个核心文件:index.html为前…

2026/10/18 15:32:06 阅读更多 →
SpringBoot+Vue足球青训俱乐部管理系统:从架构设计到部署实战

SpringBoot+Vue足球青训俱乐部管理系统:从架构设计到部署实战

开题选系统,最怕的就是撞车。每年到了三四月份,一堆人盯着那几个经典题目反复改——图书管理、宿舍管理、医院预约,做得再好答辩老师也看麻了。我之前带过的一个学弟选的就是这个方向:SpringBootVue Web足球青训俱乐部管理后台系统…

2026/10/18 15:31:05 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →