泛化的ICP算法,通过协方差矩阵起到类似于权重的作用,消除某些不好的对应点在求解过程中的作用。不过可以囊括Point to Point,Point to Plane的ICP算法,真正的是泛化的ICP。牛!

CC中的GICP插件

void qLxPluginPCL::doSpraseRegistration()
{
assert(m_app);
if (!m_app)
return; const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
size_t selNum = selectedEntities.size();
if (selNum!=2)
{
m_app->dispToConsole("Please select two cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
} ccHObject* ent = selectedEntities[0];
assert(ent);
if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
{
m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
}
ccHObject* ent2 = selectedEntities[1];
assert(ent2);
if (!ent2 || !ent2->isA(CC_TYPES::POINT_CLOUD))
{
m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
return;
} ccPointCloud* m_target_cloud = static_cast<ccPointCloud*>(ent);
ccPointCloud* m_Source_cloud = static_cast<ccPointCloud*>(ent2); //input cloud
unsigned count = m_target_cloud->size();
bool hasNorms = m_target_cloud->hasNormals();
CCVector3 bbMin, bbMax;
m_target_cloud->getBoundingBox(bbMin,bbMax);
const CCVector3d& globalShift = m_target_cloud->getGlobalShift();
double globalScale = m_target_cloud->getGlobalScale(); cc3DNdtdlg dlg;
if (!dlg.exec())
return; double maxCorrDis =1;
maxCorrDis= dlg.getVoxelGridsize();
pcl::PointCloud<PointXYZ>::Ptr pcl_t_cloud (new pcl::PointCloud<PointXYZ>);
pcl::PointCloud<PointXYZ>::Ptr pcl_s_cloud (new pcl::PointCloud<PointXYZ>);
try
{
//
unsigned pointCount = m_target_cloud->size();
pcl_t_cloud->resize(pointCount); for (unsigned i = 0; i < pointCount; ++i)
{
const CCVector3* P = m_target_cloud->getPoint(i);
pcl_t_cloud->at(i).x = static_cast<float>(P->x);
pcl_t_cloud->at(i).y = static_cast<float>(P->y);
pcl_t_cloud->at(i).z = static_cast<float>(P->z);
}
//
pointCount = m_Source_cloud->size();
pcl_s_cloud->resize(pointCount); for (unsigned i = 0; i < pointCount; ++i)
{
const CCVector3* P = m_Source_cloud->getPoint(i);
pcl_s_cloud->at(i).x = static_cast<float>(P->x);
pcl_s_cloud->at(i).y = static_cast<float>(P->y);
pcl_s_cloud->at(i).z = static_cast<float>(P->z);
}
}
catch(...)
{
//any error (memory, etc.)
pcl_t_cloud.reset();
pcl_s_cloud.reset();
}
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree1 (new pcl::search::KdTree<pcl::PointXYZ>);
tree1->setInputCloud (pcl_t_cloud);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree2 (new pcl::search::KdTree<pcl::PointXYZ>);
tree2->setInputCloud (pcl_s_cloud);
pcl::PolygonMesh::Ptr mesh(new pcl::PolygonMesh);
// reconstruct meshes for source and target
pcl::OrganizedFastMesh<pcl::PointXYZ> fast_mesh;
fast_mesh.setInputCloud(pcl_t_cloud); //设置输入点云
/* ofm.setIndices(cloudInd);*/ //设置输入点云索引
fast_mesh.setMaxEdgeLength(0.1); //设置多边形网格最大边长
fast_mesh.setTriangulationType(pcl::OrganizedFastMesh<pcl::PointXYZ>::TRIANGLE_ADAPTIVE_CUT);//设置网格类型
fast_mesh.setTrianglePixelSize(1); //设置三角形边长 1表示链接相邻点作为边长
//fast_mesh.storeShadowedFaces(false); //设置是否存储阴影面
fast_mesh.setSearchMethod(tree1);
fast_mesh.reconstruct(*mesh);
// compute normals and covariances for source and target
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
boost::shared_ptr<std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> >> target_covariances(new std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> >);
pcl::features::computeApproximateNormals(*pcl_t_cloud, mesh->polygons, *normals);
pcl::features::computeApproximateCovariances(*pcl_t_cloud, *normals, *target_covariances); fast_mesh.setInputCloud(pcl_s_cloud);
/* ofm.setIndices(cloudInd);*/ //设置输入点云索引
fast_mesh.setMaxEdgeLength(1.0); //设置多边形网格最大边长
fast_mesh.setTriangulationType(pcl::OrganizedFastMesh<pcl::PointXYZ>::TRIANGLE_ADAPTIVE_CUT);//设置网格类型
fast_mesh.setTrianglePixelSize(1); //设置三角形边长 1表示链接相邻点作为边长
fast_mesh.storeShadowedFaces(false); //设置是否存储阴影面
fast_mesh.setSearchMethod(tree2);
fast_mesh.reconstruct(*mesh);
// compute normals and covariances for source and target
pcl::PointCloud<pcl::Normal>::Ptr normalst(new pcl::PointCloud<pcl::Normal>);
boost::shared_ptr<std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d>>> source_covariances(new std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> >);
pcl::features::computeApproximateNormals(*pcl_s_cloud, mesh->polygons, *normalst);
pcl::features::computeApproximateCovariances(*pcl_s_cloud, *normalst, *source_covariances);
// setup Generalized-ICP
pcl::GeneralizedIterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> gicp;
gicp.setMaxCorrespondenceDistance(maxCorrDis);
gicp.setInputSource(pcl_s_cloud);
gicp.setInputTarget(pcl_t_cloud);
/*gicp.setSourceCovariances(source_covariances);
gicp.setTargetCovariances(target_covariances);*/
// run registration and get transformation
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZ>);
gicp.align(*cloud_out);
Eigen::Matrix4f transform = gicp.getFinalTransformation();
int pointCount = cloud_out->size(); //static_cast<size_t>(sm_cloud ? sm_cloud->width * sm_cloud->height : 0); ccPointCloud* ccCloud =new ccPointCloud();
if (!ccCloud->reserve(static_cast<unsigned>(pointCount)))
return ;
for (size_t i = 0; i < pointCount; ++i)
{
CCVector3 P(cloud_out->at(i).x,cloud_out->at(i).y,cloud_out->at(i).z);
ccCloud->addPoint(P);
}
ccCloud->setName(QString("GICP"));
ccColor::Rgb col = ccColor::Generator::Random();
ccCloud->setRGBColor(col);
ccCloud->showColors(true);
ccCloud->setPointSize(1);
ccHObject* group = 0;
if (!group)
group = new ccHObject(QString("GICP(%1)").arg(ent2->getName()));
group->addChild(ccCloud);
group->setVisible(true);
m_app->addToDB(group);
}

   

