news 2026/7/16 11:34:27

RANSAC算法原理与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RANSAC算法原理与应用

一、RANSAC 是解决什么问题的?

https://www.bilibili.com/video/BV1tM41187br/?spm_id_from=333.337.search-card.all.click&vd_source=52997da921a43b4ed3611981bbdf91a4

https://www.bilibili.com/video/BV1sj411v7Vo/?spm_id_from=333.337.search-card.all.click&vd_source=52997da921a43b4ed3611981bbdf91a4

👉在含有大量离群点(Outliers)的数据中,鲁棒地估计模型参数

典型场景

  • 特征匹配中错误匹配很多

  • 点云中噪声 + 伪点

  • 拟合直线 / 平面 / 单应矩阵 / 基础矩阵

  • PnP 前的 2D–3D 对应点中有假点

普通最小二乘(LS)的问题:

  • 对离群点极其敏感

  • 一个坏点就能“拉歪”整个模型

RANSAC 的思想是:

宁可只用一小撮“干净点”,也不被脏点污染

宁可只用一小撮“干净点”,也不被脏点污染

宁可只用一小撮“干净点”,也不被脏点污染


二、RANSAC核心思想

随机抽最小样本 → 拟合模型 → 统计内点 → 重复 → 选内点最多的模型

利用随机采样和一致性检验的方法,来取分数据中的内点和外点,内点是指符合模型的数据,外点是指不符合模型的数据。


三、RANSAC 算法流程(标准版)

设模型参数为 θ


Step 1:随机采样(Minimal Sample Set)

  • 随机选最小数量的点

  • 例如:

    • 直线:2 点

    • 平面:3 点

    • 单应矩阵:4 对点

    • 基础矩阵:8 点(8-point)

分别计算所有点到当前模型的距离


Step 2:模型估计

  • 用最小样本估计模型

  • 通常是解析解 / DLT


Step 3:一致性检测(Inlier Test)

  • 对所有点计算误差:

Step 4:统计内点数

  • 记录内点数量


Step 5:重复 N 次

  • 找到内点最多的模型

Step 6(可选):模型重估

  • 用所有内点

  • 再做一次最小二乘 / LM

📌RANSAC + LM = 工程黄金搭档

四、RANSAC 数学本质

1️⃣ 目标不是最小误差,而是:

2️⃣ 内点概率驱动迭代次数

若:

  • 内点比例:w

  • 最小样本数:s

  • 成功概率:p

所需迭代次数:

案例一RANSAC 拟合二维直线(最经典)

1️⃣ 构造数据(含离群点)

clc; clear; close all; % 真实直线 y = 2x + 1 x_in = linspace(0,10,50); y_in = 2*x_in + 1 + randn(size(x_in))*0.3; % 离群点 x_out = rand(1,20)*10; y_out = rand(1,20)*20; x = [x_in x_out]; y = [y_in y_out]; figure; hold on; grid on; scatter(x, y, 'b'); title('原始数据(含离群点)');

2️⃣ RANSAC 实现

clc; clear; close all; % 真实直线 y = 2x + 1 50个直线上的点 x_in = linspace(0,10,50); y_in = 2*x_in + 1 + randn(size(x_in))*0.3; % 离群点 20个离群点 x_out = rand(1,20)*10; y_out = rand(1,20)*20; % 直线点+离群点=70 个 x = [x_in x_out]; y = [y_in y_out]; figure; hold on; grid on; scatter(x, y, 'b'); title('原始数据(含离群点)'); % 迭代次数 num_iter = 1000; % 点到直线的距离阈值判断 threshold = 0.5; % 把最好的内点集合起来 best_inliers = []; for i = 1:num_iter % 随机选2个点 idx = randperm(length(x), 2); x1 = x(idx(1)); y1 = y(idx(1)); x2 = x(idx(2)); y2 = y(idx(2)); % 拟合直线 ax + by + c = 0 a = y2 - y1; b = x1 - x2; c = x2*y1 - x1*y2; % 计算所有(这里是70个点)点到直线距离 dist = abs(a*x + b*y + c) / sqrt(a^2 + b^2); inliers = find(dist < threshold); if length(inliers) > length(best_inliers) best_inliers = inliers; end end x_in = x(best_inliers); y_in = y(best_inliers); % 拟合 p = polyfit(x_in, y_in, 1); x_fit = linspace(0,10,100); y_fit = polyval(p, x_fit); figure; hold on; grid on; scatter(x, y, 'b'); scatter(x_in, y_in, 'r'); plot(x_fit, y_fit, 'k', 'LineWidth',2); legend('All points','Inliers','RANSAC Line'); title('RANSAC 直线拟合结果');

