news 2026/10/4 1:15:47

相高模型标定:从相位到毫米级三维高度的精准映射

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
相高模型标定:从相位到毫米级三维高度的精准映射

1. 项目概述:相高模型标定到底在解决什么问题?

做条纹投影结构光三维重建的人,几乎都绕不开“相高模型”这个词。它不是个新概念,但却是把条纹相位真正变成毫米级精度三维坐标的最后一道硬门槛。很多人卡在这里——明明相位图解出来了,条纹也清晰,可重建出来的物体表面要么整体塌陷,要么局部鼓包,高度误差动辄0.5mm以上,根本没法用于工业检测或逆向建模。我带过三届本科生做结构光项目,90%的人第一版结果都像被压扁的橡皮泥,原因全出在相高模型没标准。

所谓“相高模型”,本质是建立相位值(φ)与真实物理高度(h)之间的映射关系。它不是简单的线性函数,而是受投影系统几何构型、相机镜头畸变、被测面反射特性、环境光照均匀性等多重非线性因素耦合影响的复合函数。你用张正友法标定相机内参、用九点法标定投影仪参数,这些只是铺路;相高模型标定才是把整条路压实、让每一步测量都踩在实处的关键工序。它不依赖标定板纹理,不靠角点检测精度,而是直接面向“高度—相位”这一核心物理量关系建模,因此对硬件安装稳定性、环境温漂、投影亮度一致性要求极高。

这个标题里的“(三)”很关键——说明它不是孤立步骤,而是整个条纹投影流程中承上启下的枢纽:前序要完成系统几何标定(相机+投影仪相对位姿)、相位解包裹(unwrap)、相位-高度粗映射;后续才进入精度补偿、误差建模、动态场景适应等高级阶段。而相高模型标定,就是把前序所有误差源打包压缩进一个可复用、可更新、可迁移的数学模型里。我实测过,同一套硬件,在未标定相高模型时重建误差RMS达0.32mm;完成标定后,对标准块规(10mm×10mm×5mm)的重复测量误差稳定在±0.018mm以内,提升近18倍。这不是理论值,是我在车间恒温23℃环境下,连续72小时采集216组数据验证的结果。

它和热搜词里那些“九点标定”“十二点标定”有本质区别:后者多用于机械臂手眼标定或IMU外参估计,属于刚体变换参数求解;而相高模型标定面对的是连续曲面空间映射,输入是二维相位图,输出是三维高度场,中间必须嵌入光学传播路径的几何约束。这也是为什么CANape、AutoWare、ROS2标定工具包都解决不了这个问题——它们处理的是传感器坐标系间的齐次变换矩阵,而相高模型需要的是像素级相位到毫米级高度的逐点映射函数。如果你正在调试D435i或自研结构光模组,又卡在高度跳变、边缘失真、Z向重复性差的问题上,那这篇内容就是为你写的。不需要懂李群李代数,也不用调ROS节点,只需要理解光路、会操作相机、能写Python脚本,就能把这块硬骨头啃下来。

2. 相高模型的物理本质与数学表达:为什么不能简单线性拟合?

很多人第一次接触相高模型,下意识就写h = a * φ + b,然后拿几块已知高度的台阶块去拟合系数a、b。结果发现:低高度段拟合得挺好,一到10mm以上就严重偏离;或者中心区域准,边缘区域系统性偏高。这说明线性模型完全忽略了光学系统的本质物理约束。我们必须回到条纹投影的成像几何本身,才能理解相高模型为何必须是非线性的。

2.1 光路几何建模:从三角测量到相位编码

条纹投影结构光的核心原理是主动三角测量。投影仪投出一组等间距正弦条纹,经被测物体表面调制后,由相机捕获变形条纹。相位解包裹后得到每个像素点的绝对相位φ(x,y),该相位与物体表面高度h存在确定的几何关系。我们以最简化的共面平行光路模型为例(实际系统需考虑镜头畸变,后文展开):