近似特征值计算

这个的原理被想复杂了,就是特征值分解的逆步骤,形成了三个正交的向量,epsilon是最小的特征值,法向量是最小的特征向量。

本来求法向量的过程就是根据近邻的k个点,利用主成分分析PCA进行计算得到特征值最小的那个特征向量作为法向量。

/** \brief Compute GICP-style covariance matrices given a point cloud and
* the corresponding surface normals.
* \param[in] cloud Point cloud containing the XYZ coordinates,
* \param[in] normals Point cloud containing the corresponding surface normals.
* \param[out] covariances Vector of computed covariances.
* \param[in] Optional: Epsilon for the expected noise along the surface normal (default: 0.001)
*/
template <typename PointT, typename PointNT> inline void
computeApproximateCovariances(const pcl::PointCloud<PointT>& cloud,
const pcl::PointCloud<PointNT>& normals,
std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> >& covariances,
double epsilon = 0.001)
{
assert(cloud.points.size() == normals.points.size()); int nr_points = static_cast<int>(cloud.points.size());
covariances.resize(nr_points);
for (int i = 0; i < nr_points; ++i)
{
Eigen::Vector3d normal(normals.points[i].normal_x,
normals.points[i].normal_y,
normals.points[i].normal_z); // compute rotation matrix
Eigen::Matrix3d rot;
Eigen::Vector3d y;
y << 0, 1, 0;
rot.row(2) = normal;
y = y - normal(1) * normal;
y.normalize();
rot.row(1) = y;
rot.row(0) = normal.cross(rot.row(1)); // comnpute approximate covariance
Eigen::Matrix3d cov;
cov << 1, 0, 0,
0, 1, 0,
0, 0, epsilon;
covariances[i] = rot.transpose()*cov*rot;
}
} }

  