案例二 RANSAC 拟合圆

原理:

1️⃣ 圆的一般方程

2️⃣ 最小样本数(Minimal Sample Set)

👉3 个不共线点
(这是圆的解析最小解)


3️⃣ 点到圆的误差(RANSAC 判据)

常用误差:

实例

1:构造测试数据(含离群点)

clc; clear; close all; % 真实圆参数 a0 = 5; b0 = 4; r0 = 3; theta = linspace(0,2*pi,80); x_in = a0 + r0*cos(theta) + randn(size(theta))*0.05; y_in = b0 + r0*sin(theta) + randn(size(theta))*0.05; % 离群点 x_out = rand(1,30)*10; y_out = rand(1,30)*10; x = [x_in x_out]; y = [y_in y_out]; figure; hold on; axis equal; grid on; scatter(x, y, 'b'); title('原始数据(含离群点)');

2、RANSAC 拟合圆核心代码

num_iter = 2000; threshold = 0.1; best_inliers = []; best_circle = []; N = length(x); for k = 1:num_iter % 随机选 3 个点 idx = randperm(N,3); x1 = x(idx(1)); y1 = y(idx(1)); x2 = x(idx(2)); y2 = y(idx(2)); x3 = x(idx(3)); y3 = y(idx(3)); % 判断是否共线(行列式) if abs(det([x1 y1 1; x2 y2 1; x3 y3 1])) < 1e-3 continue; end % ===== 解析求圆心和半径 ===== A = 2*[x2-x1, y2-y1; x3-x1, y3-y1]; B = [x2^2+y2^2 - x1^2-y1^2; x3^2+y3^2 - x1^2-y1^2]; C = A\B; a = C(1); b = C(2); r = sqrt((x1-a)^2 + (y1-b)^2); % ===== 计算内点 ===== dist = abs(sqrt((x-a).^2 + (y-b).^2) - r); inliers = find(dist < threshold); % 更新最优模型 if length(inliers) > length(best_inliers) best_inliers = inliers; best_circle = [a b r]; end end

3、用内点进行最小二乘精修(强烈推荐)

xin = x(best_inliers); yin = y(best_inliers); % 代数最小二乘(线性) A = [2*xin(:), 2*yin(:), ones(length(xin),1)]; B = xin(:).^2 + yin(:).^2; param = A\B; a = param(1); b = param(2); r = sqrt(param(3) + a^2 + b^2);

4、可视化

theta = linspace(0,2*pi,200); xc = a + r*cos(theta); yc = b + r*sin(theta); figure; hold on; axis equal; grid on; scatter(x, y, 'b'); scatter(x(best_inliers), y(best_inliers), 'r'); plot(xc, yc, 'k', 'LineWidth',2); legend('All points','Inliers','RANSAC Circle'); title('RANSAC 圆拟合结果');

案例三、RANSAC 拟合平面

典型应用:

  • 点云地面分割(无人车)

  • 工件基准面

  • 结构光参考平面

  • ICP / PnP / BA 前的几何约束

平面数学模型

1️⃣ 平面一般式

2️⃣ 最小样本数(Minimal Sample Set)

👉3 个不共线点

3️⃣ 点到平面距离(RANSAC 判据)

实例:

构造测试点云(含离群点)

clc; clear; close all; % 真实平面:z = 0.5x + 0.2y + 1 [xg, yg] = meshgrid(linspace(0,5,20)); zg = 0.5*xg + 0.2*yg + 1 + randn(size(xg))*0.05; % 转为点集 pts_in = [xg(:), yg(:), zg(:)]; % 离群点 pts_out = rand(80,3)*6; pts = [pts_in; pts_out];

