泛化的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. 隐式调用 Intent 大全, 很全

    http://ming-fanglin.iteye.com/blog/1061312 //调用浏览器 Uri uri = Uri.parse(""); Intent it  = n ...

  2. Coder-Strike 2014 - Round 1 A. Poster

    主要就是先将梯子移动到最左边或者最右边 k>n/2时移动到最右边 k<=n/2时移动到最左边 然后遍历一遍 #include <iostream> #include <v ...

  3. 主席树+启发式合并(LT) BZOJ3123

    好久没做题了,写道SBT又RE又T 查询:主席树裸题. 修改:对于两个树合并重建小的树. 注意fa[x][i]重新计算时要清空 #include<cstdio> #include<c ...

  4. 关于C#引用Dll后,找不到命名空间的问题

    在引用里明确添加了一个Dll,能够看到该Dll详细信息,可就是用using找不到命名空间.并且发现刚引用时是有该命名空间,一编译就消失了. 最后发现原因如下: 原目标框架为.Net Framework ...

  5. 纪念逝去的岁月——C/C++字符串旋转

    几年前,我还不会写这个 例如: 1.向右→旋转5个字符 输入:HelloWorld 输出:WorldHello 2.向右→旋转3个字符 输入:HelloWorld 输出:rldHelloWo 代码 # ...

  6. JAVA复制网络图片到本地

    import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.Out ...

  7. linux笔记八---------文件查找

    1.find文件查找指令 > find  目录  参数 参数值,参数 参数值.....    > find  /  -name  passwd   //从系统根目录开始递归查找name=p ...

  8. 解决PHP下导出csv乱码小记

    我们之前都是使用PHPexcel导出我们的一些数据的,由于Phpexcel对导出超出1万条数据会导至超时和内存暴涨,后来我们就改用数据导出成csv格式的. 相信很多朋友们在用PHP导出csv文件时都遇 ...

  9. CCF关于NOIP2014复赛报名的通知

    CCF关于NOIP2014复赛报名的通知   CCF NOIP2014复赛全部实行网上注册.报名.未通过网上报名的选手将不具备参赛和申诉资格. 系统注册须知: NOIP2014复赛注册时间:2014年 ...

  10. param STRING $username 要检查的用户名

    检查用户名是否符合规定 两位以上的字母,数字,或者下划线,代码如下: php;auto-links:false;">/** * 检查用户名是否符合规定 * * @param STRIN ...