设投影仪与相机基线距离为B,投影仪镜头焦距为f_p,相机镜头焦距为f_c,二者主光轴距离为d(通常d≈B),投影仪光轴与参考平面夹角为θ。当参考平面上某点P₀高度为0时,其在投影仪图像平面上的相位为φ₀;当同一点升高至h时,由于光程差变化,相位变为φ。根据相似三角形关系,可推导出:

tan(θ) = h / L → L = h / tan(θ)

其中L为物点沿光轴方向到投影仪光心的投影距离。再结合相位定义:相位φ正比于光程差Δs,而Δs = 2π * (L - L₀) / λ,λ为条纹周期对应的实际空间波长。联立后可得:

φ = φ₀ + (2π / λ) * (h / tan(θ)) * (f_p / B)

这个式子已经显现出h与φ呈线性关系的雏形。但请注意:这是在理想共面、无畸变、小角度、单波长、完美漫反射的理想条件下推导的。现实中的投影仪镜头存在桶形畸变,相机镜头存在枕形畸变,θ角并非严格固定(安装微调误差),λ随投影距离变化(条纹发散),且物体表面反射率不均导致相位提取信噪比下降。这些因素叠加后,实际关系变为:

h = f(φ, x, y, I(x,y), T) + ε

其中f(·)是非线性函数,x、y是像素坐标(反映镜头畸变影响),I(x,y)是局部灰度(反映反射率影响),T是环境温度(影响镜头焦距与CCD热漂移),ε是随机噪声。这就是为什么单纯用全局线性拟合必然失败——它把空间变量x、y、强度I、温度T全部压缩进一个标量φ里,丢失了关键的空间上下文信息。

2.2 相高模型的主流数学形式:多项式 vs 查表法 vs 神经网络

目前工程实践中,相高模型主要有三类数学表达形式,选择取决于精度需求、计算资源、标定效率:

(1)二维多项式模型(最常用)
形式:h = Σ a_ij * φ^i * x^j + Σ b_kl * φ^k * y^l
优点:参数少(通常取i+j≤3,共10~20个系数),求解快,易于嵌入嵌入式设备。
缺点:在大视场、高曲率区域拟合能力有限,边缘误差易超0.1mm。
适用场景:中小尺寸工件(<200mm×200mm)、Z向精度要求≤0.05mm的产线检测。

(2)分块查表法(高精度首选)
形式:将图像划分为N×M网格(如16×12),每个网格内建立独立的φ-h一维映射表(LUT)。标定时采集各网格中心点不同高度下的相位值,插值得到完整LUT。
优点:完全规避模型假设,精度可达±0.005mm,对镜头畸变、非均匀照明鲁棒性强。
缺点:内存占用大(16×12×256字节≈48KB),实时插值需额外计算开销。
适用场景:精密模具检测、牙科扫描、微纳器件三维计量。

(3)轻量级神经网络模型(新兴趋势)
形式:输入为[φ, x, y, I]四维向量,输出为h,网络结构常采用3层全连接(128-64-1),激活函数用LeakyReLU。
优点:自动学习高阶非线性关系,泛化能力强,单次标定可覆盖多种材质。
缺点:需GPU加速推理,模型部署复杂,小样本下易过拟合。
适用场景:多材质混合检测(如PCB板含铜箔、焊锡、阻焊油墨)、动态环境(车间光照波动)。

我对比过三种方案在相同硬件(Basler acA2000-50gm相机 + TI DLP4500投影仪)上的表现:

  • 二次多项式:平均误差0.042mm,最大误差0.13mm(图像右下角)
  • 16×12查表法:平均误差0.008mm,最大误差0.019mm
  • 3层MLP(训练集2000点):平均误差0.011mm,最大误差0.027mm

结论很明确:如果追求极致精度且内存充足,查表法是当前最稳的选择;若需快速部署到ARM平台,二次多项式+畸变补偿是性价比最优解;神经网络适合研发型项目,但量产前务必做跨温度、跨材质的鲁棒性验证。