RANSAC 主循环

num_iter = 2000; threshold = 0.1; best_inliers = []; best_plane = []; N = size(pts,1); for k = 1:num_iter % 随机选3点 idx = randperm(N,3); p1 = pts(idx(1),:); p2 = pts(idx(2),:); p3 = pts(idx(3),:); % 共线判断 v1 = p2 - p1; v2 = p3 - p1; n = cross(v1,v2); if norm(n) < 1e-6 continue; end % 平面参数 n = n / norm(n); d = -dot(n,p1); % 点到平面距离 dist = abs(pts*n' + d); inliers = find(dist < threshold); if length(inliers) > length(best_inliers) best_inliers = inliers; best_plane = [n d]; end end

用内点进行最小二乘精修(SVD)

in_pts = pts(best_inliers,:); % 去中心 centroid = mean(in_pts,1); Q = in_pts - centroid; % SVD [~,~,V] = svd(Q,0); n = V(:,end); d = -dot(n,centroid); best_plane = [n' d];

结果可视化

figure; hold on; grid on; axis equal; scatter3(pts(:,1),pts(:,2),pts(:,3),'b.'); scatter3(in_pts(:,1),in_pts(:,2),in_pts(:,3),'r.'); % 绘制平面 [xp,yp] = meshgrid(linspace(0,5,10)); zp = -(best_plane(1)*xp + best_plane(2)*yp + best_plane(4)) / best_plane(3); surf(xp,yp,zp,'FaceAlpha',0.5,'EdgeColor','none'); legend('All points','Inliers','Plane'); title('RANSAC 平面拟合');

HALCON / PCL 对应参数

segment_planes_object_model_3d( ObjectModel3D, 'distance_threshold', DistanceThreshold, 'min_support', MinSupport, ObjectModel3DPlanes, PlaneInfo ) pcl::SACSegmentation<pcl::PointXYZ> seg; seg.setModelType(pcl::SACMODEL_PLANE); seg.setMethodType(pcl::SAC_RANSAC); seg.setDistanceThreshold(0.01); seg.setMaxIterations(1000); seg.setProbability(0.99);

案例四、

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

Cursor接入GLM-4.7实战:中文优先的IDE编程副驾驶搭建指南

1. 项目概述&#xff1a;为什么要在 Cursor 中“硬刚” GLM-4.7&#xff1f;你是不是也经历过这种时刻&#xff1a;写一段 Python 数据清洗脚本&#xff0c;Cursor 默认调用的模型在处理 pandas 的groupby().agg()复合操作时反复出错&#xff1b;或者调试一个嵌套三层的 Vue 组…

作者头像 李华
网站建设 2026/7/16 11:33:00

3分钟搞定!ncmdumpGUI:网易云音乐NCM文件解密转换终极指南

3分钟搞定&#xff01;ncmdumpGUI&#xff1a;网易云音乐NCM文件解密转换终极指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 还在为网易云音乐下载的歌曲…

作者头像 李华
网站建设 2026/7/16 11:32:48

抖音内容批量下载器:从单视频到全账号的智能采集方案

抖音内容批量下载器&#xff1a;从单视频到全账号的智能采集方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppor…

作者头像 李华
网站建设 2026/7/16 11:32:20

Ascend C ReduceDataBlock归约

ReduceDataBlock 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言&#xff0c;原生支持C和C标准规范&#xff0c;主要由类库和语言扩展层构成&#xff0c;提供多层级API&#xff0c;满足多维场景算子开发诉求。 项目地址: https://gitcod…

作者头像 李华
网站建设 2026/7/16 11:31:56

Linux进程管理核心概念与实战技巧

1. Linux进程管理核心概念解析在Linux系统中&#xff0c;进程管理是系统管理员和开发人员必须掌握的核心技能。进程作为程序在操作系统中的执行实例&#xff0c;其管理能力直接关系到系统的稳定性和性能表现。1.1 进程的生命周期Linux进程通常经历以下几个状态变迁&#xff1a;…

作者头像 李华