news 2026/10/8 19:08:46

开源扫地机器人全栈拆解:从传感器融合到SLAM与路径规划

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源扫地机器人全栈拆解:从传感器融合到SLAM与路径规划

扫地机器人这东西,大多数人的认知停留在“买一台、手机连上、它自己转悠”的层面。但如果你真把一个开源扫地机器人项目拆开看,会发现这几乎是市面上绝无仅有的全栈工程教材——从钣金结构到电机驱动,从惯性测量单元到里程计融合,从路径规划到嵌入式 Linux,从手机 App 到云端地图存储,一路打通,所有知识全部落在一台能跑、能扫、能自己回家的机器上。

所以当你看到“开源扫地机器人全栈拆解”这个标题时,要知道它不是简单的 DIY 玩具项目,而是用一台机器把机器人工程、嵌入式开发、算法设计、前后端通信全部串起来的一套完整课程。这篇博文,我就以我实际折腾过的开源扫地机器人项目为底,把整台机器的技术框架掰开揉碎,按“硬件分工—底层软件—算法大脑—通信链路—复刻实操”这条线来讲清楚,顺便分享那些代码注释里永远不会写的坑。

1. 一台扫地机器人里究竟藏了几个技术栈

先别急着看代码,先搞清楚一个开源扫地机器人项目摆在面前时,你手里到底拿着一堆什么。我的结论是:它至少横跨四个完全不同的技术领域,任何一个单拎出来都可以养活一条职业线。

第一个是嵌入式硬件层。整台机器的主控通常是一颗 MCU,常见的是 STM32F4 系列或者 ESP32,承担电机控制、传感器采集、IO 逻辑、低层通信这些实时性要求比较高的任务。在这一层你要处理 PWM 调速、编码器计数、ADC 采样、I2C 读取激光雷达或 IMU 数据,还要设计电源管理,让电池电压、充电检测、电机堵转保护都能可靠工作。

第二个是算法层。扫地机器人区别于遥控小车的核心在于自主性。它要回答三个问题:我在哪?我去哪?怎么去?对应着里程计与 IMU 数据融合、栅格地图构建与 SLAM、覆盖路径规划与回充路径搜索。这一层的知识密度最高,也最容易把人劝退,因为它需要线性代数、概率论、数值优化三样基本功。

第三个是应用与通信层。现代扫地机器人几乎都有手机 App,你要做网络配网、MQTT 或自定义 TCP 协议、状态上报、地图可视化、远程指令下发。这里面涉及前后端开发、协议设计、数据序列化(protobuf、JSON、msgpack),踩过坑的人都知道,设备端和服务端各有一套处理边界。

第四个是结构与机电一体化层。别看它小,轮子怎么布局、吸尘风道怎么设计、边刷离地高度怎么调、传感器装在什么位置避障效果最好,这些都是工程问题。开源项目通常把你需要的三维模型文件(STEP/STL)、PCB 工程、BOM 表全开放出来,这一层玩明白,基本就具备了从“只看代码”到“能造实物”的跨越能力。

拿具体项目来对照会更直观。以我参考过的几款典型开源方案为例,它们的硬件选型和架构思路大体如下表:

部件模块常见开源方案选择核心职责
主控 MCUSTM32F407 / ESP32-S3电机控制、传感器采集、运动执行
协处理器/核心板Raspberry Pi / Jetson Nano跑 SLAM、路径规划、ROS 节点
导航传感器RPLIDAR A1/A2、单线激光雷达环境测距、提供 2D 点云
里程计传感器霍尔编码器(AB 相)轮速测量、里程累计
姿态传感器MPU6050 / ICM20948惯性测量、偏航角估计
电机驱动DRV8825 / TB6612 / BTN7971直流有刷或无刷电机驱动
定位与地图Cartographer / Gmapping实时 SLAM
通信链路Wi-Fi 模块 + MQTT / WebSocketApp 远程连接

这张表不是随手列的。单片机和树莓派的分工逻辑,几乎决定了整个项目的代码组织方式:底层实时任务归单片机,深度学习或重计算任务归上位机,上下位机之间通过 UART 或 USB 通信。理解了这个“分工”,你就抓住了整个项目的骨架。

