研究生课程系列文章参见索引《在信科的那些课

基本原理

假定已给两个数据集P、Q, ,给出两个点集的空间变换f使他们能进行空间匹配。这里的问题是,f为一未知函数,而且两点集中的点数不一定相同。解决这个问题使用的最多的方法是迭代最近点法(Iterative Closest Points Algorithm)。

基本思想是:根据某种几何特性对数据进行匹配,并设这些匹配点为假想的对应点,然后根据这种对应关系求解运动参数。再利用这些运动参数对数据进行变换。并利用同一几何特征,确定新的对应关系,重复上述过程。

迭代最近点法目标函数

三维空间中两个3D点, ,他们的欧式距离表示为:
三维点云匹配问题的目的是找到P和Q变化的矩阵R和T,对于 ,利用最小二乘法求解最优解使:
最小时的R和T。
 

数据预处理

实验中采集了五个面的点如下所示:

由于第一组(第一排第1个)和第三组(第一排第三个)采集均为模型正面点云,所以选用一和三做后续的实验。

首先利用Geomagic Studio中删除点的工具,去除原始数据中的一些隔离的噪点,效果如下:

 

平行移动和旋转的分离

先对平移向量T进行初始的估算,具体方法是分别得到点集P和Q的中心:

 

分别将点集P和Q平移至中心点处:

则上述最优化目标函数可以转化为:

最优化问题分解为:

  1. 求使E最小的 
  2. 求使 

平移中心点的 具体代码为:

  1. //计算点云P的中心点mean
  2. void CalculateMeanPoint3D(vector<Point3D> &P, Point3D &mean)
  3. {
  4. vector<Point3D>::iterator it;
  5. mean.x = 0;
  6. mean.y = 0;
  7. mean.z = 0;
  8. for(it=P.begin(); it!=P.end(); it++){
  9. mean.x += it->x;
  10. mean.y += it->y;
  11. mean.z += it->z;
  12. }
  13. mean.x = mean.x/P.size();
  14. mean.y = mean.y/P.size();
  15. mean.z = mean.z/P.size();
  16. }

初始平移效果如下:

 

利用控制点求初始旋转矩阵

在确定对应关系时,所使用的几何特征是空间中位置最近的点。这里,我们甚至不需要两个点集中的所有点。可以指用从某一点集中选取一部分点,一般称这些点为控制点(Control Points)。这时,配准问题转化为:

这里,pi,qi为最近匹配点。
在Geomagic Studio中利用三个点就可以进行两个模型的“手动注册”(感觉这里翻译的不好,Registration,应该为“手动匹配”)。

 
我们将手动选择的三个点导出,作为实验初始的控制点:

对于第i对点,计算点对的矩阵 Ai:

 

 ,的转置矩阵。

(*这里在査老师的课上给了一个错误的矩阵变换公式)

对于每一对矩阵Ai,计算矩阵B:

  1. double B[16];
  2. for(int i=0;i<16;i++)
  3. B[i]=0;
  4. for(itp=P.begin(),itq=Q.begin();itp!=P.end();itp++,itq++ ){
  5. double divpq[3]={itp->x,itp->y,itp->z};
  6. double addpq[3]={itp->x,itp->y,itp->z};
  7. double q[3]={itq->x,itq->y,itq->z};
  8. MatrixDiv(divpq,q,3,1);
  9. MatrixAdd(addpq,q,3,1);
  10. double A[16];
  11. for(int i=0;i<16;i++)
  12. A[i]=0;
  13. for(int i=0;i<3;i++){
  14. A[i+1]=divpq[i];
  15. A[i*4+4]=divpq[i];
  16. A[i+13]=addpq[i];
  17. }
  18. double AT[16],AMul[16];
  19. MatrixTran(A,AT,4,4);
  20. MatrixMul(A,AT,AMul,4,4,4,4);
  21. MatrixAdd(B,AMul,4,4);
  22. }

