全色影像水体提取:阈值分割原理与后处理实践
简介针对全色影像水体提取的专题资源聚焦阈值分割技术在单波段遥感影像中的应用。全色影像空间分辨率较高、地表细节丰富因此适合用于快速水体识别适合地理信息系统、环境监测、城市规划等领域的初学者或研究人员帮助快速理解从预处理、阈值设定到后处理的完整图像分割流程。压缩包共2个文件包含1个可直接运行的Matlab脚本和1张BMP格式结果示例图整体体积约2.18MB便于下载后快速验证效果。已有1270人学习下载。脚本实现覆盖灰度特征选择、Otsu动态阈值计算、图像二值化以及连通域去噪等环节输出图可直观对照分割结果对需要快速搭建水体提取原型、熟悉阈值分割算法或开展教学演示的读者具有较高参考价值。1. 水体提取的“不高科技”开局为什么全色影像还靠阈值分割一个听起来没那么“智能”的方法往往才是遥感影像处理里最稳的起手式。水体提取这件事在地理信息系统、环境监测、城市规划里都有需求但落到全色影像上最常用、最容易被低估的恰恰是阈值分割它只用一个灰度界限就把“水”和“非水”切开。真正反直觉的地方在于随着深度学习分割模型满天飞针对全色影像这种单波段数据阈值分割依旧没有退出工程现场——因为它切中的正是全色影像最本质的物理规律水体在可见光到近红外区间对入射能量的吸收特征极其稳定灰度分布上的分离度天然可观。理解为什么一个阈值就能完成水体提取等于理解了遥感分割问题的起点。这份专题资源和配套脚本 water.m、输出样例 out.bmp恰好就是一条从灰度直方图到二值水体的完整链路值得把每一环都拆开看看。2. 全色影像的灰度物理为什么水体在直方图上“自成一段”2.1 单波段影像到底记录了什么样的信息全色影像通常指只有一个波段的灰度图像它的灰度值不是随意的“亮度”概念而是地表物体在某个宽谱段范围内反射辐射能量的积分结果。空间分辨率高、纹理细节丰富是它最大的优点但代价是缺少多光谱那样的波段组合自由度。你没法像看多光谱影像那样用一个比值指数把植被、土壤、水体分开所有可分性都压缩在灰度这一个维度上。正是这种“只有灰度”的限制把问题逼到了最简单的形态水体在影像上表现出低反射、高吸收的特性尤其是在近红外响应的波段区间内水的吸收系数远高于绝大多数地表覆盖物。这意味着在影像的灰度值分布里水体区域的像素会聚集在灰度较低的一端与周边植被、裸地、建筑物形成天然的灰度落差。灰度直方图上呈现为低值区出现一个可辨识的峰或者斜坡这就是阈值分割能成立的第一前提。2.2 直方图双峰假设分割的几何直觉阈值分割的底层逻辑建立在直方图形状假设上。理想的自然后场景里背景和目标分别对应直方图上的两个峰阈值应该取在两峰之间的谷底。放到水体提取场景中水体是低灰度目标非水体是高灰度背景理想情况下直方图上会有一个“低峰 高峰”的双峰结构。但要留心一个常见的误解真实全色影像的直方图极少出现经典意义上的两组独立钟形峰更多是“一个主峰加一个肩部斜坡”甚至“单峰带长尾”。水体的贡献往往淹没在主峰的低灰度斜坡里。此时的关键不是寻找到视觉意义上的“两峰夹一谷”而是把阈值选择问题转化为“找一个能把低灰度区域切出去的分割点”。理解这一点你就明白为什么阈值分割的工程实现里有那么多自动选阈值的变体。2.3 灰度值从哪里来辐射定标对阈值的影响全色影像的灰度值可以是原始数字化值DN值也可以是经过辐射定标后的反射率或辐亮度。阈值的水位标定必须跟输入数据的尺度保持一致这是实际操作里最容易被忽略的一环。原始 DN 值在 0 到 1023 或 0 到 255 的整型范围里浮动不同传感器、不同太阳高度角采集到的 DN 分布会整体平移或伸缩反射率则被归一化到 0 到 1 的浮动小数区间。由此导出一个实际操作上的关键推论用一套固定阈值去处理不同成像条件、不同传感器的全色影像阈值大概率会漂移。water.m 这类脚本如果直接对一个常数阈值硬编码换景影像就翻车。自动阈值方法的价值恰恰在于它让分割点跟着直方图形态走而不是跟着影像的绝对灰度值走因此它对成像条件的差并不敏感。这也是我建议所有读这份资源的人重点看脚本里阈值来源在哪一步——是人为设定的常数还是算法自适应计算出来的。3. 阈值从哪里来固定阈值、直方图谷底与最大类间方差的机制推导3.1 手工选阈值的工程直觉和它的局限阈值分割最先让人想到的办法就是打开直方图用鼠标在谷底处画一条线。这种手工方式在交互式图像处理软件里到今天依然常用原理很简单直方图的谷底是两个类别在灰度空间里最难以归属的位置把阈值放在谷底错分概率在经验上最小。局限也很直接。肉眼判断谷底带有主观性而且当真峰与背景峰的重叠区域很宽时所谓的“谷底”可能根本不是一条清晰的谷而是一段平坦的过渡带。另一个陷阱是当水体面积占比很小的时候水体对应的灰度峰在直方图上高度极低甚至淹没在噪声里肉眼很难定位。于是工程上只能把自动阈值当作主要手段手工阈值退化为辅助干预。3.2 Otsu 的数学动因为什么最大化类间方差等于分割最优Otsu 方法提出时解决的是一个精确性问题在不知道目标占比、直方图形状也不规整的情况下能否由算法单值确定一个“最合理”的阈值。它的核心思想是把分割看成两类像素的划分然后遍历灰度级找到使两类之间离得最远、类内最紧凑的灰度级。对灰度级为 0 到 L-1 的影像设阈值 t 将像素分为水体系灰度 ≤ t与非水体系灰度 t全局均值为 μG。定义 p(i) 为灰度 i 的出现概率ω0(t) 为水系像素占比μ0(t) 为水系灰度均值ω1(t)、μ1(t) 为非水系的对应值。类间方差定义为σB²(t) ω0(t) * ω1(t) * (μ0(t) - μ1(t))²这个公式的机制值得展开ω0 与 ω1 的乘积表示两类“相遇”的概率当两类占比接近时乘积最大均值差的平方表示两类灰度中心的分离程度。最优阈值就是让这个乘积达到峰值的 t。它不要求直方图双峰也没有外部参数完全由灰度分布驱动。因此 Otsu 成了水体提取脚本里最常见的自动阈值求解器。对应到 water.m 这类脚本里核心循环也就是从 t0 到 tL-1 累加概率、更新两类均值、计算类间方差迭代替换。Matlab 的graythresh直接封装了这套逻辑使用时要注意它输入的是归一化到 0 到 1 的灰度数组而不是原始 DN 值这一点最容易踩坑。3.3 直方图单峰时的替代方案百分位阈值与三角阈值Otsu 并非万能。当影像里水体面积占比极小或者水体与阴影在灰度上连续过渡时直方图呈现单峰加长尾形态Otsu 求出的类间方差最大值可能落在主峰的肩部把大量非水体背景错误划入水体。这时工程上常用两种替代方案。三角阈值是直线逼近的思路在直方图最高峰处拉一条线到底部最远端计算直方图各方条到这条线的垂直距离距离最大的灰度位置即阈值。它的直觉是“切断一个斜坡”适合目标只占直方图低频小段的场景。百分位阈值则更粗暴一些先统计灰度累计直方图直接取累计占比 5% 或 10% 位置对应的灰度作为阈值。这种做法的隐含假设是水体在影像里占比不超过该百分位在平原水体遥感图上往往成立但在宽阔水域或季节性泛滥场景里会失效。我在阅读这类脚本时常用的判断标准是先跑一遍 Otsu看分割结果里水体是否连成大片、边缘是否符合水系走向再决定是否需要降级到百分位约束。4. 从阈值到水体边界二值化之后的形态学后处理链路4.1 粗分割之后的典型病灶椒盐噪声、孔洞与破碎连通域阈值分割的输出是一张二值图但直接拿它当作水边界是不现实的。噪声像素在影像上呈现孤立亮点或暗点在二值图上会变成散布在非水体区域的白色斑点水体内漂浮的藻类、船舶、波浪纹理则形成孔洞细窄的河流可能被分割成断续线段连通性被切断。这些是阈值分割后处理要解决的三大典型问题water.m 这类脚本里后处理部分的代码长度往往超过阈值计算本身。后处理的顺序也很讲究先消除离散噪声点再做连通性修复最后填补目标内部孔洞。如果一上来就做膨胀弥补河流断裂孤立噪点的面积也会跟着被放大之后再做噪声滤波反而会把刚接上的断口又断开。顺序错了结果就是噪声清了河道也断了或者河道接上了噪声也留下了。4.2 形态学开闭运算与最小连通面积滤波的参数窗口形态学处理里开运算先腐蚀后膨胀用于去掉目标外部的孤立噪点闭运算先膨胀后腐蚀用于填补目标内部的细小孔洞。选择窗口大小时结构元素应小于最细水体的宽度否则开运算会把细窄的支流直接抹除。对河流提取常见的结构元素是 3×3 或 5×5 的方形这和影像空间分辨率有关分辨率越高同一河道占用的像素宽度越大可用的窗口尺寸也越大。在代码实现层面Matlab 的bwareaopen是对二值图做最小连通面积过滤的直接入口。它删除像素数少于指定阈值的连通域作用机理是统计每个连通区域的面积再把小于阈值的区域整体置为背景% 假设 bw 为阈值分割得到的二值图水体像素为 1 minArea 50; % 面积阈值小于 50 像素的连通域视为噪声 bw_clean bwareaopen(bw, minArea); % 用闭运算填补水体内部的小孔洞 se strel(square, 5); % 5x5 结构元素按水体最窄宽度调整 bw_closed imclose(bw_clean, se); % 再次去除由补洞引起的边缘毛刺保持边界平滑 bw_final bwareaopen(bw_closed, minArea);这里bwareaopen的 minArea 是重要参数它应该结合影像分辨率和最小目标尺寸倒推如果一像素对应 10 米地面距离最小需要保留的河流宽度是 100 米那么连通域面积至少需要保留等效于 10 像素宽、延伸若干像素的条形区域面积阈值不宜设得过高否则细长型河流会被当作噪声摘除。这也是一个常见翻车点——把 minArea 设得太大整条支流直接消失后处理变成伤害。4.3 边界平滑与栅格矢量化之间的连续处理链如果水体提取的终点是 GIS 分析二值图还需要转为矢量面。栅格转矢量的质量取决于二值图边界的锯齿程度阈值分割天生边缘参差不齐直接转换会产生大量多余节点。常规做法是先对二值图做一次中值滤波或高斯平滑再做轮廓提取和简化也可以先膨胀再腐蚀一次即闭运算让边界凹陷处被填充水岸线的锯齿程度明显下降。值得留意的是在不同软件里“提取边界”的实现是不一致的。Matlab 里bwboundaries返回每个连通域的外边界像素坐标集合边界排序按连通域编号依次输出转为面要素需要再经过坐标转换、节点抽稀。从 out.bmp 这样的输出样例来反推原始脚本很可能止步于二值图输出并未做矢量化。如果你是奔着“从影像到水面边界”去的拿到二值图后还要自己补一条矢量化的处理链。5. 全色影像水体提取避坑阈值漂移、阴影漏提与虚假连通5.1 换一景影像固定阈值就不灵了现象同一段脚本第一景影像水体提取效果很好水体完整、岸线清晰换到另一景同地域的影像结果水体大面积丢失只提取出零星碎片。原因全色影像的灰度值受太阳高度角、大气条件、传感器增益影响不同成像时刻的 DN 值分布整体偏移。脚本里写死了一个绝对阈值适用于第一景影像的灰度水位对第二景影像来说已经滑到了水体灰度峰之外。解决把阈值计算改为直方图自适应。在 Matlab 里优先使用graythresh(bw)自动算阈值再把阈值乘以 255 还原回原始 DN 尺度进行比较。如果影像有明显的大气噪声先在分割前做一次去噪预处理避免让噪声峰干扰阈值计算。5.2 山体阴影被当成水体提取出来现象结果图上出现大面积片状连通区域形状沿山体走向分布面积远大于实际水面。原因山体阴影区的反射能量极低灰度值与水体同样落在直方图低端本质上无法仅靠灰度阈值区分。这是全色影像水体提取的物理极限不是阈值选得不够好。解决引入地形辅助数据做掩膜。有 DEM 时先按坡度和坡向生成阴影掩膜在阈值分割后的二值图中将阴影区域直接删除。没有 DEM 时利用水体多在低海拔、平坦区域的空间常识结合连通域的形状特征做启发式过滤水体的连通域通常呈河网状或面状边界平缓山体阴影的连通域边缘曲折、内部纹理粗糙可计算连通域边界长度与面积之比形状指数来筛除。5.3 云影边界处产生虚假条带现象影像中有云影遮盖时阴影边缘附近出现条带状的高亮误提区呈狭长形与真实水体粘连或平行。原因云影边界处存在明显的灰度突变二值化时这一区域由于灰度介于水体与亮背景之间最容易被阈值切开后形成一条狭窄的边缘带。它本质上是“边缘像素归属模糊”的产物。解决对二值图做断线处理删除面积占连通域比例过小的狭长域或者对原始影像做边缘检测将落在强边缘附近的误提像素反向剔除。实际操作中先做一次形态学开运算再用bwareaopen过滤一般能清除大部分窄条。5.4 水体内部出现大量孔洞水体变成“斑马纹”现象分割结果里水体区域散布大量小孔洞连水面都变得支离破碎面积统计严重偏低。原因水面波纹、悬浮物、船舶等亮度较高的干扰像素在阈值之上被分到背景类形成水体内的孔洞。如果阈值偏低这类孔洞会更多如果后处理闭运算窗口太小填补不了较大孔洞。解决先增大闭运算的结构元素尺寸注意不要超过最窄水道的宽度如果填补效果仍然不足则改用填充孔洞算法——在二值图中对背景做连通域标记与影像边界相连的背景视为外部背景其余被水体包围的背景区域置为水面。在 Matlab 里可以用imfill(bw, holes)直接实现这个操作比盲目加大闭运算窗口更精准。6. 为什么坚持阈值分割这一条路准确率之外的工程取舍如果只说“阈值分割简单、快、易实现”那是在回避真正值得思考的问题在机器学习分割已成熟的今天为什么水体提取入门资料还要从阈值入手我的理解是阈值分割提供了一个最清晰的误差归因链路。深度学习模型内部是一个黑匣子错分了你很难说清楚是训练样本问题、特征学习问题还是边界回归问题而阈值分割的每一步——从直方图形状到阈值位置再到后处理参数——都是可解释、可调节、可追溯的。对一个刚接触影像处理的人找不到比这更好的切入点去建立“灰度分布影响分割结果”这件事的手感。从工程选型的角度阈值的适应场景是“快速概查、指标粗估、样本预标注”。它不适合高精度水体边界测绘但适合在数据量巨大、需要快速产出一版水体范围图做资源普查的场景里跑第一遍。很多所谓的新方法实际上就是在这个粗分割结果之上叠加深度学习精修用阈值分割做候选区域筛选用语义分割做边界优化两者不是替代而是接力。进阶方向也很明确一是把固定阈值升级为局部自适应阈值把影像分块每块单独计算 Otsu 阈值解决光照不均匀问题二是引入多尺度分析在不同分辨率影像上分别提取水体再合并结果改善细小水体的连续性三是在阈值分割后接一个形状约束利用水体的延展性、边界平滑度等先验特征过滤误提区域。out.bmp 这类样例的价值就在于此——它不只是结果展示还是一个可对照的基准你可以改阈值、改后处理参数重新跑 water.m看输出影像与样例的差异从而理解每个参数在控制什么。从那以后我每次拿到新的全色影像做水体提取都强制自己先走一遍完整链路看直方图、算自动阈值、对比固定阈值结果、检查后处理参数然后才考虑要不要上更复杂的模型。这个过程帮我避开了绝大多数因为“工具好用”而忽略数据本身特性的翻车。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Prompt设计实战指南:从模糊指令到精准AI输出

