zoukankan      html  css  js  c++  java
  • [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进行计算得到特征值最小的那个特征向量作为法向量。

    /** rief 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;
          }
        }
    
      }
    

      

  • 相关阅读:
    线程池ThreadPoolExecutor
    常用引擎+存储过程
    在浏览器中输入www.baidu.com后执行的全过程
    win端git连接私服仓库+上传本地项目+从服务器下载文件到win
    TCP的三次握手和四次挥手+TCP和UDP的区别
    2017网易---计算糖果
    ubuntu下wireshark+scapy+tcpreply
    网易2017---数列还原
    2017网易---藏宝图
    2017网易---不要二
  • 原文地址:https://www.cnblogs.com/yhlx125/p/5709157.html
Copyright © 2011-2022 走看看