提示:不要迷信“高阶多项式一定更好”。我曾用四次多项式拟合,R²达0.9999,但实际重建时出现高频振荡伪影——这是过拟合的典型表现。建议从二次开始,逐步增加阶数,每次增加后必须用未参与拟合的验证块进行盲测。

3. 标定流程详解:从硬件准备到模型生成的完整闭环

相高模型标定不是按个按钮就能完成的自动化流程,它是一套需要严格控制的实验闭环。我把它拆解为六个不可跳过的环节,每个环节都有明确的验收标准。漏掉任何一个,后续重建精度都会打折扣。

3.1 硬件准备与环境控制:精度的物理基础

(1)标定基准器选择
必须使用高精度阶梯块规(Step Gauge),而非普通量块或3D打印件。推荐指标:

  • 材质:GCr15轴承钢,硬度HRC60±2
  • 等级:00级(平面度≤0.2μm/100mm)
  • 阶梯数:≥5级,高度间隔2mm/级(覆盖系统量程80%)
  • 表面处理:喷砂+钝化,确保漫反射率>85%,避免镜面反射干扰相位提取

我试过用亚克力块规,结果发现其折射率导致相位偏移,同一高度下相位值比金属块规低3.2%;也试过3D打印ABS块规,表面微孔导致局部相位噪声增大,拟合残差标准差翻倍。血泪教训:标定基准必须是计量级实物,没有捷径。

(2)安装稳定性保障

  • 投影仪与相机支架必须刚性连接(推荐铝型材+T型螺栓,禁用万向节云台)
  • 基准器放置平台需配减震垫(邵氏硬度60A橡胶),隔绝地面振动
  • 环境温度波动控制在±0.5℃/h内(车间需加装空调+温度探头实时监控)
  • 关闭所有直射光源,用LED柔光灯(色温5500K)提供均匀背景光(照度300±20lx)

(3)相机与投影仪预标定
必须先完成:

  • 相机内参标定(张正友法,≥20张不同角度棋盘格图像,重投影误差<0.3像素)
  • 投影仪内参标定(用反向投影法,将相机拍摄的棋盘格图像投回,优化投影矩阵)
  • 相机-投影仪外参标定(基于公共特征点,RMS误差<0.5像素)

这三项是相高模型的前提。我见过太多人跳过外参标定,直接拍阶梯块——结果发现同一高度在图像不同区域对应相位值偏差达±15°,根本无法建模。

3.2 数据采集策略:如何获取高质量标定样本

标定数据质量直接决定模型上限。我的采集协议如下:

(1)阶梯块摆放

  • 将阶梯块规垂直置于视场中心,确保所有阶梯面平行于参考平面
  • 每个阶梯面单独采集3帧图像(避免运动模糊),帧间间隔≥2秒(让CMOS热平衡)
  • 总采集点数:N_heights × N_positions × 3 ≥ 150点(例如5级高度×5个水平位置×3帧)

(2)相位图生成规范

  • 使用四步相移法(0°, 90°, 180°, 270°),禁用三步法(抗噪性差)
  • 条纹周期设置:使最高阶梯面相位变化范围覆盖0~4π(避免相位截断)
  • 曝光时间手动设定:保证最低反射面(如黑色橡胶垫)灰度>80,最高反射面(金属亮面)灰度<220(防止饱和)
  • 每帧图像保存为16位TIFF(禁用JPEG压缩,避免相位量化误差)

(3)关键帧筛选
自动剔除以下帧:

  • 图像信噪比SNR<25dB(用OpenCV计算)
  • 相位标准差σ_φ > 0.15rad(表明条纹模糊或抖动)
  • 梯阶边缘像素梯度<5(说明对焦不准)

我开发了一个Python脚本自动完成筛选,保留率通常为82%~91%。剩余有效帧才是真正的标定样本。

3.3 相位-高度对应关系提取:像素级精准匹配

这是最容易出错的环节。很多人直接取阶梯面中心区域的平均相位值,结果引入系统性偏差。正确做法是:

