ransac拟合
链接:https://zhuanlan.zhihu.com/p/62238520
RANSAC简介
RANSAC(Random Sample Consensus,随机采样一致)算法是从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代算法。“外点”一般指的的数据中的噪声,比如说匹配中的误匹配和估计曲线中的离群点。所以,RANSAC也是一种“外点”检测算法。RANSAC算法是一种不确定算法,它只能在一种概率下产生结果,并且这个概率会随着迭代次数的增加而加大(之后会解释为什么这个算法是这样的)。RANSAC算最早是由Fischler和Bolles在SRI上提出用来解决LDP(Location Determination Proble)问题的。
对于RANSAC算法来说一个基本的假设就是数据是由“内点”和“外点”组成的。“内点”就是组成模型参数的数据,“外点”就是不适合模型的数据。同时RANSAC假设:在给定一组含有少部分“内点”的数据,存在一个程序可以估计出符合“内点”的模型。
算法基本思想和流程
RANSAC是通过反复选择数据集去估计出模型,一直迭代到估计出认为比较好的模型。
具体的实现步骤可以分为以下几步:
- 选择出可以估计出模型的最小数据集;(对于直线拟合来说就是两个点,对于计算Homography矩阵就是4个点)
- 使用这个数据集来计算出数据模型;
- 将所有数据带入这个模型,计算出“内点”的数目;(累加在一定误差范围内的适合当前迭代推出模型的数据)
- 比较当前模型和之前推出的最好的模型的“内点“的数量,记录最大“内点”数的模型参数和“内点”数;
- 重复1-4步,直到迭代结束或者当前模型已经足够好了(“内点数目大于一定数量”)。
迭代次数推导
这里有一点就是迭代的次数我们应该选择多大呢?这个值是否可以事先知道应该设为多少呢?还是只能凭经验决定呢? 这个值其实是可以估算出来的。下面我们就来推算一下。
假设“内点”在数据中的占比为\(t\)
\]
那么我们每次计算模型使用\(N\)个点的情况下,选取的点至少有一个外点的情况就是
\]
也就是说,在迭代 \(k\)次的情况下,\((1-t_n)^k\)就是\(k\)次迭代计算模型都至少采样到一个“外点”去计算模型的概率。那么能采样到正确的 \(N\)个点去计算出正确模型的概率就是
\]
通过上式,可以求得
\]
“内点”的概率 \(t\)通常是一个先验值。然后\(P\)是我们希望RANSAC得到正确模型的概率。如果事先不知道\(t\)的值,可以使用自适应迭代次数的方法。也就是一开始设定一个无穷大的迭代次数,然后每次更新模型参数估计的时候,用当前的“内点”比值当成\(t\)来估算出迭代次数。
用Python实现直线/平面拟合
import numpy as np
import random
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
# 将数据增加一个维度,最后一位是1
def augment(xys):
axy = np.ones((len(xys), len(xys[0]) + 1))
axy[:, :len(xys[0])] = xys
return axy
# 计算方程组的解
def estimate(xys):
axy = augment(xys)
return np.linalg.svd(axy)[-1][-1, :]
# 判断是否是inlier点, 方程:ax + by + c < threshold
def is_inlier(coeffs, xy, threshold = 0.01):
return np.abs(coeffs.dot(augment([xy]).T)) < threshold
def run_ransac(data, sample_size, goal_inliers, max_iterations, stop_at_goal=True, random_seed=None):
"""
:param data: 待拟合数据
:param sample_size:
2:两个点确定一条线
3:三个点确定一个平面。
:param goal_inliers: inliers点的个数
:param max_iterations: 最大迭代次数
:param stop_at_goal: 是否在满足goal_inliers条件时候结束迭代
:param random_seed: 随机初始化种子
:return:
1:返回拟合参数(a, b, c ...)
2: 拟合数据量
"""
best_ic = 0
best_model = None
random.seed(random_seed)
# random.sample cannot deal with "data" being a numpy array
data = list(data)
for i in range(max_iterations):
s = random.sample(data, int(sample_size))
m = estimate(s)
ic = 0
for j in range(len(data)):
if is_inlier(m, data[j]):
ic += 1
if ic > best_ic:
best_ic = ic
best_model = m
if ic > goal_inliers and stop_at_goal:
break
print('took iterations:', i+1, 'best model:', best_model, 'explains:', best_ic)
return best_model, best_ic
def line_fit():
n = 100
max_iterations = 100
goal_inliers = n * 0.3
# test data
xys = np.random.random((n, 2)) * 10
xys[:50, 1:] = xys[:50, :1]
plt.scatter(xys.T[0], xys.T[1])
# RANSAC
m, b = run_ransac(xys, 2, goal_inliers, max_iterations)
a, b, c = m
plt.plot([0, 10], [-c / b, -(c + 10 * a) / b], color=(0, 1, 0))
plt.show()
def plane_fit():
fig = plt.figure()
ax = mplot3d.Axes3D(fig)
def plot_plane(a, b, c, d):
xx, yy = np.mgrid[:10, :10]
return xx, yy, (-d - a * xx - b * yy) / c
n = 100
max_iterations = 100
goal_inliers = n * 0.3
# test data
xyzs = np.random.random((n, 3)) * 10
xyzs[:50, 2:] = xyzs[:50, :1]
ax.scatter3D(xyzs.T[0], xyzs.T[1], xyzs.T[2])
# RANSAC
m, b = run_ransac(xyzs, 3, goal_inliers, max_iterations)
a, b, c, d = m
xx, yy, zz = plot_plane(a, b, c, d)
ax.plot_surface(xx, yy, zz, color=(0, 1, 0, 0.5))
plt.show()
if __name__ == '__main__':
# line_fit() # 拟合直线
plane_fit() # 拟合平面
ransac拟合的更多相关文章
- PCL使用RANSAC拟合三位平面
1.使用PCL工具 //创建一个模型参数对象,用于记录结果 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); ...
- RANSAC拟合算法
最小二乘法只适合与误差较小的情况.试想一下这种情况,假使需要从一个噪音较大的数据集中提取模型(比方说只有20%的数据时符合模型的)时,最小二乘法就显得力不从心了. 算法简介 随机抽样一致算法(RANd ...
- PCL利用RANSAC自行拟合分割平面
利用PCL中分割算法. pcl::SACSegmentation<pcl::PointXYZ> seg; ,不利用法线参数,只根据模型参数得到的分割面片,与想象的面片差距很大, pcl:: ...
- OpenCV2马拉松第25圈——直线拟合与RANSAC算法
计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/28118095 收入囊中 最小二乘法(least ...
- 29 基于PCL的点云平面分割拟合算法技术路线(针对有噪声的点云数据)
0 引言 最近项目中用到了基于PCL开发的基于平面的点云和CAD模型的配准算法,点云平面提取采用的算法如下. 1 基于PCL的点云平面分割拟合算法 2 参数及其意义介绍 (1)点云下采样 1. 参数: ...
- 计算机视觉基本原理——RANSAC
公众号[视觉IMAX]第31篇原创文章 一 前言 对于上一篇文章——一分钟详解「本质矩阵」推导过程中,如何稳健地估计本质矩阵或者基本矩阵呢?正是这篇文章重点介绍的内容. 基本矩阵求解方法主要有: 1) ...
- [PCL]模型拟合方法——随机采样一致性
SACSegmentation封装了多种Ransac方法,包括: RandomSampleConsensus, LeastMedianSquares, MEstimatorSampleConsensu ...
- 使用Python基于HyperLPR/Mask-RCNN的中文车牌识别
基于HyperLPR的中文车牌识别 Bolg:https://blog.csdn.net/lsy17096535/article/details/78648170 https://www.jiansh ...
- 三维点集拟合:平面拟合、RANSAC、ICP算法
ACM算法分类:http://www.kuqin.com/algorithm/20080229/4071.html 一: 拟合一个平面:使用SVD分解,代码里面去找吧 空间平面方程的一般表达式为: A ...
- RANSAC与 最小二乘(LS, Least Squares)拟合直线的效果比较
代码下载地址: 1.Matlab版本:http://pan.baidu.com/s/1eQIzj3c.进入目录后,请自行定位到该博客的源代码与数据的目录“
随机推荐
- Day20.1:关于this、super的解析
this.super详解 当我们在外部程序调用一个类的方法,如果这个类的方法与其父类的方法重载,我们需要用this.super进行区分 this在Java中是一个复杂的关键字,this的使用形式体现了 ...
- C++编程笔记(GPU并行编程)
目录 一.配置并使用 二.代码 三.内存管理 数组的分配 一.配置并使用 环境:Windows10 + CLion + VS2019 cuda的安装,并行的话只需要安装cuda,cuDNN就不必了 编 ...
- 【每日一题】【动态规划】2022年1月30日-NC127 最长公共子串
描述 给定两个字符串str1和str2,输出两个字符串的最长公共子串 题目保证str1和str2的最长公共子串存在且唯一. 方法1:dp数组存子串 import java.util.*; public ...
- 【Shell脚本案例】案例3:批量创建100个用户并设置密码
一.背景 新入职员工创建用户 二.常规操作 useradd zhangsan ls /home/ password zhangsan 三.考虑问题 1.实现自动输入密码,将其存到文件中 passwor ...
- go操作Kfaka
目录 1. Kafka介绍 1.1.1. Kafka是什么 1.1.2. Kafka的特点 1.1.3. 常用的场景 1.1.4. Kafka中包含以下基础概念 1.1.5. 消息 1.1.6. 消息 ...
- 真正“搞”懂HTTP协议06之body的玩法(理论篇)
本来啊,本来,本来我在准备完善这个鸽了四年的系列的时候,是打算按照时间的顺序来完成的,好吧.我承认那个时候考虑的稍稍稍稍稍微有些不足,就是我忽略了HTTP协议的"模块性".因为虽然 ...
- cs231n__4.1 Backpropagation and Neural Network
CS231n 4.1 Backpropagation 回顾: 两个损失函数: 优化的方法: 如何计算梯度: 用有限差分估计 直接计算偏导数(解析梯度) 今天,我们要学习如何计算任意复杂度的解析梯度 要 ...
- Apache Dubbo 官方正式发布 Spring 6 & Spring Boot 3 支持
Dubbo 简介 Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java.Golang 等多语言 SDK 实现.使用 Dubbo 开发的 ...
- vscode下无法使用fresh的问题
使用了go get github.com/pilu/fresh ,需要 go install github.com/pilu/fresh. 在带用go.mod的版本中,go get只是下载代码和帮助修 ...
- Vue3 企业级优雅实战 - 组件库框架 - 9 实现组件库 cli - 上
上文搭建了组件库 cli 的基础架子,实现了创建组件时的用户交互,但遗留了 cli/src/command/create-component.ts 中的 createNewComponent 函数,该 ...