IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> trimmed ICP及其在PCL代码解析与使用 -> 正文阅读

[人工智能]trimmed ICP及其在PCL代码解析与使用

1 基本原理

定义data set(source set,待配准数据):
P = { p i } 1 N p \mathcal{P}=\left\{\mathbf{p}_{i}\right\}_{1}^{N_{p}} P={pi?}1Np??
点云数量为 N p N_p Np?
定义 model set (target set,基准数据):
M = { m i } 1 N m \mathcal{M}=\left\{\mathbf{m}_{i}\right\}_{1}^{N_{m}} M={mi?}1Nm??
点云数量为 N m N_m Nm?。一般情况下,两个点云并不存在100%重叠度,即 N p ≠ N m N_{p} \neq N_{m} Np??=Nm?。假设重叠度为 ξ \xi ξ,则重叠点云数量记为 N p o = ξ N p N_{p o}=\xi N_{p} Npo?=ξNp?
假设旋转矩阵 R R R平移向量 t t t,对待配准点云进行变换:
p i ( R , t ) = R p i + t \mathbf{p}_{i}(\mathbf{R}, \mathbf{t})=\mathbf{R} \mathbf{p}_{i}+\mathbf{t} pi?(R,t)=Rpi?+t
则变换后的待配准点云为:
P ( R , t ) = { p i ( R , t ) } 1 N p \quad \mathcal{P}(\mathbf{R}, \mathbf{t})=\left\{\mathbf{p}_{i}(\mathbf{R}, \mathbf{t})\right\}_{1}^{N_{p}} P(R,t)={pi?(R,t)}1Np??
根据距离定义待配准点云对应在基准点云的最近邻点集合为:(注意这里为1范数,不用平方)
m c l ( i , R , t ) = arg ? min ? m ∈ M ∥ m ? p i ( R , t ) ∥ \mathbf{m}_{c l}(i, \mathbf{R}, \mathbf{t})=\arg \min _{\mathbf{m} \in \mathcal{M}}\left\|\mathbf{m}-\mathbf{p}_{i}(\mathbf{R}, \mathbf{t})\right\| mcl?(i,R,t)=argmMmin?m?pi?(R,t)
定义individual distances:在一个最近邻匹配点对中,变换后的待配准点与基准点之间的欧式距离,则individual distances:(注意这里为1范数,不用平方)
d i ( R , t ) = ∥ m c l ( i , R , t ) ? p i ( R , t ) ∥ d_{i}(\mathbf{R}, \mathbf{t})=\left\|\mathbf{m}_{c l}(i, \mathbf{R}, \mathbf{t})-\mathbf{p}_{i}(\mathbf{R}, \mathbf{t})\right\| di?(R,t)=mcl?(i,R,t)?pi?(R,t)
这个individual distance其实就是残差,也就是匹配对的距离。
trimmed ICP主要的贡献就在于利用这个individual distance进行重叠度不是100%的点云配准(即待配准点云和基准点云之间是部分重合)。下面讲一下距离算法,首先给定初值,并给 S T S ′ S_{T S}^{\prime} STS?一个很大的值,然后进行如下步骤:
(1)对于待配准点云 P \mathcal{P} P中的每一个点而言,寻找其在 M \mathcal{M} M的最近邻点(对应点),计算 squared individual distance d i 2 d_i^2 di2?;
(2)将 d i 2 d_i^2 di2?按照升序(ascending order,从小到大排序),选择前面 N p o N_{p o} Npo?(重叠数量)个 d i 2 d_i^2 di2?,计算它们的和 S T S S_{TS} STS?;
(3)如果满足终止条件,则退出程序,否则,令 S T S ′ = S T S S_{T S}^{\prime}=S_{T S} STS?=STS?,继续下一步;
(4)利用(2)中筛选出来的前 N p o N_{p o} Npo?个点云匹配对,(利用最小二乘)求解 ( R , t ) (R,t) (R,t);
(5)利用 ( R , t ) (R,t) (R,t)变换待配准点云 P \mathcal{P} P,返回第一步(1)。
本文中给出的终止条件一共有三个:
(1)达到最大迭代次数,终止迭代
(2)定义 trimmed MSE:
e = S T S N p o e=\frac{S_{T S}}{N_{p o}} e=Npo?STS??
如果 e e e足够小,终止迭代
(3)如果trimmed MSE之间的改变量 ∣ e ′ ? e ∣ \left|e^{\prime}-e\right| e?e足够小,终止迭代。
上述三种终止方式任选一即可。
总结:trimmedICP对部分重叠点云配准提出一种解决方案,利用了 Least Trimmed Squares(修剪最小二乘)求解ICP问题。文中使用的是点到点的距离度量。其思路很好理解:即在求解旋转和平移量时,删除残差比较大的匹配对(残差越大对求解结果影响越大),文中将残差定义为individual distance。