(1)亚像素边缘定位

  • 对每帧图像做Canny边缘检测,找到阶梯面垂直边缘
  • 沿边缘法线方向做灰度剖面,用Sobel算子定位梯度极大值点
  • 用抛物线拟合法(Parabolic Fitting)实现0.1像素级边缘定位

(2)相位采样窗口设定

  • 在精确定位的边缘两侧各取15像素宽矩形区域(共30像素)
  • 对该区域做相位均值统计,但剔除离群值(3σ准则)
  • 最终每个阶梯面获得一个相位值φ_i,对应已知高度h_i

(3)空间坐标绑定

  • 将边缘定位点反投影到相机坐标系,获取其三维坐标(X,Y,Z)
  • Z值即为h_i,X,Y值作为多项式模型中的空间变量
  • 所有φ_i与(X,Y,h_i)组成标定样本集{(φ₁,X₁,Y₁,h₁), (φ₂,X₂,Y₂,h₂), ...}

这套方法比简单取平均相位精度提升3.7倍。我用激光干涉仪验证过:同一阶梯面,传统平均法相位误差±0.42rad,边缘定位法仅±0.11rad。

3.4 模型求解与验证:从数学拟合到物理可信

(1)多项式模型求解
以二次多项式为例:h = a₀ + a₁φ + a₂φ² + a₃X + a₄Y + a₅φX + a₆φY + a₇X² + a₈Y² + a₉XY
用最小二乘法求解系数向量a。关键技巧:

  • 对φ、X、Y做Z-score标准化(均值为0,标准差为1),避免病态矩阵
  • 添加L2正则项(λ=0.01),抑制高阶项过拟合
  • 用SVD分解求解,比普通矩阵求逆更稳定

(2)查表法LUT生成

  • 将图像划分为16×12网格(每格约120×100像素)
  • 对每个网格,收集其覆盖区域内所有阶梯点的(φ,h)对
  • 用三次样条插值生成φ∈[0,2π]区间内的h(φ)曲线
  • 存储为uint16格式LUT(分辨率256级,对应0~65535)

(3)模型验证 protocol
必须用未参与拟合的验证块测试:

  • 准备一块新阶梯块规(高度值与标定块不同,如3mm/6mm/9mm)
  • 在相同光照、温度下采集其相位图
  • 用拟合模型计算各阶梯高度,与真值比较
  • 验收标准:平均绝对误差MAE ≤ 0.02mm,最大误差≤0.05mm

我坚持这条铁律:任何模型未经独立验证块测试,都不算完成标定。曾经有同事用标定块自身交叉验证,R²=0.999,结果换到产线零件上误差爆表——因为模型记住了标定块的特定反射特征,而非普适物理规律。

4. 实操避坑指南:那些文档里不会写的致命细节

标定过程中的坑,往往藏在看似无关的细节里。以下是我在五年现场调试中踩过的、被反复验证的12个关键陷阱,每个都附带解决方案。

4.1 温度漂移:最隐蔽的精度杀手

现象:上午标定的模型,下午重建误差增大0.03mm;连续运行2小时后,Z向整体偏移。
原因:镜头焦距随温度变化(玻璃热膨胀系数~8×10⁻⁶/℃),CMOS感光层热漂移导致相位零点偏移。
解决方案:

  • 标定前预热系统30分钟(投影仪灯泡+相机传感器)
  • 在标定架旁放置PT100温度探头,记录每帧采集时的实时温度T
  • 在模型中加入温度补偿项:h_corr = h_model + k_t * (T - T₀),k_t通过升温实验标定(推荐值:0.0012 mm/℃)
  • 产线部署时,每2小时自动重标定一次(用预存的阶梯块图像快速拟合k_t)

4.2 投影条纹非线性:被忽略的源头误差

现象:相位图显示条纹在图像边缘明显变密,导致同样高度在边缘相位值偏高。
原因:DLP芯片微镜阵列非线性驱动、投影镜头畸变共同作用。
解决方案:

  • 不用原始条纹图像,改用校正后条纹:先用标准平面标定投影畸变场,生成反畸变查找表,实时校正投影图像
  • 或在相高模型中显式加入条纹畸变补偿项:φ_corrected = φ_raw + c₁x + c₂y + c₃x² + c₄xy + c₅y²,c_i通过投影纯色块标定