2. 传感器与驱动器的分工:一台机器如何感知自己所在的环境

说到传感器,很多初学者有个误区,以为传感器越多越好。我一开始也是这个思路,给机器装了一大堆超声波、红外、激光、碰撞开关,结果代码里做数据融合的时候自己先乱掉了。真实项目里,开源扫地机器人的传感器设计讲究的是“各司其职、冗余兜底”,而不是堆料。

2.1 感知的三个层次:定位、防撞、沿边

打开一个典型的开源扫地机器人原理图,你会发现传感器可以分成三组。

第一组是导航用的测距传感器,核心通常是单线激光雷达,安装在机器顶部,以 360 度旋转扫描周围环境,输出的是 2D 点云数据。这类雷达的原理其实不复杂:内部有一个高速旋转的测距模块,常见方案是三角测距法或 TOF(飞行时间法)。RPLIDAR A1 用的是三角测距,成本低、精度在厘米级,家用扫地机上完全够。对这部分数据做处理后,机器就能得到一个“我周围 6 米内哪里有墙、哪里有障碍物”的环境快照。

第二组是防碰撞和悬空传感器。因为激光雷达的探测范围通常有盲区,特别是低矮障碍物很难直接看到,所以项目会在机器前侧加碰撞开关(机械微动开关)或者红外接近传感器。底部则会装 3-4 个红外悬崖传感器,用来检测台阶和楼梯边缘,防止机器从高处掉下去。原理很简单:红外发射管发射信号,如果地面反光正常,接收管能收到反射;如果识别到悬空,反射信号突变,机器就立刻停止前进并后退。

第三组是里程计传感器。每一个驱动轮都装有霍尔编码器,通过检测磁场变化输出 A/B 两路相位差 90° 的方波信号,MCU 通过对两路信号进行正交解码,既能算出轮子转了多少圈,还能判断出转动的方向。这个数据结合轮径和轮距,就能推算出机器走了多远、转了多少度,这就是所谓的“航迹推算”。

这三组感知有一个现实问题:单一传感器都有弱点。激光雷达看不到低矮物体,里程计在轮子打滑时会产生累计误差,陀螺仪有温漂和零偏。所以真实项目里一定存在“传感器融合”这一步,下面细讲。

2.2 数据融合:从“各自报数”到“统一坐标”

很多人第一次看到卡尔曼滤波或者粒子滤波会头大,我可以给个简单类比:这就好比屋子里有三个人分别告诉你“你从门口走了几步”“你往左还是右偏了”“你前方有没有墙”,你不可能谁的话都完全相信,要根据每个人经验的可靠程度来加权估计自己的位置。卡尔曼滤波在做的事,本质就是动态地对每个观测来源的“置信度”进行加权更新。

在扫地机器人项目里,常见的融合方案有两类:

  • EKF(扩展卡尔曼滤波):适合处理非线性系统,把 IMU 的角速度积分结果和轮式里程计的位置增量组合起来,输出一个相对平滑、短期精度较高的位姿估计。它的输出会作为 SLAM 前端里程计的先验信息。
  • 粒子滤波:在重定位场景更常用。比如机器被搬动、被抬起然后放下,轮式里程计失效了,粒子滤波可以通过激光匹配在已知地图中找到机器当前最可能的位置,帮助机器重新“找自己”。

选择哪种融合方式,取决于你的算力平台和精度要求。树莓派上跑 Cartographer 时,通常只用里程计数据和激光雷达点云做扫描匹配,IMU 数据作为辅助;而 MCU 级别的小型自研方案,往往会用轻量级 EKF 库在单片机上实时运行,效果已经足够。

实操层面我建议你从“打印各传感器原始数据”开始排查。把编码器脉冲数、MPU6050 解算出的偏航角、激光雷达的最近扫描距离全部格式化输出到串口,然后手动推一下机器,观察数据变化是否符合物理直觉。这一步花不了两小时,但可以帮你节省后面 80% 的定位调试时间。很多新手上来就配 SLAM,结果地图建得歪歪扭扭,查了半天才知道是编码器接线时 A/B 相搞反了——这种问题只靠算法调参是永远调不出来的。