Prompt设计实战指南:从模糊指令到精准AI输出

简介:《AI引擎:Prompt指令设计绿皮书》是一份面向AI初学者与新媒体从业者的实用型Prompt工程指南,聚焦解决ChatGPT、Claude、Bard等大模型使用中“指令写不准、输出不达标”的核心痛点。全书系统拆解指令设计的7大技巧公式(如明确…

2026/10/18 12:09:17 阅读更多 →
计算机网络复习地图:从因特网发展到五层模型,串起核心考点

计算机网络复习地图:从因特网发展到五层模型,串起核心考点

简介:这份《计算机网络》课件源自谢希仁经典教材,是电气信息类与计算机类专业本科生、研究生学习网络原理的配套PPT,也可供网络工程技术人员参考。课件共1173页,以1个PPT文件呈现,压缩包约20.32MB,内容按章…

2026/10/18 12:09:17 阅读更多 →
AirParrot 2.6.2 跨协议屏幕镜像工具:原理、配置与延迟调优

AirParrot 2.6.2 跨协议屏幕镜像工具:原理、配置与延迟调优

简介:AirParrot 2.6.2 是一款轻量实用的无线投屏工具,面向需要在会议室、教室、培训室等场景中将电脑画面实时共享到投影设备的用户。它借助局域网 WLAN 连接,只要电脑与投影仪处于同一网段,便无需额外线缆或硬件,即可…

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

最新新闻

基于MATLAB的视频行人检测与跟踪系统实战解析

基于MATLAB的视频行人检测与跟踪系统实战解析

前阵子我帮一家园区做监控视频的离线分析,需求不复杂:统计每条通道一天的行人流量,最好还能画出每个目标的行走轨迹。人工盯录像实在不现实,一小时快进看完基本就是碰运气。后来我用MATLAB搭了一套视频行人检测与跟踪系统&#xf…

2026/10/18 12:59:42 阅读更多 →
PHP原生生成Excel:不装Composer轻松导出xlsx

PHP原生生成Excel:不装Composer轻松导出xlsx

简介:在PHP后端开发中,Excel文件生成是数据导出、报表下载等场景的高频需求。这套源码示例围绕“PHP生成Excel文件”提供完整入门演示,适合需要快速实现表格导出功能的初中级开发者参考使用。压缩包共2个文件,RAR格式,…

2026/10/18 12:59:42 阅读更多 →
Spark 2.3.0无Hive版部署指南:轻量级生产就绪实践

Spark 2.3.0无Hive版部署指南:轻量级生产就绪实践

简介:本资源是专为大数据工程师与 Spark 高级使用者定制的 Spark 2.3.0 精简发行版,聚焦 Hive on Spark 场景下的轻量集成需求——在不捆绑 Hive JAR 包的前提下,实现 Spark 对 Hive 元数据与表数据的访问能力,适用于已部署独立 H…

2026/10/18 12:59:42 阅读更多 →
零分配流式CSV解析器:23GB大文件秒级吞吐实战

零分配流式CSV解析器:23GB大文件秒级吞吐实战

简介:本资源是一份面向C#中高级开发者的高性能CSV文件读取实战方案,聚焦大数据量场景下的速度瓶颈与内存优化问题。针对9GB、1.2亿行14列的极端规模CSV文件,提供可在8秒内完成读取与初步显示的完整工程实现,适用于金融数据清洗、日…

2026/10/18 12:59:42 阅读更多 →
Nexus 3.30.0 Windows 安装避坑指南:JDK 8 与端口冲突解决方案

Nexus 3.30.0 Windows 安装避坑指南:JDK 8 与端口冲突解决方案

简介:本资源为Nexus Repository Manager 3.30.0-01正式版Windows 64位安装包,面向Java开发者、DevOps工程师及企业级Maven仓库搭建者,用于快速部署本地或私有化构件仓库,解决依赖代理缓存、多源聚合、安全发布与权限管控等核心问题…

2026/10/18 12:59:42 阅读更多 →
微信小程序英语学习平台:Spring Boot+MySQL全栈实践指南

微信小程序英语学习平台:Spring Boot+MySQL全栈实践指南

简介:这是一套面向计算机专业本科生的毕业设计级微信小程序实战项目,聚焦英语学习场景下的用户互动与知识管理需求,适用于Java后端开发、小程序前端及全栈课程设计实践。资源包含1221个文件,涵盖111个Java后端代码(SSM…

2026/10/18 12:58:41 阅读更多 →

日新闻

基于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 阅读更多 →