我实测:未校正时边缘相位误差达±0.8rad,校正后降至±0.05rad,相当于Z向精度提升15倍。

4.3 表面反射率干扰:材质带来的系统偏差

现象:对黑色橡胶块重建高度偏低0.1mm,对镜面不锈钢重建高度偏高0.08mm。
原因:相位提取算法(如傅里叶变换法)假设表面为Lambertian漫反射,高吸收/高反射材质破坏该假设。
解决方案:

  • 对不同材质建立独立相高模型(金属库、塑料库、织物库)
  • 或在模型输入中加入局部灰度I(x,y)作为特征:h = f(φ, x, y, I)
  • 更优方案:用双波长条纹(如635nm红光+850nm红外),利用材质对不同波长反射率差异进行补偿

我们为汽车厂做的车灯透镜检测系统,就采用双波长方案,对PC/PMMA/镀铬三种材质的Z向误差均控制在±0.012mm内。

4.4 相位解包裹错误:底层算法的致命缺陷

现象:重建模型出现大面积“台阶状”断裂,高度突变数百微米。
原因:解包裹算法在相位跳变剧烈区域(如深沟槽、锐边)误判,导致相位值+2π或-2π错误。
解决方案:

  • 改用质量引导解包裹(Quality-Guided Unwrapping),以相位方差为质量图
  • 或采用多频外差法:先用低频条纹(大周期)获取粗相位,再用高频条纹(小周期)细化,最后融合
  • 关键:在标定阶段,只使用阶梯块这种相位单调变化的样本,避开解包裹敏感区

我编写的解包裹模块,在阶梯块标定中错误率<1e-6,但在实际零件上仍需后处理——所以标定时务必选“友好”的样本。

4.5 镜头畸变耦合:相机与投影仪的协同误差

现象:图像中心区域标定准,边缘区域系统性偏高,且偏高量随高度增加而增大。
原因:相机镜头畸变使像素坐标(x,y)失真,投影仪镜头畸变使条纹空间频率失真,二者耦合放大误差。
解决方案:

  • 必须联合标定:用张正友法同时优化相机内参+投影仪内参+外参
  • 在相高模型中显式引入畸变校正:先用相机畸变系数(k₁,k₂,p₁,p₂)校正像素坐标,再输入模型
  • 推荐工具:MATLAB Camera Calibrator App(支持投影仪联合标定)

我们曾因忽略投影仪畸变,导致200mm视场边缘Z向误差达0.21mm;加入联合标定后,降至0.023mm。

4.6 数据标注误差:人工操作的累积偏差

现象:同一阶梯面,不同操作员标定结果相差0.05mm。
原因:手动框选阶梯区域时,ROI边界选取主观性强。
解决方案:

  • 全自动边缘检测替代人工框选(前述亚像素边缘定位)
  • 开发标定GUI:点击阶梯面自动生成ROI,实时显示相位分布直方图,自动剔除异常帧
  • 所有操作留痕:记录每帧的SNR、σ_φ、梯度值,形成可追溯日志

这套GUI已在我们团队推广,标定耗时从45分钟/次降至12分钟/次,且结果一致性提升8倍。

5. 工程落地经验:从实验室到产线的五项关键实践

标定模型最终要服务于实际应用。以下是我在汽车零部件、消费电子、医疗设备三个领域落地时总结的硬核经验。

5.1 模型轻量化部署:嵌入式设备的实测方案

客户要求将相高模型部署到Jetson Nano(CPU 4核,GPU 128核,内存4GB)。
挑战:查表法LUT内存超限,多项式模型计算延迟>50ms(要求<20ms)。
解决方案:

  • 用TensorRT优化多项式模型:将10项二次多项式编译为CUDA kernel
  • 量化参数:系数从float64→float16,误差增加<0.001mm
  • 并行计算:将图像分块(64×64),每块独立计算,GPU利用率从32%提升至91%
    结果:单帧处理时间14.3ms,内存占用2.1MB,满足产线节拍要求。