3. 软件架构的骨架:从底层驱动到应用节点的分层设计

一台扫地机器人运行起来的核心是软件代码的有序分工。我见过的开源项目在这一点上高度一致:主控 MCU 上是一个裸机或 FreeRTOS 实时系统,负责一切“必须立刻响应”的任务;而上位机是一套 Linux 环境,负责一切“需要大算力和复杂逻辑”的任务。两层之间通过串口或 USB 以固定协议通信。

3.1 底层 MCU:实时性优先的驱动层

底层代码中最重要的是电机闭环控制。扫地机器人的速度控制不能简单“给 PWM 就行”,因为电池电压会变化、地面摩擦会变化、爬坡时负载会突变。常见做法是 PID 速度闭环:编码器测量实际轮速,MCU 按设定速度与实际速度的误差,实时调整 PWM 占空比。

拿比例-积分-微分三项参数来说,调参口诀可以记成“P 管快慢、I 管稳定、D 管刹车”:

  • P 系数太小,轮子加速慢,启动迟钝;P 系数太大,轮子会震荡,发出嗡嗡声。
  • I 系数能消除静态误差,比如上坡时 P 项推不动,I 项会逐渐积累力量把轮速拉回目标值。
  • D 系数提供阻尼,抑制超调,但过大容易引入噪声,因为微分对编码器抖动非常敏感。

一个实用调参法:先只调 P,逐渐增大直到轮速出现轻微震荡;再加大 I,让实际轮速和设定值之间没有稳定偏差;最后加一点 D 来压制超调。记录三组参数对应波形图,就能建立手感。底层代码还包括传感器驱动,比如激光雷达通过串口以特定波特率输出测距数据帧,需要解析帧头、帧尾、校验位,稍有不慎数据就错位;MPU6050 通过 I2C 读取原始加速度和角速度,再经过滤波换算角度。

3.2 上层 Linux:算法和应用的家

树莓派或 Jetson 上跑的系统,一般是 Ubuntu + ROS(或 ROS 2),核心是几个功能节点:

  • 雷达驱动节点:发布激光扫描话题。
  • 里程计节点:接收底层 MCU 传来的编码器数据,转化为里程计消息。
  • SLAM 节点:订阅激光和里程计数据,实时输出机器人在栅格地图中的位姿,同时构建地图。
  • 导航节点:接收目标点,执行全局路径规划和局部避障。
  • 状态机节点:负责扫地逻辑的决策,比如“从基站出发—沿边清扫—弓字形覆盖—检测低电量—回充”。

这套架构的精髓在于模块的“线程模型”。 SLAM 线程持续运算,如果 CPU 被抢占太多,就会出现地图卡顿和位置漂移;导航线程实时响应,占据局部规划优先级,一旦前方突然出现人脚或宠物,要能在几百毫秒内改变速度方向。很多开源项目的坑就出在“单线程把所有事都干了”——机器在地图构建正常时看起来没问题,一进入动态环境就直接撞墙。我强烈建议你用ros2 topic hz这类命令去实测各话题的发布频率,雷达扫描通常 10Hz 左右,里程计 20-30Hz,如果某个话题掉到了 1Hz 以下,那一定是资源瓶颈,需要优化而不是继续叠加功能模块。

4. 算法的核心现场:SLAM 与路径规划到底在算什么

这部分是绝大多数人觉得“深不可测”的地方,但实际拆开看,思路非常清晰。扫地机器人的算法层其实就三件事:建图、定位、路径规划。

4.1 建图与定位:一边画地图一边找自己

扫地机器人开始工作时,它对家居环境一无所知。它要拿着 2D 激光雷达的数据,一边移动一边构建一张“栅格地图”——你可以把这张地图想象成一张黑白网格纸,每个格子要么是空白,要么是障碍物(墙壁、家具),要么是未知区域。

