最小二乘问题详解22:抗差估计与增量式SFM的工程稳健实现
最小二乘问题详解22抗差估计与增量式SFM的工程稳健实现大家好欢迎来到《最小二乘问题详解》系列的第22篇。前几篇我们聊了标准最小二乘LS的推导、QR分解、Cholesky分解还有非线性优化的高斯牛顿和LM算法。但今天这篇我们要聊点“接地气”的——工程中到底怎么让最小二乘在真实数据上不崩。真实数据里没有“干净”的高斯噪声只有各种野值outlier、错误匹配、遮挡、传感器跳变。如果你直接拿标准最小二乘去优化一个野值就能把你的解拉飞。所以今天我们要讲两个核心主题1.抗差估计Robust Estimation—— 怎么让误差函数对野值不敏感。2.增量式SFMIncremental Structure from Motion—— 在大规模三维重建里怎么高效且稳健地不断加入新图像而不是每次都从头解一遍。我会结合代码示例尽量讲得通俗。—## 一、为什么标准最小二乘这么“脆”先看一个最简单的线性回归问题。假设我们有数据点(x_i, y_i)想拟合一条直线y ax b。标准最小二乘的目标是minimize Σ (y_i - (a*x_i b))²这个二次代价函数意味着误差越大惩罚是平方增长的。如果某个点是个野值比如传感器故障y值偏离了10倍它的残差平方会主导整个目标函数最终把拟合线硬生生拉向它。这就是“脆”的根源平方损失函数对长尾误差无约束。—## 二、抗差估计让误差“饱和”抗差估计的核心思想是替换损失函数让大残差带来的惩罚不再无限增长而是趋于饱和。常用的损失函数有-Huber损失小误差用平方大误差用线性。-Cauchy损失更平滑的饱和。-Tukey损失超过阈值直接权重归零完全丢弃野值。我们来看一个简单的Python实现对比标准最小二乘和Huber抗差估计的效果。pythonimport numpy as npimport matplotlib.pyplot as pltfrom scipy.optimize import minimize# 生成一些带野值的数据np.random.seed(42)x np.linspace(0, 10, 50)true_a, true_b 2.0, 1.0y true_a * x true_b np.random.normal(0, 0.5, sizex.shape)# 人为加入野值10个点被严重污染outlier_idx np.random.choice(len(x), 10, replaceFalse)y[outlier_idx] np.random.normal(0, 20, size10)# 标准最小二乘def ls_cost(params): a, b params return np.sum((y - (a*x b))**2)# Huber损失delta1.0def huber_loss(r, delta1.0): r np.abs(r) return np.where(r delta, 0.5 * r**2, delta * (r - 0.5*delta))def huber_cost(params): a, b params residual y - (a*x b) return np.sum(huber_loss(residual))# 优化res_ls minimize(ls_cost, [0, 0], methodBFGS)res_huber minimize(huber_cost, [0, 0], methodBFGS)print(f标准LS: a{res_ls.x[0]:.3f}, b{res_ls.x[1]:.3f})print(fHuber: a{res_huber.x[0]:.3f}, b{res_huber.x[1]:.3f})print(f真实值: a{true_a}, b{true_b})# 画图plt.scatter(x, y, alpha0.6, labeldata)plt.plot(x, true_a*x true_b, k--, labeltruth)plt.plot(x, res_ls.x[0]*x res_ls.x[1], r-, labelLS)plt.plot(x, res_huber.x[0]*x res_huber.x[1], g-, labelHuber)plt.legend()plt.show()运行结果你会发现标准LS的拟合线被野值拉得歪七扭八而Huber几乎完美恢复了真实直线。这就是抗差估计的威力。关键点抗差估计的优化目标不再是二次函数通常我们用迭代重加权最小二乘IRLS来求解因为Huber等损失可以转化为权重加权的LS问题。—## 三、增量式SFM从“全局”到“增量”SFMStructure from Motion是从多张二维图像恢复三维结构和相机位姿的问题。传统做法是全局优化Bundle Adjustment把所有点、所有相机一起丢进一个巨大的最小二乘问题里。但工程上当图像数量到几千张时全局BA的计算量会爆炸。于是有了增量式SFM每次加入一张新图像只优化局部相关的变量而不是全部重来。经典的流程是1.初始化选两帧有足够匹配的图像做基础矩阵或本质矩阵估计得到初始相机位姿和三角化点。2.加入新帧用PnPPerspective-n-Point估计新相机的位姿。3.三角化新点新图像与已有图像匹配三角化出新的三维点。4.局部BA只优化与当前帧相关的相机和点控制窗口大小。5.全局BA定期触发当累积一定误差后做一次全量优化。其中抗差估计在每一步都至关重要——因为特征匹配不可避免会有错误匹配野值。比如在PnP中我们用DLT或EPnP求初始解然后用RANSAC剔除野值再用抗差BA精化。下面是一个简化的增量式SFM核心流程伪代码用Python描述简化了相机模型pythonimport numpy as npfrom scipy.sparse import lil_matrixfrom scipy.optimize import least_squares# 假设我们有一系列相机位姿简化只存旋转和平移class Camera: def __init__(self, R, t): self.R R # 3x3 旋转 self.t t # 3x1 平移# 模拟一个简单的增量式SFMdef incremental_sfm(frames, matches): # frames: list of dict, 每个包含2D特征点 # matches: 帧间匹配关系 cameras [] points_3d [] # 三维点列表 point_observations [] # (cam_idx, point_idx, 2D坐标) # Step 1: 初始化前两帧 # 用基础矩阵 三角化这里省略具体实现 R0, t0 np.eye(3), np.zeros(3) R1, t1 estimate_essential_matrix(frames[0], frames[1]) # 假设实现 cameras.append(Camera(R0, t0)) cameras.append(Camera(R1, t1)) # 三角化初始点 pts triangulate_two_views(frames[0], frames[1], cameras[0], cameras[1]) points_3d.extend(pts) # Step 2: 增量加入后续帧 for i in range(2, len(frames)): # 用PnP估计新相机位姿 # 先找与已有3D点的匹配 correspondences get_2d_3d_matches(frames[i], points_3d, matches) R_new, t_new solve_pnp_robust(correspondences) # 内部用RANSACHuber cameras.append(Camera(R_new, t_new)) # 三角化新的3D点 new_pts triangulate_with_previous(frames[i], frames[i-1], cameras[i], cameras[i-1]) points_3d.extend(new_pts) # 局部BA只优化最近K帧和相关的3D点 if i % 5 0: local_bundle_adjustment(cameras[-5:], points_3d, point_observations) # Step 3: 最后全局BA global_bundle_adjustment(cameras, points_3d, point_observations) return cameras, points_3d# 实际BA中我们会构造一个稀疏雅可比矩阵def bundle_adjustment(cameras, points_3d, observations): # 构造稀疏矩阵使用scipy的least_squares # 这里只展示核心思想 def residual(params): # 重投影误差 errs [] for obs in observations: cam_idx, pt_idx, (u, v) obs R, t cameras[cam_idx].R, cameras[cam_idx].t X points_3d[pt_idx] proj project(R, t, X) # 投影函数 errs.append(proj - (u, v)) return np.concatenate(errs) # 使用Huber损失的抗差BA res least_squares(residual, initial_params, losshuber, f_scale1.0) return res.x这段代码省略了很多几何运算细节但核心骨架就是增量加入 → 局部BA → 定期全局BA并且每一步都用抗差损失。—## 四、工程稳健性的一些“坑”和技巧在实际工程中光有理论还不够还得注意几个细节1.阈值选择Huber的delta、RANSAC的内点阈值都需要根据图像噪声水平、特征匹配精度来调。太严则丢内点太松则留野值。2.增量BA的窗口大小窗口太小误差会累积窗口太大计算量又上去了。通常经验值是5-10帧。3.相机退化如果新图像与已有视图重叠太少三角化出来的点会很差。这时候要检测“退化”情况比如检查最小特征值必要时拒绝加入该帧。4.浮点误差与归一化在计算本质矩阵或PnP之前要对2D坐标做归一化centroid scaling否则数值不稳定。—## 五、总结今天我们讲了两个工程上不可或缺的“防弹衣”-抗差估计通过Huber、Cauchy等损失函数让最小二乘对野值不敏感。核心实现是IRLS或直接调用scipy.optimize.least_squares的losshuber。-增量式SFM不是一次性解全局而是先初始化两帧然后一帧帧加入每步做局部BA定期再做全局BA。既保证了计算效率也通过抗差损失保证了稳健性。工程和理论的差距往往就体现在这些“脏活累活”上。理解了抗差和增量策略你才能真正把最小二乘用在真实场景里——无论是SLAM、三维重建还是标定问题。下一期我们可以聊聊鲁棒核函数在大规模BA中的稀疏求解加速或者位姿图优化的抗差方法。有想听的话题欢迎评论区留言。我们下期见