2trimmed ICP在pcl中的实现

trimmed ICP在PCL的recognition模块中,具体实现在pcl\recognition\ransac_based\的trimmed_icp.h文件中。具体实现代码为align函数:

        inline void
        align (const PointCloud& source_points, int num_source_points_to_use, Matrix4& guess_and_result) const
        {
          int num_trimmed_source_points = num_source_points_to_use, num_source_points = static_cast<int> (source_points.size ());

          if ( num_trimmed_source_points >= num_source_points )
          {
            printf ("WARNING in 'TrimmedICP::%s()': the user-defined number of source points of interest is greater or equal to "
                    "the total number of source points. Trimmed ICP will work correctly but won't be very efficient. Either set "
                    "the number of source points to use to a lower value or use standard ICP.\n", __func__);
            num_trimmed_source_points = num_source_points;
          }

          // These are vectors containing source to target correspondences
          pcl::Correspondences full_src_to_tgt (num_source_points), trimmed_src_to_tgt (num_trimmed_source_points);

          // Some variables for the closest point search
          pcl::PointXYZ transformed_source_point;
          std::vector<int> target_index (1);
          std::vector<float> sqr_dist_to_target (1);
          float old_energy, energy = std::numeric_limits<float>::max ();

//          printf ("\nalign\n");

          do
          {
            // Update the correspondences
            for ( int i = 0 ; i < num_source_points ; ++i )
            {
              // Transform the i-th source point based on the current transform matrix
              aux::transform (guess_and_result, source_points.points[i], transformed_source_point);

              // Perform the closest point search
              kdtree_.nearestKSearch (transformed_source_point, 1, target_index, sqr_dist_to_target);

              // Update the i-th correspondence
              full_src_to_tgt[i].index_query = i;
              full_src_to_tgt[i].index_match = target_index[0];
              full_src_to_tgt[i].distance = sqr_dist_to_target[0];
            }

            // Sort in ascending order according to the squared distance
            std::sort (full_src_to_tgt.begin (), full_src_to_tgt.end (), TrimmedICP::compareCorrespondences);

            old_energy = energy;
            energy = 0.0f;

            // Now, setup the trimmed correspondences used for the transform estimation
            for ( int i = 0 ; i < num_trimmed_source_points ; ++i )
            {
              trimmed_src_to_tgt[i].index_query = full_src_to_tgt[i].index_query;
              trimmed_src_to_tgt[i].index_match = full_src_to_tgt[i].index_match;
              energy += full_src_to_tgt[i].distance;
            }

            this->estimateRigidTransformation (source_points, *target_points_, trimmed_src_to_tgt, guess_and_result);

//            printf ("energy = %f, energy diff. = %f, ratio = %f\n", energy, old_energy - energy, energy/old_energy);
          }
          while ( energy/old_energy < new_to_old_energy_ratio_ ); // iterate if enough progress

//          printf ("\n");
        }

讲解一下具体实现:
函数参数:

source_points:待配准点云 
num_source_points_to_use:重叠点云数量
guess_and_result:变换矩阵初值

变量old_energy, energy分别对应算法中的 S T S ′ , S T S S_{T S}^{\prime},S_{T S} STS?STS?(individual distance 平方之和)
dowhile循环为trimmedICP实现过程:
首先,利用kdtree寻找匹配对,放入full_src_to_tgt,
然后,利用距离平方对匹配点对进行升序排序(sort函数),
然后,筛选前num_source_points_to_use进行真正的匹配对,放入trimmed_src_to_tgt
接着,利用最小二乘求解 R , t R,t R,t(estimateRigidTransformation函数(应该是SVD求解,没细看))
直到energy/old_energy大于new_to_old_energy_ratio_(实例化类时设置的参数,默认为0.99)停止迭代,这里迭代终止没有用到原文提到的三种方法,而是PCL自己定义的比值。理想情况下,当二者相等即比例接近1时可以认为终止,不过这种迭代终止条件略显粗糙,可能导致在没有完全收敛时迭代已经终止。

3PCL中trimmedICP的使用

请参考链接1
可能提示找不到aux,需要在trimmed_icp.h加入include<pcl/recognition/ransac_based/auxiliary.h>

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:39:40  更:2022-05-09 12:40:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:22:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码