Scan Context:点云描述子如何解决激光SLAM回环检测难题

发布时间:2026/10/20 10:09:06
Scan Context:点云描述子如何解决激光SLAM回环检测难题 1. 为什么一个点云描述子值得专门写一篇学习笔记1.1 回环检测在SLAM中的位置做机器人、自动驾驶或者三维视觉相关工作的人对SLAM一定不陌生。定位与建图这件事往简单了说就是让机器在未知环境中一边走一边画地图同时搞清楚自己在地图里的位置。这里面有一个绕不开的问题机器在运动中会不断累积误差走着走着位置就偏了地图也跟着扭曲。回环检测就是用来纠正这个问题的关键模块——当机器重新回到曾经到过的地方时它能认出来“我来过这里”然后把当前的局部地图和之前的轨迹做一个全局对齐一次性把累积漂移拉回来。如果把SLAM系统比作一个人闭着眼睛走迷宫回环检测就是那个“睁眼认路”的瞬间。没有回环检测的SLAM系统长时间运行后误差会越来越大地图完全没法看。有回环检测的系统即使中途漂移再厉害只要某个时刻认出了来过的地方整体状态就能被“吸”回正确的位置附近。那回环检测最朴素的做法是什么呢就是把当前看到的环境和之前所有时刻看到的环境逐一比对看看有没有相似的。麻烦在于两点一是环境是有视角的同一个地方从不同方向看差别可能很大二是计算量问题实时场景下不可能把每一帧都拿来全量比对。为了做到“快速地识别来过的地方”研究者把目光投向了“全局描述子”也就是为每一帧点云提取一个紧凑的、对整个场景有概括能力的特征表示。Scan Context正是这一类工作中极具代表性的一个方案。1.2 Scan Context到底解决了什么问题在Scan Context被提出之前业界已经有了不少回环检测思路。比如基于视觉词袋的方法把图像特征聚成词典再用向量比较相似度在视觉SLAM里用得很广。但在纯LiDAR场景里点云数据没有颜色、没有纹理只有几何结构视觉那套办法不太好直接搬过来。还有一类方法是做局部特征提取和匹配比如提取关键点并计算描述子再通过几何一致性验证回环这类方法精度高但速度慢而且对点云的密度和噪声比较敏感。Scan Context的想法很直接把一帧3D点云的“空间轮廓”压缩成一张2D矩阵这个矩阵能够反映这个地点在空间结构上的独特性。也就是说它不依赖任何人工设计的局部特征也没有复杂的几何匹配流程而是从“整个场景长什么样”这个宏观视角出发直接生成一个全局签名。有了这个签名之后回环检测就变成了签名之间的查重问题快而且稳。这篇论文里提出的方案有几个让人印象深刻的特点。第一它对LiDAR点云非常友好不需要额外的传感器数据也不需要做语义分割之类的预处理。第二它天然支持旋转不变性同一位置换个朝向扫描描述子之间仍然能匹配上同时还能顺带估计出偏航角的偏移量。第三检索过程做了分层设计先用粗粒度编码快速过滤候选帧再精确计算相似度整个架构放在嵌入式平台上也能跑得动。我在实际项目中复现过这个方案并且把它接进了一个完整的激光SLAM系统里。整个学习过程让我觉得Scan Context是一个值得反复阅读的经典工作它的工程价值和设计思想都远比表面上的几页公式要丰富得多。1.3 读这篇论文前需要哪些前置知识如果你是第一次接触这个方向直接去看原文可能会被一些概念卡住。建议动手前先把这几块基础补一补。首先是3D点云的基本表示方式。LiDAR每帧返回的数据是由很多个点组成的点集每个点通常包含三维坐标有的还包含反射强度。一帧64线激光雷达在市区环境下可能产生十几万个点数据量不小但直接拿这些原始点来做匹配既不高效也不稳健。其次是旋转不变性的概念。我们可以想象一下一个场景里有一栋楼和一个花坛如果机器人从南向北看楼的影像出现在描述子的左侧如果从北向南看楼的影像出现在描述子的右侧。两次扫描描述的内容一样但排列顺序会发生循环位移。一个好的回环检测方法必须能处理这种位移否则明明在同一个地方也会被判成不相似。再有就是相似度度量。拿到了两个描述子之后怎么算它们“像不像”这是需要定义距离函数的问题。Scan Context的设计里距离函数的每个细节都有讲究不是随便拿个Frobenius范数就能糊弄过去的。我个人觉得读这篇论文最好的方式是带着“如果我来设计会怎么做”的思考去读。看到它把点云按方位角和距离划分成网格时你可以停下来想想为什么是这种划分而不是体素化看到它存的是每个格子里的最大高度时你再想想为什么存极值而不是均值这些思考过程比单纯刷一遍公式有价值得多。2. 核心思想逐层拆解从点云到描述子矩阵2.1 环与扇区怎么把一个无序点云变成有结构的信息Scan Context描述子的构建过程一句话概括就是“把点云投影成鸟瞰图然后按极坐标切格子”。但这句话听起来容易做起来有不少细节。首先把点云中的每个点从三维坐标转换成极坐标视角下的表示。具体来说以传感器所在位置为中心计算每个点的水平距离也就是到z轴的距离和方位角。水平距离用ρ表示方位角用θ表示。然后依据ρ大小把空间划分为若干个同心圆环依据θ大小把圆周划分为若干个扇区。这样一来每一个点就落到了一个由“第几环”和“第几扇区”共同确定的网格里。典型的参数配置是20个环、60个扇区也就是把整个水平空间切成了20乘以60等于1200个网格。每个网格覆盖的角度是360度除以60等于6度覆盖的径向范围取决于最大扫描距离和环数的分配方式。在论文的默认配置里环的宽度采用了非均匀设计内圈更密、外圈更疏。为什么这样设计因为靠近传感器的点云通常更密集、细节更多而远处点稀疏过密的分割只会引入噪声。网格划分完成之后每个网格里可能有点也可能没有点可能有一个点也可能有几百个点。Scan Context记录的是每个网格中所有点的最高z值作为这个网格的代表值最终得到一个20行60列的矩阵矩阵的每个元素就是对应位置的最大高度。这种做法的好处是直接把三维问题压缩成了二维而且保留了最能区分场景的结构信息。在城市场景中建筑物、树木、路灯这些物体的顶部轮廓往往非常稳定不像地面点那样到处都是也不像车辆点那样移动频繁。用最高点来代表一个区域相当于只关注场景的“天际线”这个思路和人类认路时记住标志性建筑的逻辑是相通的。这里需要说明的是实际的点云第一帧往往包含地面点在构建描述子之前是否滤除地面论文里没有做强制要求。实际操作时很多复现版本会先做一个高度裁剪比如只保留z轴方向-0.5米到3米范围内的点这样既保留了道路边缘和建筑物的主要结构又能有效去除悬空物体和噪声点。我个人复现时在这个环节做过对比实验保留地面点会让描述子在空旷区域出现大量低区分度的行而去除地面后整体检索精度有可感知的提升。2.2 为什么存最大高度而不是平均高度这是一个值得反复琢磨的设计决策。如果只是描述“这个格子里有什么”存平均高度似乎更合理——它更能反映一个区域的整体起伏。但Scan Context选择了最大值这是经过对大量场景分析之后得出的结论。存储最大高度的第一个好处是对动态物体的鲁棒性更强。想象一个场景一片空旷的广场上停着一辆公交车还有一棵树。如果存平均值这辆公交车一旦开走描述子就会发生变化而这个变化和位置本身无关纯粹是动态物体引起的噪声。但如果存最大值在这个格子里占主导的往往是树顶或者建筑物的轮廓线公交车的车顶通常不会比树高多少对最大值的影响非常有限。第二个好处是最大高度对环境语义的捕捉更锐利。建筑物的边缘、高压线塔的顶部、路灯的灯臂这些元素在场景中往往是识别性地标。它们不一定占据很大的面积如果用平均值来算这些地标会被周围大量的低矮物体稀释但用最大值它们就能在矩阵对应的位置上形成一个清晰的“高峰”让整个描述子表现出明显的纹理结构。第三个好处是在检索时的判别力。描述子的本质是给每个地点一个“指纹”指纹之间的区分度决定了回环检测的准确率。平均值倾向于让大多数元素值接近地形高度矩阵整体变得平滑相似地点之间很难拉开差距最大值则能放大场景中的几何差异一个10层的建筑和一个2层的商铺在描述子里会表现出完全不同的峰值模式。当然最大高度也有它的代价。它对传感器噪声和极端误差比较敏感比如一个格子里偶然扫到一块飞溅的泥点就可能让这个格子的值失真。这也是为什么论文在构建描述子时会做一层z轴方向的过滤只保留合理范围内的点把明显的离群值提前去掉。2.3 描述子的相似度计算旋转不变性是怎么解决的有了两个描述子矩阵之后下一步是计算它们之间的距离。这里涉及一个核心难点旋转。假设机器人在同一个位置进行了两次扫描第一次车头朝东第二次车头朝北。把这两次扫描构建成描述子矩阵之后会发现矩阵的内容完全一样但所有列的顺序发生了整体平移。因为扇区是按起始方位角编号的一旦起始方位角变了整个矩阵的列布局就跟着循环位移了。Scan Context解决这个问题的思路很朴素与其找一个绝对不变的代表方向不如把对齐搜索本身作为匹配过程的一部分。当我们需要计算两帧A和B的相似度时对A矩阵做任意列的循环位移然后和B矩阵计算逐列距离所有位移中能取得的最小距离就作为最终距离。这样做在数学上非常干净它保证了只要两次扫描的内容一致无论相对偏航角是多少最终距离都会很接近因为总存在一个位移量能把两帧对齐。而且这个过程中还顺带得到了偏航角的估计值——让距离最小的那一位移量乘以单扇区对应的角度就是两帧之间相对旋转的粗估计。但这里有一个需要注意的点逐位移全搜索意味着要做N次矩阵距离计算如果扇区数是60就是60次完整的矩阵比较。对于一帧一帧的回环检测来说这个计算成本并不低。论文的分层检索策略正是为了解决这个问题而设计的先用粗粒度编码快速缩小候选范围只在少数候选帧上做完整的位移搜索。这个设计非常务实也是Scan Context能落到实时系统的关键原因之一。2.4 快速检索与偏航角估计的工程化设计粗粒度编码在Scan Context里叫Ring Key每个环对应一个值把描述子矩阵压缩成一个固定长度的向量。这个向量的每个元素代表对应环上所有扇区最大值的一个统计量。有了Ring Key之后两帧之间的匹配就可以先在这个低维空间里进行粗筛选分数超出阈值的候选帧才进入完整的描述子距离计算。我在复现时对比过两种检索方案。一种是论文里使用的基于Ring Key距离的线性搜索对每一帧历史数据都做一次高维向量的距离计算然后把排名靠前的帧挑出来。另一种是用最近邻索引来组织Ring Key向量比如用KD树或者基于哈希的方法。实测下来当地图规模不大时线性搜索的速度完全够用而且省去了构建索引带来的复杂度和内存开销。当地图规模增长到数万帧以上时建索引的价值才能体现出来。如果你做的是在线SLAM建议先在内存中维护一个简单的向量列表等帧数确实上去了再考虑索引。偏航角估计还有一个工程细节在对齐描述子列时由于扇区划分是离散的估计出的角度精度被限制在了单个扇区对应角度之内。比如60个扇区时角度分辨率就是6度。这个精度拿来粗对齐可以但不足以直接作为回环约束的最终姿态。实际工程中通常的做法是把Scan Context得到的偏航角作为初始值再交给ICP或者因子图优化做精对齐。Scan Context在这里的角色是“提供候选和粗约束”最终的高精度位姿修正仍然需要配准算法来完成。理解这一点很重要因为它在大量论文复现中是一个常见误区。有人认为加了Scan Context之后系统就应该具备完整的回环优化能力但实际上Scan Context的定位只是“回环检测提供者”它负责在正确的时刻给出正确的候选精确修正由后续模块完成。在系统集成时这个边界越清晰整个链路就越好调试。3. 论文实验结论与关键设计选择的分析3.1 实验环境与对比方法论文的验证工作主要是在公开的驾驶数据集上完成的同时也采集了一些园区、校园类的环境数据做补充测试。为了公平评估作者把Scan Context和当时主流的几类回环检测方案放在一起对比——包括基于高度直方图的方法、基于点云分割标签的方法以及基于传统手工特征的匹配方法。这些方法在当时的文献里都有各自的支持者。高度直方图方法把点云的高度分布统计成直方图计算简单但对空间结构的信息损失很大——两个完全不同的地点只要高度分布相似就会被误判成同一个。基于分割标签的方法需要额外的语义信息而且对分割质量的依赖非常高稍有错分割就会导致描述子剧变。对比结果出来后Scan Context在精度和召回率的平衡上明显优于其他方法。这个结论并不让人意外因为Scan Context在信息保留程度上占据优势它保留了每个扇区在径向方向上的高度峰值序列相当于在存储“这个方向上的天际线长什么样”。直方图丢失了方向信息而Scan Context把方向信息保留在了矩阵的列结构中。3.2 精度-召回率曲线怎么读评估回环检测通常看两个指标。精度表示检测出的回环里有多少是真回环召回率表示所有真回环中有多少被成功检测出来。这两个指标天然是矛盾的阈值放宽召回率上升但精度下降阈值收紧精度提升但召回率下降。好的方法在两者之间能取得更好的平衡反映在图形上就是曲线更靠近右上角。从论文的实验结果看Scan Context在不同场景下都能保持较高的召回率同时精度损失很小。这在驾驶场景中尤为稀缺车辆重新经过同一路段时视野可能完全不同道路另一侧可能有停靠的车辆遮挡视野季节变化还可能导致树叶挡掉了半边描述子。在这样的干扰下描述子仍然能保持稳定的匹配能力和它的“稀疏峰值结构”密切相关——少数关键要素如建筑轮廓、交通标志高度差即使被部分遮挡剩下的峰值仍然足够支撑匹配。读这条曲线时还要注意一个细节在精度100%对应的高阈值区间不同方法的召回率差异非常大。这意味着Scan Context的“强匹配”判定非常可靠——只要它说这是回环大概率就是真回环。这个特性在实际工程中尤其重要因为SLAM系统里一个错误的回环比错过一个回环危害大得多。错误回环会把地图拧到完全错误的位置而且这种错误一旦进入优化器很难自动恢复。3.3 参数对性能的影响Scan Context有两个主要参数环数和扇区数。环数决定了径向分辨率扇区数决定了角度分辨率。环数太小描述子之间缺乏区分度不同地点容易被混淆环数太大矩阵过于稀疏大量格子没有有效信息且计算量上升。论文里20环的配置在大多数场景下表现合理我实际测试时发现在更开阔的园区里减小环数到16性能下降不明显但速度更快在建筑密集的城区里增加到24环检索精度略有提升但计算量增加收益已经不大。这个参数和传感器量程、安装高度都有关系不要盲目照抄最好在自有数据上做一个小范围网格搜索。扇区数的选择影响更直接。扇区太多单个扇区的角度范围小点落入扇区的数量少描述子对噪声更敏感扇区太少角度分辨率不足偏航角估计的粒度也会变粗。60个扇区在大多数情况下很均衡但对于近距离扫描、场景结构简单的环境36个扇区也能工作同时还能减少循环位移搜索的计算量。还有一个容易被忽略的参数是高度范围裁剪。论文构建描述子之前会设置一个高度上下界超出范围的点直接丢弃。上界的作用是去掉建筑物上方的杂散点和飞鸟、树梢等偶然信号下界的作用是滤除地面点。这两个值对描述子质量的影响非常大但论文只给出了大致的推荐范围具体数值需要根据传感器安装位置来调。我当时使用16线激光雷达时把下界设为-0.4米上界设为2.5米效果不错。如果用的是64线或者固态激光雷达覆盖范围和点密度都不同这两个值通常需要重新标定。4. 复现过程中的实操细节与踩坑记录4.1 搭建一个最小可运行的描述子生成模块复现Scan Context时最忌讳的就是上来就把整个SLAM系统搭起来再调回环检测。正确路线是先单独把描述子生成模块跑通用几帧点云验证输出的矩阵是否符合直觉然后加上检索和距离计算最后再接回SLAM系统。描述子生成的代码逻辑其实不复杂核心就三步遍历点云中的每个点计算其极坐标表示根据环数和扇区数确定该点所属的网格索引更新该网格的最大高度值。但如果直接对每个点逐一遍历在点云规模大时会非常慢。一个优化技巧是先做体素下采样把点云从十几万个点降到可控数量比如两三万个点并不会对描述子质量产生明显影响。另一个技巧是利用排序和分段统计替代逐点判断比如先按环索引排序再在每个环内部按扇区索引分组求最大值这样能充分发挥现代CPU的向量化能力。我在初始版本里用的是最简单的双层循环加条件判断处理一帧点云需要大约120毫秒明显偏慢。改成先算好每个点的环索引和扇区索引再用分组归约方式计算后单帧时间降到30毫秒左右。如果还想再快可以把扇区索引计算改成流水线方式在点云接收的同时就开始构建描述子矩阵省掉中间存储步骤。提示调试描述子生成模块时最有效的验证方式是选取一个已知地点在附近移动采集几帧点云观察矩阵的行列峰值是否大致稳定。如果矩阵出现了大量零值区域或者随机噪声峰值大概率是坐标转换或者网格索引计算出了问题。4.2 检索与距离计算的性能瓶颈描述子距离计算在快速验证阶段可以直接按论文公式实现但接进SLAM系统后必须考虑性能。假设系统运行了10分钟以10Hz的帧率产生了6000帧历史数据每一帧新扫描都要和这6000帧计算距离再快的公式也会被拖垮。论文给出的层次检索策略在这里非常关键。先把所有历史帧的Ring Key存储在一个向量列表里新帧到达时先和全部历史帧的Ring Key计算粗距离只保留距离最小的若干帧作为候选然后才在候选帧上做完整的描述子距离计算和循环位移对齐。Ring Key的维度远小于完整的Scan Context矩阵粗距离计算的成本低一个数量级。我实测下来6000帧历史数据时粗筛选加精匹配的总耗时可以控制在20毫秒以内完全满足实时需求。再进一步优化时可以对Ring Key向量做归一化处理这样距离计算就等价于向量内积可以直接调用高性能线性代数库。另外一个有用的技巧是维护一个滑动窗口对于在线运行的SLAM系统距离很近的时间邻近帧几乎不可能产生有效回环系统可以直接跳过这些帧省掉大量无效计算。除了时间开销还有内存开销。每个描述子矩阵如果以浮点数形式存储6000帧大约是6000乘以1200乘以4字节约28.8MB规模尚可。但如果帧数是几万帧就需要考虑压缩存储或者定期清理策略否则内存占用会逐渐侵蚀系统稳定性。4.3 偏航角校正与回环优化联动描述子匹配成功后能直接得到一个匹配距离和对应的列偏移量。列偏移量乘以单扇区角度就可以换算成偏航角变化。在实际SLAM集成中这个偏航角通常作为粗略约束加入后端优化而不是直接覆盖当前位姿估计。为什么不能直接覆盖因为Scan Context的列对齐只有扇区级分辨率误差在正负半个扇区之间。对于60扇区配置这个误差范围是正负3度。对于建图任务3度的角度误差在几十米范围内就会造成明显的位置偏差所以必须通过后续的点云配准来精修。精修阶段的主流选择是ICP及其变体但要处理一个实际问题Scan Context给出的初始变换只包含偏航角位置平移未知。此时可以把两帧点云先按偏航角做旋转对齐然后用初始平移为零的ICP开始收敛。因为旋转已经大致对齐ICP的收敛范围明显扩大不容易陷入局部极小值。我尝试过省略这个粗对齐步骤直接用原始点云做ICP结果出现了多个错误收敛案例整体精度下降明显。这也印证了论文中“先粗后精”设计思路的工程价值。精配完成后还需要做一层几何一致性验证比如统计匹配点对比例或者计算配准后的残差分布。只有验证通过的候选才会被确认为回环约束加入后端优化。这个流程在工程上几乎是必需的因为它能挡住那些“描述子相似但几何不吻合”的假阳性。4.4 阈值调优的实际经验Scan Context匹配阈值的选取直接决定了系统的精度与召回率平衡。论文给出的参考值在不同场景下不一定适用最好的方式是在自有数据上做一个阈值扫描实验。我的做法是采集一段包含多次轨迹重叠的录制数据标注出真实回环帧对然后对不同的距离阈值运行检测器统计每个阈值下的真正率和假正率绘制曲线并选择合理的工作点。这个过程看起来繁琐但做一次之后阈值标定的依据就非常充分后续换传感器或换场景时只需要微调。值得注意的是阈值不是固定不变的。驾驶速度、场景开阔度、LiDAR线数都会影响描述子距离的分布范围。比如在高速公路场景中两侧结构稀疏描述子距离整体偏大阈值需要适当放宽在建筑密集的城区描述子距离分布比较紧凑阈值需要收紧以抑制误检。一个实用的技巧是同时监控当前帧与最近候选的距离比值用相对值代替绝对值做判断这样能在一定程度上自适应场景变化。5. 论文学习中最容易误解的几个点5.1 描述子和全局定位不是一回事很多刚接触Scan Context的人会把它和全局定位混为一谈。全局定位通常是“给定地图确定当前位置”的问题需要从一张完整的地图中检索当前位置而Scan Context主要用于回环检测它判断的是“当前这一帧是否访问过一个历史地点”。两者在输入输出上相似但在系统架构中的角色不同。实际做全局定位系统时可以把Scan Context用作粗定位阶段先通过描述子检索得到若干候选位置再做精配准。这种用法是可以的也确实有人这么做过。但要注意Scan Context匹配只能告诉你这两个地方长得像它无法直接给出位置坐标。真正的位置计算公式依赖于你如何关联描述子矩阵与已知地图的坐标系这一步需要自行设计。5.2 为什么不能直接拿描述子做位姿优化描述子矩阵中的元素是区域最大高度这个值本身不含点级别的对应关系。就算两帧描述子完全匹配你也不能直接读出“点A和点B对应”的信息。位姿优化中通常需要点对应关系来构建误差项而Scan Context只能提供一个整体性的相似度分数和粗略的偏航角精度远达不到优化所需的水平。一个常见误区是在后端优化中直接把Scan Context的距离作为约束因子。这本质上是在用一个噪音较高的标量来约束六自由度位姿很容易引入不稳定的优化行为。正确的做法是把Scan Context的结果当作“回环是否存在”的判定信号然后利用原始点云数据通过配准产生精确的相对位姿约束。也就是说描述子负责干粗活配准负责干细活二者分工明确。5.3 和深度学习方法的关系Scan Context这类基于几何结构的手工设计描述子在近年来受到了越来越多的深度学习方法挑战。基于深度学习的点云全局描述子通常能端到端学习出更具判别力的表示在某些数据集上的表现确实超过手工方法。但是Scan Context在工程领域仍然有独特的吸引力。它不需要训练数据部署成本几乎为零它的计算逻辑完全可解释出现问题能快速定位原因它在计算资源受限的嵌入式平台上表现稳定不需要GPU。对于大多数落地项目来说这些属性比“在某个榜单上多了一个点的召回率”重要得多。我在实际项目中也尝试过深度学习方法效果在标准测试集上很好但换到自定义场景时遇到了显著的域偏移问题——模型在训练环境里学到的特征无法完美适配新的传感器配置和环境布局。作为对比Scan Context在换场景后几乎不需要重新调整只需微调少数几个参数就能正常工作。这种“零训练成本”的鲁棒性让它在产品化过程中拥有不可替代的地位。论文学习这件事我的体会是一个优秀的方案不在于某个公式多巧妙而在于它把每个工程约束都考虑进了设计。Scan Context就是一个典型的例子——它牺牲了部分理论完美性换来了实时、稳健、可解释而这恰恰是实际系统最需要的品质。如果你也在做激光回环检测建议先把它吃透再考虑更花哨的方案你会在踩过那些坑之后明白我为什么这么说。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询