原最优化问题可以转为求B的最小特征值和特征向量,具体代码:

  1. //使用奇异值分解计算B的特征值和特征向量
  2. double eigen, qr[4];
  3. MatrixEigen(B, &eigen, qr, 4);
  1. //计算n阶正定阵m的特征值分解:eigen为特征值,q为特征向量
  2. void MatrixEigen(double *m, double *eigen, double *q, int n)
  3. {
  4. double *vec, *eig;
  5. vec = new double[n*n];
  6. eig = new double[n];
  7. CvMat _m = cvMat(n, n, CV_64F, m);
  8. CvMat _vec = cvMat(n, n, CV_64F, vec);
  9. CvMat _eig = cvMat(n, 1, CV_64F, eig);
  10. //使用OpenCV开源库中的矩阵操作求解矩阵特征值和特征向量
  11. cvEigenVV(&_m, &_vec, &_eig);
  12. *eigen = eig[0];
  13. for(int i=0; i<n; i++)
  14. q[i] = vec[i];
  15. delete[] vec;
  16. delete[] eig;
  17. }
  18. //计算旋转矩阵
  19. void CalculateRotation(double *q, double *R)
  20. {
  21. R[0] = q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3];
  22. R[1] = 2.0 * (q[1]*q[2] - q[0]*q[3]);
  23. R[2] = 2.0 * (q[1]*q[3] + q[0]*q[2]);
  24. R[3] = 2.0 * (q[1]*q[2] + q[0]*q[3]);
  25. R[4] = q[0]*q[0] - q[1]*q[1] + q[2]*q[2] - q[3]*q[3];
  26. R[5] = 2.0 * (q[2]*q[3] - q[0]*q[1]);
  27. R[6] = 2.0 * (q[1]*q[3] - q[0]*q[2]);
  28. R[7] = 2.0 * (q[2]*q[3] + q[0]*q[1]);
  29. R[8] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
  30. }

平移矩阵计算

2.4中可以得到选择矩阵的4元数表示,由于在"平行移动和旋转的分离"中,我们将最优问题分解为:

  1. 求使E最小的 
  2. 求使 

因此还需要通过中心点计算平移矩阵。

  1. //通过特征向量计算旋转矩阵R1和平移矩阵T1
  2. CalculateRotation(qr, R1);
  3. double mean_Q[3]={_mean_Q.x,_mean_Q.y,_mean_Q.z};
  4. double mean_P[3]={_mean_P.x,_mean_P.y,_mean_P.z};
  5. double meanT[3]={0,0,0};
  6. int nt=0;
  7. for(itp=P.begin(),itq=Q.begin();itp!=P.end();itp++,itq++ ){
  8. double tmpP[3]={itp->x,itp->y,itp->z};
  9. double tmpQ[3]={itq->x,itq->y,itq->z};
  10. double tmpMul[3];
  11. MatrixMul(R1, mean_P, tmpMul, 3, 3, 3, 1);
  12. MatrixDiv(tmpQ,tmpMul,3,1);
  13. MatrixAdd(meanT,tmpQ,3,1);
  14. nt++;
  15. }
  16. for(int i=0; i<3; i++)
  17. T1[i] = meanT[i]/(double)(nt);

一次旋转计算得到的矩阵如下:


效果在Geomagic Studio中显示如图:
 

迭代最近点