相关新闻

Python实现高效相似性检索:FAISS实战指南

Python实现高效相似性检索:FAISS实战指南

1. 项目概述在数据密集型应用中,相似性检索是一个常见但极具挑战性的需求。想象一下,你手头有数百万条文本、图片或商品数据,如何快速找到与目标最相似的几条记录?这就是相似性检索要解决的核心问题。Python作为数据科学领域的主流…

2026/10/14 14:40:51 阅读更多 →
2026涉密项目投标缺资质怎么补救?3类缺口的应急判断与行动清单

2026涉密项目投标缺资质怎么补救?3类缺口的应急判断与行动清单

周一上午,一家做安防工程的企业接到消息:某单位涉密安防监控项目正在招标,投标截止周五下午。负责人让投标专员赶紧准备,专员翻完招标公告的资格要求,发现一条——"供应商须具备涉密信息系统集成资质(…

2026/10/14 14:39:41 阅读更多 →
SVN服务搭建实战:账号管理、自动更新与日志权限控制

SVN服务搭建实战:账号管理、自动更新与日志权限控制

1. 项目概述:从零搭建一个可控的SVN服务 在团队协作开发中,版本控制是基石。虽然Git如今风头正劲,但在许多传统企业、游戏开发、嵌入式或特定规范的软件项目中,SVN(Subversion)凭借其集中式管理、严格的目录…