构建这张地图的同时,机器人还要实时回答“我在这张图上的哪个位置”。这听起来像先有鸡还是先有蛋:要知道位置就得有地图,要知道地图就得知道位置。SLAM 要解决的正是这个互相依赖的问题。

Google 的 Cartographer 是目前开源扫地机器人项目中最常用的 SLAM 方案,它的核心思路是“扫描匹配 + 闭环检测”:

  • 局部地,每收到一帧新激光扫描,就尝试将它放到上一个已知位置的附近,计算一个最优变换,让当前扫描与已有的子图最吻合。这一步叫做扫描匹配,计算量很大,Cartographer 用的是栅格化像素匹配加分支限界搜索的技巧来加速。
  • 全局地,当机器人再次回到曾经到过的区域时,系统要识别出“这里我来过”,然后对累积的位置漂移做一次全局修正,这就是回环检测。回环正确闭合后,地图会突然变得整齐,漂移被大幅拉回。

我这里有个强烈建议:初学者想理解 Cartographer,不要单看公式和博客,先下载官方开源包,在离线存储的传感器数据包上跑一遍 lidar_slam 配置文件,然后反复调整tracking_frame、map_frame、odom_frame这些坐标系的定义,你会发现 90% 的地图畸变问题都出在坐标系定义不对或 TF 树断链上。这比背十篇论文都管用。

4.2 覆盖路径规划:扫地不是乱跑,是“弓字形”

扫地机器人的路径规划和普通移动机器人的“点到点导航”有一个显著区别:它要的是覆盖整个区域,而不是找到一条最短路径。家用覆盖策略几乎统一采用“弓字形”回退清扫——直线沿一个方向覆盖,到边界后旋转 180°,偏置一个机身宽度,再反方向覆盖。这个策略实现简单、覆盖率高,而且视觉上看起来很聪明。

具体实现时会先对地图做区域切分:把一个完整的大房间,根据障碍物的凸包轮廓切分成若干个子区域,比如客厅、通道、卧室。对每个子区域分别执行弓字形覆盖,区域之间通过“途经点”衔接。这样做的原因是:如果对整个大区域直接作弓字形,机器容易被复杂障碍物的凹形边界困住,反复绕圈却漏扫很多角落。

避障局部规划器则负责躲开突然出现的障碍物。常用动态窗口法:在每个控制周期内,枚举一组可行速度(线速度 + 角速度),用运动学模型预测以这些速度行驶一小段时间后机器会到哪儿,再对每个候选轨迹打分,分数考虑“离目标近不近”“离障碍物远不远”“能耗高不高”,最后选择得分最高的轨迹。听起来复杂,但实际上就是数学上的“多目标最优”问题,在一个周期内用有限候选集做穷举近似。

4.3 回充与断点续航:看着不起眼,其实最容易崩

扫地机器人的回充功能是很影响实际体验的。低电量时机器要能从清扫位置自动回到充电座,这涉及两套方案叠加:

  1. 先导航回大体位置:利用 SLAM 地图中标记的基站坐标做全局路径规划,把机器人导航到基站附近 1 米范围内。这要求建图时基站必须可见。
  2. 再红外对接:基站上装有红外发射器,扫地机侧装有红外接收传感器阵列。机器人慢速前进,通过接收信号强度差异微调角度,最终实现精准插入充电极片。电极片要设计成倒角结构,让物理插入过程有容错。

我在折腾回充时踩过最深的坑是:地图里基站位置没更新,机器人回到旧位置,结果基站已经被人挪了 20 厘米,机器疯狂转圈,就是找不到。后来在代码里加了“回充失败则触发重定位”的逻辑,回充成功率才真正稳定下来。这类“看着不起眼边缘功能”其实非常考验工程整合能力,很多开源项目在这一点上做得并不好,所以我专门把它单列出来提醒。

5. 让机器“对话”起来:App、云端与远程控制的链路

一台扫地机器人如果没有 App,它依旧能扫地,但你就无法远程启动、查看地图、设定禁区。这东西属于典型的“全栈开发”场景:设备端、通信协议、服务端、前端,一条链路。

5.1 配网与通信协议