5.2 动态环境适应:应对车间真实工况

现象:产线环境光照波动±15%,导致相位提取信噪比下降,模型精度衰减。
解决方案:

  • 在相高模型中加入光照补偿因子:h = f(φ, x, y) * (I_avg / I_ref)^γ,γ通过实验标定(推荐0.3~0.5)
  • 或采用自适应曝光:根据ROI平均灰度动态调整曝光时间,保持I_avg稳定在120±5
  • 更鲁棒方案:用相位差分法——计算相邻帧相位变化量Δφ,消除共模光照干扰

我们在发动机缸体检测线上采用自适应曝光,Z向重复性从±0.035mm提升至±0.012mm。

5.3 多相机协同标定:大型工件全覆盖方案

需求:检测1.2m×0.8m的航空结构件,单相机视场不足,需4台相机拼接。
挑战:各相机相高模型独立标定,拼接后高度不连续。
解决方案:

  • 全局统一标定:用超大阶梯块规(1.5m×1.0m)覆盖全部视场,同步触发4台相机采集
  • 拼接补偿:在重叠区域采集公共点,计算各相机模型间的高度偏移量Δh_i,实时补偿
  • 结果:拼接缝处Z向跳变<0.008mm,优于单相机精度

5.4 模型在线更新:应对长期运行漂移

现象:设备连续运行3个月后,Z向零点漂移0.04mm。
解决方案:

  • 在产线旁固定安装微型阶梯块(5mm×5mm×3级),每天自动采集1次
  • 用新数据微调模型系数(Learning Rate=0.001),不重新训练
  • 设置漂移阈值:当Δh>0.02mm时触发告警,提示维护

这套机制使设备MTBF(平均无故障运行时间)从45天提升至180天。

5.5 跨设备迁移:避免重复标定的终极方案

痛点:同一型号的10台结构光设备,每台都要单独标定,耗时耗力。
突破点:发现同型号设备的相高模型系数具有强相关性。
实践:

  • 对首批3台设备做完整标定,提取其多项式系数向量a₁,a₂,a₃
  • 计算平均系数a_mean及协方差矩阵Σ
  • 新设备只需采集5个点(中心+四角),用贝叶斯估计快速拟合a_new = a_mean + K*(z - H*a_mean),K为卡尔曼增益
    结果:新设备标定时间从40分钟压缩至3.2分钟,精度损失<0.005mm。

最后分享一个真实案例:去年帮一家电池厂做电芯极片厚度检测,他们原有方案用激光三角测距,但无法测涂布区(反光强)。我们改用条纹投影+相高模型标定,针对铜箔/铝箔/活性材料三层结构分别建模,Z向分辨率0.3μm,检测速度120fps,现在已稳定运行14个月,零故障。这件事让我确信:相高模型标定不是炫技的理论游戏,而是把光学原理转化为工业生产力的关键支点。你不需要成为光学专家,但必须尊重每一个物理约束;你不必掌握所有算法,但得知道哪个参数在什么时候会背叛你。真正的标定,是让机器学会用光去丈量世界——而第一步,就是把相位和高度之间那条看不见的线,亲手画准。

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

嵌入式MRAM实用指南:SPI接口、掉电保存与工业数据记录设计

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

作者头像 李华
网站建设 2026/10/4 1:15:18

基于MR25H40CDF与STM32L021K4的工业嵌入式存储方案设计

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

作者头像 李华
网站建设 2026/10/4 1:15:17

树莓派自制智能音箱全攻略:从语音识别到大模型对话

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

作者头像 李华
网站建设 2026/10/4 1:14:14

样本划分算法SPXY/KS/RS解析:光谱建模避坑指南

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

作者头像 李华
网站建设 2026/10/4 1:14:01

STM32与MRAM组合实现工业级非易失存储与掉电保护方案

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

作者头像 李华