C++:RANSAC采样一致性算法拟合一元二次曲线

这篇具有很好参考价值的文章主要介绍了C++:RANSAC采样一致性算法拟合一元二次曲线。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数学补充

这里会用到线性代数里的一些知识,每次都是用起来看,用完了又忘,这里把一些可能用到的贴出来,用于快速理解算法里用到的公式等。
直线一般式

当x1≠x2,y1≠y2时,直线的斜率k=(y2-y1)/(x2-x1)
故直线方程为y-y1=(y2-y1)/(x2-x1)×(x-x1)
即x2y-x1y-x2y1+x1y1=(y2-y1)x-x1(y2-y1)(y2-y1)x-(x2-x1)y-x1(y2-y1)+(x2-x1)y1=0(y2-y1)x+(x1-x2)y+x2y1-x1y2=0 ①
可以发现,当x1=x2或y1=y2时,①式仍然成立。所以直线AX+BY+C=0的一般式方程就是:
A = Y2 - Y1
B = X1 - X2
C = X2*Y1 - X1*Y2

对于一元二次多项式,可以转换为线性方程组求解,我们一般写成矩阵形式 Ax = y。
ransac拟合曲线,C++,激光点云,算法,c++,矩阵

Ax = y非一致方程和一致方程的求解
一致与非一致方程

    一致方程是指Ax = y有至少一个解
    非一致方程指Ax = y没有解

Ax = y求解

    如果A是满秩的方阵,则x = inv(A)*y

    如果A不是方阵,但是是行满秩或者列满秩,那么解为A的伪逆乘以y

    如果A是秩亏的,那么A的解为A的广义逆乘以y

实际上广义逆包括逆、伪逆,广义逆又称为:Moore-Penrose逆矩阵,所以Ax = y的解可以统一为A 的Moore-Penrose逆矩阵乘以y,特别的是,对于一致性方程,该解为最小范数解,对于非一致方程,该解为最小范数最小二乘解

Moore-Penrose逆矩阵
ransac拟合曲线,C++,激光点云,算法,c++,矩阵
RANSAC直线拟合

C++实现

int ransac_curve_fitting(std::vector<float4> &in_cloud, std::vector<double> &best_model, std::vector<float4> &inliers, 
                        int maxiter=200, int mSamples=3, int min_inliers=10, float residual_thres=0.2)
{
    int point_num = in_cloud.size();
    std::default_random_engine rng;
    std::uniform_int_distribution<unsigned> uniform(0, point_num-1);
    rng.seed(10);

    // y = ax^2 + bx + c    <<<--- A_(0,0)=a, A_(1,0)=b, A_(2,0)=c --->>>
    Eigen::MatrixXd X_(3, 3), Y_(3, 1), A_(3, 1), points_x(point_num, 3), points_y(point_num, 1); //  dynamic cols.rows,
    for (int i = 0; i < point_num; ++i)
    {
      points_x(i, 0) = in_cloud[i].x * in_cloud[i].x;
      points_x(i, 1) = in_cloud[i].x;
      points_x(i, 2) = 1;
      points_y(i, 0) = in_cloud[i].y;
    }   

    std::vector<unsigned int> selectIndexs;
    int best_inilers = 0;
    float best_error = 100.0;
    int iter = 0;
    int best_iter = 0;
    float tmp_error = 0.0;
    int num = 0;
    
    while (iter < maxiter)
    {
        selectIndexs.clear();
        inliers.clear();
        // 随机选n个点
        while (1)
        {
            unsigned int index = uniform(rng); 
            selectIndexs.push_back(index);
            if(selectIndexs.size() == mSamples) // sample==2
            {
                break;
            }
        }
        // 模型参数估计
        for (size_t i = 0; i < selectIndexs.size(); ++i)
        {
          // std::cerr << selectIndexs[i] << std::endl;
          X_(i, 0) = in_cloud[selectIndexs[i]].x * in_cloud[selectIndexs[i]].x;
          X_(i, 1) = in_cloud[selectIndexs[i]].x;
          X_(i, 2) = 1;
          Y_(i, 0) = in_cloud[selectIndexs[i]].y;
        }
        try
        {
          X_.inverse();
        }
        catch(const std::exception& e)
        {
          std::cerr << e.what() << '\n';
          std::cerr << "Start the next loop..." << '\n';
          continue;
        }
        // X_为可逆方阵
        A_ = X_.inverse() * Y_;  
        Eigen::MatrixXd y_pred = points_x * A_;
        Eigen::MatrixXd residual = points_y - y_pred;

        for (size_t i = 0; i < point_num; ++i)
        {
          if (abs(residual(i, 0)) < residual_thres)
          {
            inliers.push_back(in_cloud[i]);
          }
          
        }
        
        int inlier_num = inliers.size();
        if (inlier_num > best_inilers)
        {
          best_inilers = inlier_num;
          best_model[0] = A_(0,0);
          best_model[1] = A_(1,0);
          best_model[2] = A_(2,0);
          best_iter = iter;
        }

        if (inlier_num > min_inliers)
        {
          Eigen::MatrixXd better_model(3, 1), inliers_x(inlier_num, 3), 
                          inliers_y(inlier_num, 1), y_pred_better(inlier_num, 1);
          for (size_t i = 0; i < inlier_num; ++i)
          {
            inliers_x(i, 0) = inliers[i].x * inliers[i].x;
            inliers_x(i, 1) = inliers[i].x;
            inliers_x(i, 2) = 1;
            inliers_y(i, 0) = inliers[i].y;
          }
          better_model = (inliers_x.transpose() * inliers_x).inverse() * inliers_x.transpose() * inliers_y;
          y_pred_better = inliers_x * better_model;
          float mean_square_error = 0;
          for (size_t i = 0; i < inlier_num; ++i)
          {
            mean_square_error += pow((y_pred_better(i,0) - inliers_y(i,0)), 2);
          }
          mean_square_error = mean_square_error / inlier_num;
          if (mean_square_error < best_error)
          {
            best_error = mean_square_error;
            best_model[0] = better_model(0,0);
            best_model[1] = better_model(1,0);
            best_model[2] = better_model(2,0);
            best_iter = iter;
          }

        }

        if (tmp_error != best_error)
        {
          tmp_error = best_error;
        }
        else
        {
          num += 1;
          if (num > 10)
          {
            break;
          }
        }
        std::cerr << "number of the error is constant: " << num << std::endl;
        std::cerr << "ransac iterations: " << iter << std::endl;
        iter++;
    }
    std::cerr << "best_iter: " << best_iter << "\n" 
              << "best_model[0]: " << best_model[0] << "\n" 
              << "best_error: " << best_error << "\n" 
              << "inliers.size(): " << inliers.size() << std::endl;
    return 0;

}
std::vector<double> coef_line(3); // a, b, c
std::vector<float4> inliers;
ransac_curve_fitting(result, coef_line, inliers);