家用 Wi-Fi 扫地机器人的典型配网流程是:手机先连接机器人自己开启的 AP 热点,把家庭 Wi-Fi 的 SSID 和密码发给机器人,机器人断开 AP、连接家庭 Wi-Fi,再跟服务器建立长连接。开源项目里 MQTT 是主流选择,因为协议轻量、消息支持 QoS、生态成熟。

协议字段设计上,我建议一开始就直接采用 protobuf 或 flatbuffers,不要用纯 JSON 做命令帧。原因很实际:设备端 MCU 内存小,JSON 解析开销大;功能多了以后,字段增减容易出兼容性问题。protobuf 的二进制编码和向后兼容机制更抗折腾。实际调试中,抓包工具选 MQTT 面板或 Wireshark 解析 MQTT 包都很方便,先把 QoS 设为 0 和 1 分别验证一下,再根据是否有必要开启 QoS 2 级来做决定。

5.2 状态上报与地图可视化

扫地机上云后,几个关键状态量需要实时或者定时上报:电池百分比、当前任务状态(清扫中/回充中/暂停)、清扫面积、当前地图、历史轨迹。地图可视化是最让人头疼的一个环节,因为机器人端构建的是栅格地图,要在浏览器里渲染出来,通常把栅格地图转成图片(PNG),叠加坐标系转换,再用 Canvas 或者 WebGL 画出来,同时要高亮显示清扫轨迹。

这里的坑在于:地图 PNG 和轨迹坐标必须对齐到同一个世界坐标系。我见过太多项目,地图显示正常、轨迹也正常,但图层一叠加,轨迹和地图发生了旋转偏移,原因往往是坐标系 Y 轴方向不一致(图像坐标和笛卡尔坐标的 Y 轴是反的)。这个细节写在文档里的极少,我强烈建议你在前端坐标转换层统一做一次矩阵变换,而不是每个页面各转各的,否则后面每加一个功能都要调半天。

5.3 本地化 vs. 云端的边界

并不是所有的智能都要上云。边扫边规划这种低延迟决策一定在设备端完成,否则网络延迟 300ms,机器早就撞上去了。云端更多承担的状态同步、历史记录、数据统计、远程参数下发。搞清楚这条边界,你的系统设计才不会乱。

有些进阶项目会加入“虚拟墙”功能,也就是在地图上画一条线或者一个框,算法端把它当作障碍物处理。这个功能实现不难,本质是在栅格地图上把用户框选的区域标记为不可通行。要注意的是,地图坐标和用户框选区域坐标必须按同一分辨率换算,我看到的实现 Bug 大多出在这个换算比例上。

6. 从零复刻一台开源扫地机器人的行动路线

前面讲的一堆东西,如果不落到物上,始终是纸面知识。下面我给你一条我实测过、走通过的复刻路线,并标注每一步的耗时和难点,你可以直接照着排计划。

6.1 选型阶段:别一上来就买全套

复仇一个常见的错误是先把 BOM 表的物料全部买齐,结果光是调试焊接就花了一个月。我建议分期投入:

  • 第一期:只买 MCU 开发板、两个直流电机+编码器、电机驱动小板、电池、一个简易底盘。目标是把机器人从“原地想”变成“能根据指令直走转圈”,实现最核心的电机闭环。这一期一周内可以完成。
  • 第二期:加装激光雷达和 IMU,跑通数据采集和可视化。此时机器还不具备自主能力,但你能在 PC 上看到雷达扫描出来的环境轮廓,这个成就感很强。这一期大约两周。
  • 第三期:接入 SLAM 算法,让机器在遥控下边推边建图。然后实现导航,给一个目标点,机器自己能规划路径过去。
  • 第四期:加上扫地结构(风机、尘盒、边刷),开发 App 和云端对接。此时整台机器才真正达到“可以日常用一用”的状态。

6.2 调试顺序:先拆解再整机

