[PointCloud] GICP
泛化的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的更多相关文章
- ros pcl sensor::pointcloud2 转换成pcl::pointcloud
#include <pcl_conversions/pcl_conversions.h> #include <pcl/point_types.h> #include <p ...
- 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 ...
- [转]ROS 传感器消息及RVIZ可视化Laserscan和PointCloud
https://blog.csdn.net/yangziluomu/article/details/79576508 https://answers.ros.org/question/60239/ho ...
- 论文笔记:(2019)LDGCNN : Linked Dynamic Graph CNN-Learning on PointCloud via Linking Hierarchical Features
目录 摘要 一.引言 A.基于视图的方法 B.基于体素的方法 C.基于几何的方法 二.材料 三.方法 A.问题陈述 B.图生成 C.图特征提取 D.变换不变函数 E.LDGCNN架构 F.冻结特征提取 ...
- pointcloud(点云)与mesh(面元)模型的区别
点元与面元
- PointCloud及其经典论文介绍
这篇博客会介绍点云的基本知识,重点介绍最近两年发表的部分经典论文,有什么建议欢迎留言! 点云基本介绍 点云是某个坐标系下的点的数据集,包含了丰富的信息,可以是三维坐标X,Y,Z.颜色.强度值.时间等等 ...
- pcl曲面网格模型的三种显示方式
pcl网格模型有三种可选的显示模式,分别是面片模式(surface)显示,线框图模式(wireframe)显示,点模式(point)显示.默认为面片模式进行显示.设置函数分别为: void pcl:: ...
- pcl计算样点法向并显示
利用最小二乘法估计样点表面法向,并显示 #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include < ...
- pcl曲面重建模块-poisson重建算法示例
poisson曲面重建算法 pcl-1.8测试通过 #include <iostream> #include <pcl/common/common.h> #include &l ...
随机推荐
- Windows下查看端口冲突的进程
在tomcat部署中,经常遇到80端口被占用,下面总结了两条查看端口进程的方法. 查看端口方法: netstat -aon|findstr "80" 如图,使用80端口的进程列 ...
- java.io包详细解说
转自:http://hzxdark.iteye.com/blog/40133 hzxdark的博客 我不知道各位是师弟师妹们学java时是怎样的,就我的刚学java时的感觉,java.io包是最让我感 ...
- 关于使用rem单位,calc()进行自适应布局
关于css中的单位 大家都知道在css中的单位,一般都包括有px,%,em等单位,另外css3新增加一个单位rem. 其中px,%等单位平时在传统布局当中使用的比较频繁,大家也比较熟悉,不过px单位在 ...
- 【转】移动web页面使用字体的思考
回想2年前刚开始接触手机项目,接到PSD稿后,发现视觉设计师们喜欢用微软雅黑作为中文字体进行设计,于是我写页面的时候也定义 font-family 为微软雅黑,后来发到线上后,细心的产品经理发现页面的 ...
- Windows 8 Tips
Precisely this article is about Windows 8.1, the title uses Windows 8 due to the fact that Windows 8 ...
- 【BZOJ1088】[SCOI2005]扫雷Mine 递推
调LCT奔溃,刷水调节一下. #include <iostream> #include <cstdio> #include <cstring> using name ...
- sql:select赋值和set赋值的区别
1)Set写法 declare @i integer set @i=(select count(*) from test) select @i Select写法 declare @i integer ...
- reason: '*** Collection <__NSCFArray: 0x7ffa43528f70> was mutated while being enumerated.'
一,错误分析 1.崩溃代码如下: //遍历当前数组,判断是否有相同的元素 for (NSString *str in self.searchHistoryArrM) { if ([str isEqua ...
- Bootstrap_Datatable Ajax请求两次问题的解决
最近一个项目中使用JQuery Datatable,用起来比较方便,但在测试过程中,发现当条件改变时,有时查询结果中的数据不正确. 使用FireBug跟踪时,发现在使用Ajax请求时,点击一次搜索按钮 ...
- springboot 添加job定时任务
@SpringBootApplication@ComponentScan("com.xx")@EnableScheduling //定时任务扫描 此处用该注解,容器启动自动扫描pu ...