精华内容
下载资源
问答
  • Ransac拟合平面 参考链接:链接1、链接2、链接3 、最小二乘 、链接4 、一种新方法 项目背景简介:考虑到实际项目识别平面上的非编码点,非编码点的重建精度较高,基本在一个平面上,并不希望使用任何库(传统方式...

    Ransac拟合平面

    参考链接:链接1链接2链接3最小二乘链接4一种新方法

    项目背景简介:考虑到实际项目识别平面上的非编码点,非编码点的重建精度较高,基本在一个平面上,并不希望使用任何库(传统方式基于最小二乘的SVD最小特征向量),故采用本文方式。拍摄环境中存在杂点,在此方式基础上加入Ransac。此种方式也有本身的局限性。

    局限性:此方法将最小化垂直于主轴的残差的平方,而不是垂直于平面的残差的平方。如果残差很小(即,所有点都靠近结果平面),则此方法可能就足够了。但是,如果您的观点更加分散,则此方法可能不是最合适的方法。

    1、最小二乘优化目标方程(此方法主要在这进行简单操作)

    ax + by + cz = -d ---> ax + by + d = -z;

    思路总结:

    1. 计算点的质心
    2. 计算相对于质心的点的协方差矩阵
    3. 计算协方差矩阵的最小特征向量。这是平面法线。
    • 方法二此方法将最小化垂直于平面的残差的平方转变为最小化垂直于主轴的残差的平方。
      选择性优化x、y、z其中主轴,选择最大绝对值的平面法线分量进行优化。

    思路总结:

    1. 计算点的质心
    2. 计算相对于质心的点 的协方差矩阵
    3. 找到主轴(具有最大绝对值的平面法线分量)并沿该轴进行线性回归
    • 方法三此文为改进方法:X,Y和Z轴进行线性回归

    思路总结:

    1. 计算点的质心
    2. 计算相对于质心的点的协方差矩阵
    3. 沿X,Y和Z轴进行线性回归
    4. 基于行列式平方的线性回归结果的权重

    2、C++编写

    #pragma once
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    #include <vector>
    
    
    struct float3
    {
        float x, y, z;
    };
    
    struct plane
    {
        float x, y , z, D;
    };
    
    inline void ImportPointCloud(char& filename, std::vector<float3> &points)
    {
        float3 temp;
        bool mStatus = false;
        std::ifstream import;
        import.open(&filename);
        while (import.peek() != EOF)
        {
            import >> temp.x >> temp.y >> temp.z;
            points.push_back(temp);
        }
        import.close();
    }
    
    inline float DistanceToPlane(float3& point, plane& mPlane)
    {
         return (mPlane.x * point.x + mPlane.y * point.y + mPlane.z * point.z + mPlane.D);
    }
    
    inline void PlaneFromPoints(std::vector<float3> &points, plane &mPlane)
    {
        if (points.size() < 3) throw std::runtime_error("Not enough points to calculate plane");
    
        float3 sum = { 0,0,0 };
     
        for (int i = 0; i < static_cast<int>(points.size()); i++)
        {
            sum.x += points[i].x;
            sum.y += points[i].y;
            sum.z += points[i].z;
        }
    
        float3 centroid = { 0,0,0 };
        centroid.x = sum.x / float(points.size());
        centroid.y = sum.y / float(points.size());
        centroid.z = sum.z / float(points.size());
        
    
        float xx = 0, xy = 0, xz = 0, yy = 0, yz = 0, zz = 0;
        for (int i = 0; i < static_cast<int>(points.size()); i++)
        {
            float3 temp;
            temp.x = points[i].x - centroid.x;
            temp.y = points[i].y - centroid.y;
            temp.z = points[i].z - centroid.z;
       
            xx += temp.x * temp.x;
            xy += temp.x * temp.y;
            xz += temp.x * temp.z;
            yy += temp.y * temp.y;
            yz += temp.y * temp.z;
            zz += temp.z * temp.z;
        }
    
        float detX = yy * zz - yz * yz;
        float detY = xx * zz - xz * xz;
        float detZ = xx * yy - xy * xy;
    
        float detMax = std::max(std::max(detX, detY), detZ);
        if (detMax <= 0)
        {mPlane.x = 0; mPlane.y = 0; mPlane.z = 0; mPlane.D = 0;}
    
        float3 dir{};
        if (detMax == detX)
        {
            float a = static_cast<float>((xz * yz - xy * zz) / detX);
            float b = static_cast<float>((xy * yz - xz * yy) / detX);
            dir = { 1.0, a, b };
        }
        else if (detMax == detY)
        {
            float a = static_cast<float>((yz * xz - xy * zz) / detY);
            float b = static_cast<float>((xy * xz - yz * xx) / detY);
            dir = { a, 1.0, b };
        }
        else
        {
            float a = static_cast<float>((yz * xy - xz * yy) / detZ);
            float b = static_cast<float>((xz * xy - yz * xx) / detZ);
            dir = { a, b, 1.0 };
        }
    
        float dirTemp = sqrt(dir.x * dir.x + dir.y * dir.y + dir.z * dir.z);
        dir.x /= dirTemp;
        dir.y /= dirTemp;
        dir.z /= dirTemp;
    
        mPlane.x = dir.x;
        mPlane.y = dir.y;
        mPlane.z = dir.z;
        mPlane.D = -(mPlane.x * centroid.x + mPlane.y * centroid.y + mPlane.z * centroid.z);
    }
    
    void Ransac3DPlane(std::vector<float3>& inPoints, plane& outPlane)
    {
        float minSamplePercent = 0.4f;  // Select the initial sample percentage
        int minSampleNum = static_cast<int>(float(inPoints.size())* minSamplePercent); 
        float maxSamplePercent = 0.9f;  // Maximum percentage control iteration stop
        int maxSampleNum = static_cast<int>(float(inPoints.size()) * maxSamplePercent); 
    
        float distThreshold = 0.2f;
        int iterations = 0;
        int maxIterations = 30;
        std::vector<float3> maxPlanePoints; // Satisfy the maximum number of interior points of the plane model
    
        while (iterations < maxIterations || maxPlanePoints.size() < maxSampleNum)
        {
            iterations++;
            float3 ptTemp1, ptTemp2, ptTemp3;
            plane planeParame = { 0, 0, 0, 0 };
            std::vector<float3> points;
            std::vector<float3> tempPlanePoints;
            std::random_shuffle(inPoints.begin(), inPoints.end());
            for (int i = 0; i < minSampleNum; i++)
            {
                ptTemp1.x = inPoints[i].x;
                ptTemp1.y = inPoints[i].y;
                ptTemp1.z = inPoints[i].z;
    
                points.push_back(ptTemp1);
            }
    
            PlaneFromPoints(points, planeParame);
            points.clear();
    
            for (int i = 0; i < static_cast<int>(inPoints.size()); i++)
            {
                float distTemp;
                ptTemp2.x = inPoints[i].x;
                ptTemp2.y = inPoints[i].y;
                ptTemp2.z = inPoints[i].z;
                distTemp = DistanceToPlane(ptTemp2, planeParame);
                if (distTemp < distThreshold)
                {
                    tempPlanePoints.push_back(ptTemp2);
                }
                else { continue; }
            }
            
            if (tempPlanePoints.size() > maxPlanePoints.size())
            {
                maxPlanePoints.clear();
                maxPlanePoints.reserve(tempPlanePoints.size());
                for (int i = 0; i < static_cast<int>(tempPlanePoints.size()); i++)
                {
                    ptTemp3.x = tempPlanePoints[i].x;
                    ptTemp3.y = tempPlanePoints[i].y;
                    ptTemp3.z = tempPlanePoints[i].z;
                    maxPlanePoints.push_back(ptTemp3);
                }
            }
            tempPlanePoints.clear();
            
        }
    
        PlaneFromPoints(maxPlanePoints, outPlane);
    }
    
    void test()
    {
        char filename[255];
        sprintf_s(filename, 255, "111.asc");
        std::vector<float3> points;
        plane mPlane;
        ImportPointCloud(*filename, points);
        //PlaneFromPoints(points, mPlane);
        Ransac3DPlane(points, mPlane);
        std::cout << mPlane.x << "  " << mPlane.y << "  " << mPlane.z << "  " << mPlane.D << std::endl;
    
    }
    
    int main()
    {
        test();
        return 0;
    }
    

    3、测试

    应用图
    原图
    应用图
    程序测试结果
    应用图
    Gemogic测试效果
    展开全文
  • matlab RANSAC拟合平面

    2021-06-14 18:21:51
    matlab点云工具箱实现的RANSAC拟合平面

    一、功能概述

    1、实现算法

      在matlab点云工具箱中有RANSAC拟合平面算法的直接实现,无需自己写花里胡哨的实现代码(显得自己多厉害似的)。

    2、主要函数

    model = pcfitplane(ptCloudIn,maxDistance)
    

    将点云拟合为平面,该点云具有最大允许距离,从一个独立点到该平面。函数返回描

    展开全文
  • SciPy Cookbook中的RANSAC样例,简单易懂,直观理解RANSAC拟合直线的过程。1. 选取部分数据点 2. 最小二乘法拟合直线 3. 判定inliners 4. 终止条件
  • 一、RANSAC(Random Sample Consensus) https://baike.baidu.com/item/ransac/10993469?fr=aladdin (省的某些人嫌弃我不讲原理) .../* RANSAC平面分割 */ void testOpen3D::pcPlaneRANSAC(const

    20200918:最近骨折了,很烦。蹦蹦跳跳的,膝盖疼。

    一、RANSAC(Random Sample Consensus)

    https://baike.baidu.com/item/ransac/10993469?fr=aladdin

    (省的某些人嫌弃我不讲原理)

    二、代码

    分享给有需要的人,代码质量勿喷。

    //Open3D
    #include "Open3D/Open3D.h"
    
    //Eigen
    #include "Eigen/Dense"
    
    /* RANSAC平面分割 */
    void testOpen3D::pcPlaneRANSAC(const QString &pcPath)
    {
    	int width = 700, height = 500;
    	auto cloud_ptr = std::make_shared<open3d::geometry::PointCloud>();
    	if (!open3d::io::ReadPointCloud(pcPath.toStdString(), *cloud_ptr)) { return; }
    	open3d::visualization::DrawGeometries({ cloud_ptr }, "Point Cloud 1", width, height);
    
    
    	/***** 距离阈值,平面最小点数,最大迭代次数。返回平面参数和内点 *****/
    	double tDis = 0.05;
    	int minNum = 3;
    	int numIter = 100;
    	std::tuple<Eigen::Vector4d, std::vector<size_t>> vRes = cloud_ptr->SegmentPlane(tDis, minNum, numIter);
    
    	//ABCD
    	Eigen::Vector4d para = std::get<0>(vRes);
    	//内点索引
    	std::vector<size_t> selectedIndex = std::get<1>(vRes);
    
    
    	//内点赋红色
    	std::shared_ptr<open3d::geometry::PointCloud> inPC = cloud_ptr->SelectByIndex(selectedIndex, false);
    	const Eigen::Vector3d colorIn = { 255,0,0 };
    	inPC->PaintUniformColor(colorIn);
    
    	//外点赋黑色
    	std::shared_ptr<open3d::geometry::PointCloud> outPC = cloud_ptr->SelectByIndex(selectedIndex, true);
    	const Eigen::Vector3d colorOut = { 0,0,0 };
    	outPC->PaintUniformColor(colorOut);
    
    
    	//显示 
    	open3d::visualization::DrawGeometries({ inPC,outPC }, "RANSAC平面分割", width, height);
    }

    三、结果

     

    展开全文
  • 利用点云库PCL,使用VS2015完成的C++代码,测试文件(.obj)已经在本站上传资源,...对于不平整表面,利用ransac平面拟合,然后将三维不平整表面近似为一个平面,并将表面上的点投影到该平面,并进行显示 详见本人博客
  • 简单的matlab实现的ransac平面拟合程序
  • 原理:---------------基于ransac算法平面检测: 1、确定迭代次数; 2、在迭代次数内: 2.1 随机选择三个点组成平面(判断三个点是否共线); 2.2 构造坐标矩阵; 2.3 求平面方程; 2.4 求所有点到平面的距离; 2.5 ...

    原理:---------------基于ransac算法平面检测:
    1、确定迭代次数;
    2、在迭代次数内:
    2.1 随机选择三个点组成平面(判断三个点是否共线);
    2.2 构造坐标矩阵;
    2.3 求平面方程;
    2.4 求所有点到平面的距离;
    2.5 统计inlier个数(距离小于阈值);
    3、迭代选择inlier个数最多的平面。

    已知三个点坐标为P1(x1,y1,z1), P2(x2,y2,z2), P3(x3,y3,z3),求过他们的平面方程:
    设方程为A(x - x1) + B(y - y1) + C(z - z1) = 0 (点法式) (也可设为过另外两个点),则有
    A = (y3 - y1)(z3 - z1) - (z2 -z1)(y3 - y1);
    B = (x3 - x1)(z2 - z1) - (x2 - x1)(z3 - z1);
    C = (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1);

    实现:

    void ransac( pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, int max_iter, float threshold)
    {
    	srand(time(0)); //随机种子
    	int size_old = 3;
    	double a, b, c, d; //平面法向量系数
    
    	while (--max_iter) //设置循环的次数
    	{
    		vector<int> index;
    		for (int k = 0; k < 3; ++k)
    		{
    			index.push_back(rand() % cloud->size()); //随机选取三个点 
    		}		
    		auto idx = index.begin();
    		double x1 = cloud->points[*idx].x, y1 = cloud->points[*idx].y, z1 = cloud->points[*idx].z; 
    		++idx;
    		double x2 = cloud->points[*idx].x, y2 = cloud->points[*idx].y, z2 = cloud->points[*idx].z;
    		++idx;
    		double x3 = cloud->points[*idx].x, y3 = cloud->points[*idx].y, z3 = cloud->points[*idx].z;
    
    		a = (y2 - y1)*(z3 - z1) - (z2 - z1)*(y3 - y1);
    		b = (z2 - z1)*(x3 - x1) - (x2 - x1)*(z3 - z1);
    		c = (x2 - x1)*(y3 - y1) - (y2 - y1)*(x3 - x1);
    		d = -(a*x1 + b*y1 + c*z1);
    
    		for (auto iter = cloud->begin(); iter != cloud->end(); ++iter)
    		{ 
    			double dis = fabs(a*iter->x + b*iter->y + c*iter->z + d) / sqrt(a*a + b*b + c*c);//点到平面的距离公式
    			if (dis < threshold)	index.push_back(iter - cloud->begin());
    		}
    		//更新集合
    		if (index.size() > size_old)
    		{
    			size_old = index.size();
    		}
    	}
    	cout << a << " " << b << " " << c << " " << d << endl;	
    }
    
    展开全文
  • 使用RANSAC提取平面

    2018-09-21 21:23:07
    使用PCL中RANSAC探测识别平面,并且可将探测出的多个平面进行单独保存。
  • 在获取到点云数据后,我进行了滤波,然后将我认为没有异常的点拟合了一个平面,然后再去求我想要的某个point(x,y,z)到平面的距离,这就计算出了某个点相对于平面的距离,这也是项目中用来求高度比较通用的算法。...
  • 1. 随机采样一致性 RANSAC,Random Sample Consensus拟合平面和球面 rand() //的取值范围是[0 RAND_MAX] // inliers为结果索引 // created RandomSampleConsensus object and compute the appropriated model // ...
  • 利用 ransac 算法拟合平面

    万次阅读 2016-11-01 10:16:25
    1.前言最近项目中遇到一个问题, 老板给了一组数据然后要求获取其中处于同一个平面上的数据点的信息, 很明显就是使用ransac 算法进行处理。2. ransac算法思想这里我们使用自己的理解来说明下这个算法。 1. 首先...
  • ransac平面拟合

    千次阅读 2017-06-03 20:27:35
    pcl::RandomSampleConsensus是...下面一段代码演示利用上述两个类拟合空间平面方程。 首先生成点云数据,设定空间平面方程为x +y+z=1,其中每隔五个点生成一个点作为噪声点。 pcl::PointCloud<pcl::PointXYZ>::Ptr clou
  • PCL 利用RANSAC算法拟合平面并旋转

    千次阅读 2019-10-22 21:26:23
    说明: 最近的项目用到了PCL里的旋转平面,然后又需要按一定的角度旋转,因此对于给定一个平面 的数据集,需要利用RANSAC算法拟合出平面方程,然后...PCL库中SACSegmentation类中用的是RANSAC的算法来拟合平面的。...
  • RANSAC算法详解(附Python拟合曲线和平面) 下文博主整理的很详细,请参考: https://lixin97.com/2019/04/10/RANSAC/
  • RANSAC 算法拟合平面

    2020-12-18 13:28:22
    RANSAC 算法拟合平面 视觉库为VisionPro 1、输入参数 Distance Threshold:对于拟合算法的每次迭代,测量候选平面与每个3D输入点之间的距离。比这个阈值更远的点被认为是离群值。 默认为1 Assurance:这个值必须大于...
  • 一、RANSAC介绍    随机抽样一致算法(RANdom SAmple Consensus,RANSAC),采用迭代的方式从一组包含离群的被观测数据中估算出数学模型的参数。维基百科中的RANSAC该算法最早由Fischler和Bolles于1981年提出。...
  • //显示拟合出来的平面 pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_in(cloud, 255, 0, 0); viewer->addPointCloud<pcl::PointXYZ>(cloud, color_in, "cloud_in", v1);...
  • [Matlab]基于matlab的ransac平面拟合程序

    千次阅读 2017-05-12 11:20:13
    %求每个数据到拟合平面的距离 total=sum(mask); %计算数据距离平面小于一定阈值的数据的个数 index= mask; if total>T nsample=data(:,index); [a1,a2,a3,a4] =get_nice_plane(nsample); plane = [-a1/...
  • RANSAC算法平面拟合_C++实现

    千次阅读 2020-05-17 09:21:41
    输入一组点云,使用RANSAC算法进行平面拟合,得到圆心和半径 #include <iostream> #include <random> #include <cmath> struct PointCloud3d { double x,y,z; } bool RansacCircle(QList&...
  • 基于RANSAC算法PCL点云拟合平面整理

    万次阅读 多人点赞 2018-11-30 13:51:50
    文章目录前言首先讲一下PCL是什么接下来是RANSAC算法解决思路PCL拟合平面手写RANSAC算法代码流程然而,出现了问题!!!发现问题mt19937 is what? 前言 这个项目,跟我专业不大相关,准确的说,是帮助学姐的做一...
  • matlab中实现RANSAC平面拟合

    千次阅读 2017-07-30 19:50:11
    %%%三维平面拟合 %%%生成随机数据 %内点 mu=[0 0 0]; %均值 S=[2 0 4;0 4 0;4 0 8]; %协方差 data1=mvnrnd(mu,S,300); %产生200个高斯分布数据 %外点 mu=[2 2 2]; S=[8 1 4;1 8 2;4 2 8]; %协方差 data2=...
  • ---------------基于ransac算法直线检测: (1)从样本集N中,随机选n个点作为初始子集(但是所选取的这n个点点必须能够表达待拟合的模型,比如拟合直线的话最少需要2个点,所以n=2(这是正常求解方式),但是基于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,269
精华内容 507
关键字:

ransac拟合平面