多车道线检测效果图

ransac拟合曲线,C++,激光点云,算法,c++,矩阵文章来源地址https://www.toymoban.com/news/detail-578893.html

到了这里,关于C++:RANSAC采样一致性算法拟合一元二次曲线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【负载均衡——一致性哈希算法】

    一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时,发生过多的数据迁移的问题。 一致哈希算法也用了取模运算,但与哈希算法不同的是,哈希算法是对节点的数量进行取模运算,而一致 哈希算法 是对 2^32 进行取模运算,是一个固定的值。 一致性哈希要进行两步

    2024年04月10日
    浏览(41)
  • 区块链:哈希算法与一致性哈希算法

    本篇主要介绍区块链中常用到的哈希算法。 1 哈希算法 1.1 定义及特性   哈希算法是指通过哈希函数(Hash Function)对任意长度的输入数据(比如文件、消息、数字等)进行转换,生成一个固定长度的哈希值(Hash Value)的过程。   在区块链中,哈希算法常用于区块验证及安全性保

    2024年02月17日
    浏览(51)
  • 分布式一致性算法Paxos

            Paxos算法是Lamport宗师提出的一种基于消息传递的分布式一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。Google Chubby的作者Mike Burrows曾经狂妄的说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。         Paxos算法是

    2023年04月16日
    浏览(48)
  • 通过zookeeper浅谈一致性算法

    CAP 定理指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。 通俗来说: 一致性(C):当系统数据发生更新操作后,各个主机中的数据仍然处于一致的状态。 可用性(A):对于用户的每一个请求,系统总

    2024年02月07日
    浏览(42)
  • Python小知识 - 一致性哈希算法

    一致性哈希算法 一致性哈希算法(Consistent Hashing Algorithm)是用于解决分布式系统中节点增减比较频繁的问题。它的思想是,将数据映射到0~2^64-1的哈希空间中,并通过哈希函数对数据进行映射,计算出数据所在的节点。当节点增加或减少时,只需要重新计算数据所在的节点即

    2024年02月09日
    浏览(40)
  • 一致性哈希算法优势在哪?如何实现?

    1.1 简介Hash 哈希算法即散列算法,是一种从任意文件中创造小的数字「指纹」的方法。与指纹一样,散列算法就是一种以较短的信息来保证文件唯一性的标志,这种标志与文件的每一个字节都相关,而且难以找到逆向规律。因此,当原有文件发生改变时,其标志值也会发生改

    2024年02月03日
    浏览(42)
  • 分布式一致性算法——Paxos 和 Raft 算法

    本文隶属于专栏《100个问题搞定大数据理论体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见100个问题搞定大数据理论体系 Paxos和Raft算法都是 分布式一致性算法 ,它们的目的都是 在一个分布式系统

    2024年01月20日
    浏览(53)
  • Redis扩容与一致性Hash算法解析

    作者:zhaokk 在分布式系统中,随着数据量的增加和负载的变化,对于存储系统的扩容变得尤为重要。Redis作为一种高性能的内存数据库,其在扩容方面采用了一致性Hash算法,以实现无缝的数据分布和负载均衡。本篇博客将详细探讨Redis的扩容机制,同时深入解析一致性Hash算法

    2024年02月12日
    浏览(40)
  • Redis扩容机制与一致性哈希算法解析

    在分布式系统设计中,Redis是一个备受欢迎的内存数据库,而一致性哈希算法则是分布式系统中常用的数据分片和负载均衡技术。本文将深入探讨Redis的扩容机制以及一致性哈希算法的原理,同时提供示例代码以帮助读者更好地理解这两个重要概念。 Redis是一种高性能的内存数

    2024年02月11日
    浏览(38)
  • 分布式系统共识机制:一致性算法设计思想

    这次以一个宏观的角度去总结 自己学习过的一致性算法。一致性算法的目标就是让分布式系统里的大部分节点 保持数据一致。 区块链中的共识算法,pow、pos这类就属于这个范围,但他们仅仅是在区块链领域内应用的,下面介绍一致性算法是在分布式系统中 应用广泛的,当然

    2023年04月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包