整机调试是最容易心态崩的环节,因为你不知道问题是出在电机上、雷达上还是算法参数上。聪明的做法是每个模块单独验证:

  1. 电机:用串口设置 50% 占空比,看轮子是否转动、编码器脉冲是否正常。
  2. 雷达:启动雷达驱动节点,用可视化工具查看 360 度点云,用手在雷达旁晃动,确认测距实时变化。
  3. IMU:静止时观察角度值是否稳定,旋转机器看数据变化方向是否正确。
  4. 里程计:手动推直线 1 米,对比推算距离和真实距离的误差,标定轮径参数。
  5. SLAM:手持机器在房间内缓慢走动,观察地图构建是否平滑、回环能否闭环。

每完成一层验证,再开始下一层。这样做的好处是问题边界始终清晰,永远不会出现“改一行代码不知道是谁的锅”的情况。

6.3 调试中最容易踩的五个坑(实测总结)

我在完成这个项目的过程中,把踩过的坑按“排查难度”排了个序,这里直接列出来供参考:

坑现象根因解决办法
轮子莫名其妙反转设定前进实际后退电机线正负极接反对调电机接线,或者在代码里把方向和编码器方向统一
地图建出来是歪的直线墙变成弧线里程计轮径标定不准做直线推车测试,用实测距离反推轮径系数
地图经常穿墙明明前方是墙还往前冲激光雷达安装位置太低/遮罩反光用漫反射材质遮挡,或用算法过滤近距离噪声点
回充找不到基站到了基站附近到处转圈基站位置在地图中未锁定在状态机里固定基站在地图的 TF 坐标,每次导航前读取
App 地图显示空白接口返回数据正常前端坐标系与后端地图坐标系不统一统一转换矩阵,用实测数据校准

这些坑看起来都是“小问题”,但我不得不说,它们才是整个项目真正消耗时间的地方。书上和论文里不会教你怎么查一个 Y 轴反转,但它们恰恰就是工程经验的全部意义。

7. 怎么把这台机器变成长在自己身上的技能

最后聊一个很实际的问题:项目做完了,怎么不白做?我个人的体会是,开源扫地机器人的价值并不是终点,而是下一段学习的起点。你在完成它之后,随身携带的不仅仅是“我有个会扫地的机器人”这个作品,还有一套可以迁移到任何其他机器人项目上的思维方式。

比如,你做完了扫地机器人,再去看一个开源机械臂项目,会发现电机闭环、正逆运动学、轨迹规划、上位机通信这些概念,几乎全部能平移过去。你去做无人小车,SLAM 与路径规划同样复用。甚至你去做一个工业 AGV 项目,核心的传感器融合、导航决策、云端调度链路,在逻辑上也是同构的。换句话说,扫地机器人只是形态上“最生活化”的一个载体,背后通用的正是机器人工程的核心方法论。

而那些踩过的坑、调过的参数、修过的transform链条,会在若干年后的某个项目里突然跳出来帮你避开一个同样的坑。这大概就是开源项目作为教材最值钱的地方:它让你用最低的门槛,亲手撞一遍所有非碰不可的墙,然后带着伤疤变成老手。

如果你打算开始,不要犹豫,先入手一个带编码器的底盘和一块 STM32 开发板,把“电机转起来”这件小事做成。一门精彩的机器人工程课程,正以一台会扫地的机器为封面,等你翻开它。

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

Java开源一物一码溯源防伪系统实战指南

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

作者头像 李华
网站建设 2026/10/8 19:07:27

工业级电源路径保护:TPS259483AYWPR与R7FA4L1BD4CFP协同设计

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

作者头像 李华
网站建设 2026/10/8 19:06:48

Java火车票系统实战:Access MDB+Swing实现余票扣减与退票回滚

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

作者头像 李华
网站建设 2026/10/8 19:05:55

从开发到上架:Eros 双端打包、签名与发布全流程指南

从开发到上架:Eros 双端打包、签名与发布全流程指南 【免费下载链接】eros 📱 一套 Vue 代码,两端原生应用 ,或许可以叫我 weex-native。 项目地址: https://gitcode.com/gh_mirrors/er/eros Eros 是一套「一份 Vue 代码&am…

作者头像 李华
网站建设 2026/10/8 19:05:55

二维Morlet小波图像去噪:时频局部化降噪原理与工程实现

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

作者头像 李华