在初始匹配之后,所点集P`中所有点做平移变化,在比较点集合P`和Q`的匹配度,(或迭代次数)作为算法终止的条件。
具体为对点集P中每个点,找Q中离他最近的点作为对应点。在某一步利用前一步得到的,求使下述函数最小的

 

这里, 

  1. //计算误差和d
  2. d = 0.0;
  3. if(round==1){
  4. FindClosestPointSet(data,P,Q);
  5. }
  6. int pcount=0;
  7. for(itp = P.begin(),itq=Q.begin();itp!=P.end(); itp++, itq++){
  8. double sum = (itp->x - itq->x)*(itp->x - itq->x) + (itp->y - itq->y)*(itp->y - itq->y)
  9. + (itp->z - itq->z)*(itp->z - itq->z);
  10. d += sum;
  11. pcount++;
  12. }
  13. d=d/(double)(pcount);

循环结束后能得到较好的匹配效果:

 
封装后的效果图:
 
from: http://blog.csdn.net/xiaowei_cqu/article/details/8470376

迭代最近点算法 Iterative Closest Points的更多相关文章

  1. ICP算法(Iterative Closest Point迭代最近点算法)

    标签: 图像匹配ICP算法机器视觉 2015-12-01 21:09 2217人阅读 评论(0) 收藏 举报 分类: Computer Vision(27) 版权声明:本文为博主原创文章,未经博主允许 ...

  2. 【转】ICP算法(Iterative Closest Point迭代最近点算法)

    原文网址:https://www.cnblogs.com/sddai/p/6129437.html.转载主要方便随时可以查看,如有版权要求请及时联系. 最近在做点云匹配,需要用c++实现ICP算法,下 ...

  3. ICP算法(迭代最近点)

    参考博客:http://www.cnblogs.com/21207-iHome/p/6034462.html 最近在做点云匹配,需要用c++实现ICP算法,下面是简单理解,期待高手指正. ICP算法能 ...

  4. ICP(迭代最近点)算法

    图像配准是图像处理研究领域中的一个典型问题和技术难点,其目的在于比较或融合针对同一对象在不同条件下获取的图像,例如图像会来自不同的采集设备,取自不同的时间,不同的拍摄视角等等,有时也需要用到针对不同对 ...

  5. K closest points

    Find the K closest points to a target point in a 2D plane. class Point { public int x; public int y; ...

  6. [Swift]LeetCode973. 最接近原点的 K 个点 | K Closest Points to Origin

    We have a list of points on the plane.  Find the K closest points to the origin (0, 0). (Here, the d ...

  7. [Solution] 973. K Closest Points to Origin

    Difficulty: Easy Problem We have a list of points on the plane. Find the K closest points to the ori ...

  8. LeetCode 973 K Closest Points to Origin 解题报告

    题目要求 We have a list of points on the plane.  Find the K closest points to the origin (0, 0). (Here, ...

  9. Microsoft - Find the K closest points to the origin in a 2D plane

    Find the K closest points to the origin in a 2D plane, given an array containing N points. 用 max hea ...

随机推荐

  1. ASP.NET WebAPI 04 Model绑定

    在前面的几篇文章中我们都是采用在URI中元数据类型进行传参,实际上ASP.NET Web API也提供了对URI进行复杂参数的绑定方式--Model绑定.这里的Model可以简单的理解为目标Ancti ...

  2. htm5本地存储方案——websql的封装

    一.websql 简介   在HTML5中,大大丰富了客户端本地可以存储的内容,添加了很多功能来将原本必须保存在服务器上的数据转为保存在客户端本地,从而大大提高了Web应用程序的性能,减轻了服务器端的 ...

  3. Gitlab Issue Tracker and Wiki(一)

    本节内容: 创建第一个问题 创建第一个合并请求 接受合并请求 工作里程碑 在提交中引用问题 创建维基百科页 使用Gollum管理维基百科 一. 创建问题 1. 登陆Gitlab服务器 2. 切换到想要 ...

  4. hdoj2602 Bone Collector(DP,01背包)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2602 题意 有n块骨头,每块骨头体积为volume,价值为value,还有一个容量为v的背包,现在将骨 ...

  5. HandlerExceptionResolver统一异常处理 返回JSON 和 ModelAndView

    统一异常处理类的两种方式一种是前后分离,一种是一整套集合返回指定到指定的错误页面显示错误信息 1.由于前后分离,是统一返回JSON的格式 自定义Exception public class Bussi ...

  6. Bootstrap进阶二:基本组件

    基本组件是Bootstrap的精华之一,其中都是开发者平时需要用到的交互组件.例如:网站导航.标签页.工具条.面包屑.分页栏.提示标签.产品展示.提示信息块和进度条等.这些组件都配有jQuery插件, ...

  7. Python爬虫个人记录(三)爬取妹子图

    这此教程可能会比较简洁,具体细节可参考我的第一篇教程: Python爬虫个人记录(一)豆瓣250 Python爬虫个人记录(二)fishc爬虫 一.目的分析 获取煎蛋妹子图并下载 http://jan ...

  8. QT STUDY

  9. leetcode 奇偶链表 python

    要求空间复杂度O(1) 那就只能用指针不断改链表的指针, 不能建立新的内存 时间复杂度O(1) 一遍遍历 不能嵌套循环 我的思想是: 1 如果链表元素数量小于等于2个,那就无法操作 2 能操作的情况下 ...

  10. tomcat启动startup.bat一闪而过的问题处理方式

    tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与JAVA_HOME的信息,CATALINA_HOME即tomcat的主目录,JAVA_HOME即Java安装的主目录, ...