2026/10/12 21:22:09 阅读更多 →

最新新闻

ComfyUI本地部署全攻略:从整合包到手动部署,跑通AI绘画工作流

ComfyUI本地部署全攻略:从整合包到手动部署,跑通AI绘画工作流

在家用电脑上折腾出一个自己的 ComfyUI,这事说难不难,说简单,又确实能把一大批人挡在门外。我见过太多人收藏了十几篇部署教程,结果打开一看全是"打开命令行输入 pip install xxx",人直接就懵了;…

2026/10/14 14:39:56 阅读更多 →
开源产学研协同:从技术转化到项目管理实践

开源产学研协同:从技术转化到项目管理实践

1. 论坛背景与核心价值开源技术作为连接科研创新与产业落地的桥梁,正在全球范围内重塑技术协作生态。COSCon25产研开源协同论坛的议程发布,标志着开源社区在推动产学研深度融合方面迈出了实质性步伐。这个论坛最吸引我的地方在于它精准抓住了当前技术转化…

2026/10/14 14:39:56 阅读更多 →
基于多维特征融合的互联网贷款客户聚类与风险预警可视化大屏实战

基于多维特征融合的互联网贷款客户聚类与风险预警可视化大屏实战

1. 项目背景与核心问题拆解1.1 这个毕设到底在做什么先把标题拆开看。“基于多维特征融合的互联网贷款客户聚类与风险预警研究”加上“基于数据挖掘的互联网贷款用途与风险定价可视化研究”,两个子课题合在一起,本质上是一件事:拿一批互联网贷…

2026/10/14 14:39:56 阅读更多 →
FairMOT深入解读:检测与ReID如何在anchor-free框架下实现公平共存

FairMOT深入解读:检测与ReID如何在anchor-free框架下实现公平共存

FairMOT 这篇论文在目标跟踪圈子里火了好一阵了,但网上大多数解读都停在“它是 anchor-free 的”这个层面,然后就开始讲结构图。真正动手做过 MOT 的人都知道,FairMOT 的价值远不止换了个检测头这么简单,它其实是把“检测”和“重…

2026/10/14 14:39:56 阅读更多 →
QML Popup完全指南:核心原理、常用子类与自定义实战

QML Popup完全指南:核心原理、常用子类与自定义实战

做QML界面开发有一段时间后你会发现,凡是需要“浮在页面最上层”的东西,基本都绕不开Popup这个组件。不管是右键菜单、下拉选项、消息提醒、二次确认弹窗,还是那种从屏幕边缘滑出来的抽屉导航,Popup在Qt Quick Controls 2里就是一…

2026/10/14 14:39:56 阅读更多 →
Unity2D弹球游戏可运行完整项目:物理引擎+碰撞+UI闭环实现

Unity2D弹球游戏可运行完整项目:物理引擎+碰撞+UI闭环实现

简介:这是一份面向Unity初学者与2D游戏开发入门者的可运行完整项目,聚焦弹球游戏核心逻辑实现,帮助开发者掌握不依赖物理引擎的2D运动控制、碰撞检测、挡板交互、得分系统及UI状态管理等关键技能。资源包含432个文件,以128个info配…

2026/10/14 14:38:54 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →