首页 > 编程语言 >Ransac算法优化的PnP算法-随机抽样一致性算法

Ransac算法优化的PnP算法-随机抽样一致性算法

时间:2024-11-28 22:04:17浏览次数:10  
标签:Ransac ransac int PnP init 算法 pts cv

       在基于DLT直接线性变换求解的PnP算法中,我们通过建立一个超定方程来获得一个最小二乘解,在这个超正定方程中,我们考虑了所有的特征匹配点,这显然可能会带来误差,基于这样的思路我们引入Ransac(Random sample consensus,随机抽样一致性)算法来进行优化求解。

         Ransac算法的核心在于对现有数据进行多次随机抽样,通过划定内点和外点来衡量算法所建立模型的好坏,最终留下内点最多的模型。具体到PnP算法中,就是对特征匹配点进行多次的抽样,利用抽样到的若干特征匹配点计算出相机位姿(R和T),利用计算出的相机位姿对每个点计算重投影误差,对误差小于某个阈值的点,我们认为其为当前抽样计算结果的内点,误差小于某个阈值的点,我们认为为外点。显然内点的个数可以体现当前抽样计算结果的好坏。通过多次迭代抽样,获得内点最多的计算结果。下图为程序流程图:(这里的Ransac取消了原来按照阈值计算分数的方法,转为直接比较error大小进行迭代,便于调节参数)

下面为基于C++语言对基于Ransac算法优化PnP算法的一段示例程序:

    vector<cv::Point2f> undis_pts_2;
    cv::undistortPoints(pts_2, undis_pts_2, K, D);
    // Step 1: Work out the initial pose estimates using the linear solution.
    int points_num = pts_3.size();
    MatrixXd A(2 * 5, 9);
    VectorXd sub_A1(9);
    VectorXd sub_A2(9);
    int ransac_num;
    int ransac_times = 100;
    int ransac_score_last = 0;
    int ransac_score = 0;
    cv::Mat R_ransac_out;
    cv::Mat T_ransac_out;
    MatrixXd T_out(3, 1);
    Matrix3d R_out;
    double error_last = 0.0;
    vector<cv::Point2f> reproj_pts_2_ransac;
    for (int i = 0; i < ransac_times; i++){
      //cout << "ransac iteration: " << i << endl;
      for (int j = 0; j < 5; j++){
      ransac_num = rand() % points_num;
      cv::Point3f p_3 = pts_3[ransac_num];
      cv::Point2f p_2 = undis_pts_2[ransac_num];
      double x = p_3.x;
      double y = p_3.y;
      //double z = p_3.z;
      double u = p_2.x;
      double v = p_2.y;
      sub_A1 << x, y, 1, 0, 0, 0, -x * u, -y * u, -u;
      sub_A2 << 0, 0, 0, x, y, 1, -x * v, -y * v, -v;

      A.block<1, 9>(2 * j, 0) = sub_A1.transpose();
      A.block<1, 9>(2 * j + 1, 0) = sub_A2.transpose();
      }
      JacobiSVD<MatrixXd> svd(A, ComputeThinU | ComputeThinV);
      VectorXd H_vector(9);
      H_vector = svd.matrixV().col(8);
      Eigen::Matrix3d H;
      H.row(0) << H_vector(0), H_vector(1), H_vector(2);
      H.row(1) << H_vector(3), H_vector(4), H_vector(5);
      H.row(2) << H_vector(6), H_vector(7), H_vector(8);

      Matrix3d K_eigen;
      cv2eigen(K, K_eigen);
      //H = K_eigen.inverse() * H;
      Vector3d h3 = H.col(2);
      if (h3(2) < 0)
      {
          H = -H;
      }
      Vector3d h1 = H.col(0);
      Vector3d h2 = H.col(1);
      h3 = H.col(2);
      Matrix3d H_new;
      H_new.col(0) = h1;
      H_new.col(1) = h2;
      H_new.col(2) = h1.cross(h2);
      JacobiSVD<MatrixXd> svd_H(H_new, ComputeThinU | ComputeThinV);
      Matrix3d R_H;
      cv::Mat R_init;
      R_H = svd_H.matrixU() * (svd_H.matrixV().transpose());
      eigen2cv(R_H, R_init);
      MatrixXd T_r(3, 1);
      cv::Mat T_init;
      T_r = h3 / h1.norm();
      eigen2cv(T_r, T_init);
      cv::projectPoints(pts_3, R_init, T_init, K, D, reproj_pts_2_ransac);
      // Calculate the reprojection error
      double error = 0.0;
      for (int m = 0; m < points_num; m++)
      {
        cv::Point2f diff = pts_2[m] - reproj_pts_2_ransac[m];
        error += diff.x * diff.x + diff.y * diff.y;
        //error /= 20000;
        //cout << "error: " << error << endl;
        if (error < 10)
        {
          ransac_score++;
        }
      }
      //cout << "ransac score: " << ransac_score << endl;
      //cout << "ransac score: " << ransac_score_last << endl;
      if (error < error_last || error_last == 0.0)
      {
        R_ransac_out = R_init;
        T_ransac_out = T_init;
        ransac_score_last = ransac_score;
        error_last = error;
        T_out(0) = T_r(0);
        T_out(1) = T_r(1);
        T_out(2) = T_r(2);
        R_out = R_H;
      }
      ransac_score = 0;
    }
    
    cv::Mat R_init = R_ransac_out;
    cv::Mat T_init = T_ransac_out;

标签:Ransac,ransac,int,PnP,init,算法,pts,cv
From: https://blog.csdn.net/qq_73991479/article/details/144121434

相关文章

  • 算法训练day2
    209.长度最小的子数组https://leetcode.cn/problems/minimum-size-subarray-sum/:给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其总和大于等于target的长度最小的子数组[nums_l,nums_{l+1},...,nums_{r-1},nums_r],并返回其长度。如果不存在符合条件的子......
  • 代码随想录算法训练营day60| 城市间的货物运输之1、2、3
    学习资料:https://www.programmercarl.com/kamacoder/0094.城市间货物运输I-SPFA.htmlSPFA算法(Bellman_ford队列优化算法)学习记录94.城市间的货物运输(两种方法)点击查看代码#法二importcollectionsdefmain():n,m=map(int,input().split())edges=[[]for......
  • 【机器学习算法】Adaboost原理及实现
    Adaboost一、基本内容[!note]实现思路:在每一轮训练中,记录每一次由\(f(x)=\sum_{m=1}^{i-1}\alpha_mG_m(x)\)【错误\正确】分类的样本,在加入新的弱学习器中【提高\降低】分类【错误\正确】样本的权值(即改变样本的比例,类似过采样与降采样)加法模型:多个弱分类器\(G_m(x)\)与......
  • 14Java Lambda、方法引用、算法、正则表达式
    一、Arrays类接下来我们学习的类叫做Arrays,其实Arrays并不是重点,但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。所以我们这里先学习Arrays,再通过Arrays来学习Lamdba这样学习会更丝滑一些^_^.1.1Arrays基本使用我们先认识一下Arrays是干什么用的,A......
  • Python机器学习笔记(二、监督学习算法基础)
    一、分类与回归监督机器学习问题主要有两种,分别叫作分类(classification)与回归(regression)。区分分类任务和回归任务有一个简单方法,就是问一个问题:输出是否具有某种连续性。如果在可能的结果之间具有连续性,那么它就是一个回归问题;不存在连续性,则一般是分类问题。二、泛化、......
  • golang实现比特币内核:区块链交易“transaction“二进制数据结构解析和代码实现1
    对于比特币,最重要的组成部分是交易。如果你需要通过比特币与他人交易,你可能需要像支付购买商品或服务一样,将一些比特币发送给他人。交易有四个关键字段,它们是版本、输入、输出和锁定时间。交易的二进制内容可能因不同的版本而有所不同,我们需要解析版本号以决定如何解码交易......
  • 算法日记 35 day 动态规划
    今天都是些比较简单的题,看看题目吧。题目:最长递增子序列300.最长递增子序列-力扣(LeetCode)给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,......
  • TEA家族算法
    TEA系列算法总结前言:之前都是面向CTF-reverse学的TEA算法,属于是只知道找算法特征然后无脑一把梭,现在来好好学习总结一下TEA引用百度百科的介绍:TEA算法由剑桥大学计算机实验室的DavidWheeler和RogerNeedham于1994年发明。它是一种分组密码算法,其明文密文块为64位(8字节),密钥长......
  • 算法时间复杂度和空间复杂度计算方法(O(1)、O(n)、O(logn)、O(n^2)、O(n^3 )、O(n!))分
    文章目录时间复杂度与空间复杂度计算方法一、时间复杂度概述1.1时间复杂度的定义1.2常见的时间复杂度-**常数复杂度O(......
  • 基于改进粒子群算法的混合储能系统容量优化(Matlab代码实现)
    ......