[PointCloud] GICP的更多相关文章

  1. ros pcl sensor::pointcloud2 转换成pcl::pointcloud

    #include <pcl_conversions/pcl_conversions.h> #include <pcl/point_types.h> #include <p ...

  2. How to publish a pointcloud of ros msgs in a topic from a pcd file?

    How to publish a pointcloud of ros msgs in a topic from a pcd file? Two methods 1. modified source 2 ...

  3. [转]ROS 传感器消息及RVIZ可视化Laserscan和PointCloud

    https://blog.csdn.net/yangziluomu/article/details/79576508 https://answers.ros.org/question/60239/ho ...

  4. 论文笔记:(2019)LDGCNN : Linked Dynamic Graph CNN-Learning on PointCloud via Linking Hierarchical Features

    目录 摘要 一.引言 A.基于视图的方法 B.基于体素的方法 C.基于几何的方法 二.材料 三.方法 A.问题陈述 B.图生成 C.图特征提取 D.变换不变函数 E.LDGCNN架构 F.冻结特征提取 ...

  5. pointcloud(点云)与mesh(面元)模型的区别

    点元与面元

  6. PointCloud及其经典论文介绍

    这篇博客会介绍点云的基本知识,重点介绍最近两年发表的部分经典论文,有什么建议欢迎留言! 点云基本介绍 点云是某个坐标系下的点的数据集,包含了丰富的信息,可以是三维坐标X,Y,Z.颜色.强度值.时间等等 ...

  7. pcl曲面网格模型的三种显示方式

    pcl网格模型有三种可选的显示模式,分别是面片模式(surface)显示,线框图模式(wireframe)显示,点模式(point)显示.默认为面片模式进行显示.设置函数分别为: void pcl:: ...

  8. pcl计算样点法向并显示

    利用最小二乘法估计样点表面法向,并显示 #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include < ...

  9. pcl曲面重建模块-poisson重建算法示例

    poisson曲面重建算法 pcl-1.8测试通过 #include <iostream> #include <pcl/common/common.h> #include &l ...

随机推荐

  1. 经验分享:多屏复杂动画CSS技巧三则

    当下CSS3应用已经相当广泛,其中重要成员之一就是CSS3动画.并且,随着CSS动画的逐渐深入与普及,更复杂与细腻的动画场景也如雨后春笋般破土而出.例如上个月做的「企业QQ-新年祝福」活动: 感谢sh ...

  2. Android MultiDex

    出现的原因: 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执行的.这个过程会生 ...

  3. Coder-Strike 2014 - Round 1 C. Pattern

    题目的意思是给出n个长度相同的字符串然后找出与他们匹配的字符串 将字符串存入类似二维数组的里面,每一行代表一个字符串,遍历每列,判断每列是否有公共的匹配字符,如果有输出任意一个 如果没有输出'?' # ...

  4. ACM: hdu 1811 Rank of Tetris - 拓扑排序-并查集-离线

    hdu 1811 Rank of Tetris Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & % ...

  5. 10.28&29(NOIP模拟&修正&总结)

    三道题: T1:约数的约数的个数和.数论.但是简单暴力A了. T2:前k大的(带权点ai与带权点bi的和)的和.二分.骗40. T3:三维空间内每次减少有与空点的点,前后左右相连,求最短时间减为空.d ...

  6. QQ 微信 新浪 无法 分享 收集

    1.网络请求报错.升级Xcode 7.0发现网络访问失败.输出错误信息 The resource could not be loaded because the App Transport Secur ...

  7. 基于MINA构建简单高性能的NIO应用

    mina是非常好的C/S架构的java服务器,这里转了一篇关于它的使用感受. 前言MINA是Trustin Lee最新制作的Java通讯框架.通讯框架的主要作用是封装底层IO操作,提供高级的操作API ...

  8. php 处理递归提成的方案

    好久没有写blog了,最近CRM项目中用到了递归提成的方案 CREATE TABLE `crm_proxy_bonux_rule` ( `id` ) NOT NULL AUTO_INCREMENT C ...

  9. Express 路由

    路由 路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求. 路由是由一个 URI.HTTP 请求(GET.POST等)和若干个句柄组成,它的结构如下: app.METHOD(path, [ ...

  10. 几种常用的JS类定义方法

    几种常用的JS类定义方法   // 方法1 对象直接量var obj1 = {    v1 : "",    get_v1 : function() {        return ...