Harris3D调参记录

一、测试文件(华中科技大学南一楼7位点云图):

链接:https://pan.baidu.com/s/1vnc5ZqShDCtx-acD182WkA
提取码:5m84

二、调参技巧:

1、首先要确定法线计算时使用的半径范围。半径过小会导致搜索不到邻近点(出现程序无法出结果的情况),半径太大会导致搜索太慢,且法线计算不够准确。因此确定点云的分辨率量级很重要。使用CloudCompare软件获取两点之间的距离,确定搜索半径的量级,然后在量级合理的约束下调节参数。在不能确定量级的情况下,还可以使用setKsearch来设置邻居点的个数。这种参数设置一定不会出现程序卡住的现象。

CloudCompare软件我放在网盘,自取:链接:https://pan.baidu.com/s/1QuZxx_UDGV0U6Jp7bO8LZQ
提取码:rvyn

图1:获取两点之间的距离
2、Harris3D小立方体的半径设置和抑制阈值的设置
Harris3D小立方体的半径这个参数的设置我也是通过量级的一个估计来设置的。然后比较有意思的是阈值的设置,这个数是没办法估计的。所以我到pcl库的Harriss3D种,计算R的地方进行了输出,通过输出的R的大致范围,设置阈值使得阈值以上的点的个数大概占整个点云个数的1%左右。
输出设置:在 harris3D.hpp文件427行 这里加输出,如下图所示:
在这里插入图片描述在这里插入图片描述
输出:
图2:点云的R响应值
值得注意的是,这两个参数的设置是相关的。原来设置搜索半径为2时,抑制阈值为0.02时,输出R是有大于0.02的点,但是最终检测出来的点却只有0个。 是因为非极大值抑制把这些点一直掉了,也就是搜索半径太大了(pcl中搜索半径和抑制半径是一个变量)。所以我减小搜索半径,并且相应减小抑制阈值,就检测到Harris点了。这一点也是比较有趣的。

三、代码
#include <iostream>
#include <pcl/console/parse.h>
#include <pcl/console/print.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/keypoints/harris_3d.h> // Harris3D关键点检测
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>

int
main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCLPointCloud2::Ptr cloud_brob(new pcl::PCLPointCloud2);
	pcl::PointCloud<pcl::PointXYZ>::Ptr filter(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCLPointCloud2::Ptr filter_brob(new pcl::PCLPointCloud2);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("c1filter.pcd", *cloud) == -1) // load the file
	{
		pcl::console::print_error("Couldn't read file %s!\n");
		return (-1);
	}
	cout << "从输入点云中读取:" << cloud->points.size() << "个点" << endl;

	//-------------------------------滤波-----------------------------
	/*cout << "开始滤波" << endl;
	pcl::toPCLPointCloud2(*cloud, *cloud_brob);
	pcl::VoxelGrid<pcl::PCLPointCloud2> grid;
	grid.setLeafSize(0.5f, 0.5f, 0.5f);
	grid.setInputCloud(cloud_brob);
	grid.filter(*filter_brob);
	pcl::fromPCLPointCloud2(*filter_brob, *filter);
	cout << "滤波后点数:" << filter->points.size() << "个点" << endl;
	pcl::io::savePCDFile("c2filter.pcd", *filter, true);
	cout << "滤波完成" << endl;*/
	//----------------------------计算法线-------------------------
	cout << "开始计算法线" << endl;
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
	ne.setInputCloud(cloud);
	pcl::search::KdTree< pcl::PointXYZ>::Ptr tree_src(new pcl::search::KdTree< pcl::PointXYZ>());
	ne.setSearchMethod(tree_src);
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud< pcl::Normal>);
	//以最近的10的点来估计法向量
	//或者用0.5的半径去搜索
	ne.setRadiusSearch(0.5);
	ne.compute(*cloud_normals);
	cout << "法线计算完成" << endl;

	//-----------------------------Harris关键点提取----------------------------------
	//注意此处PCL的point类型设置为<pcl::PointXYZI>,即除了x、y、z坐标还必须包含强度信息
	//因为Harris的评估值保存在输出点云的(I)分量中,Harris输出点云中的(I)非传统点云中的
	//强度信息,因此后续在保存和可视化输出点云的时候需要通过点的索引来重新获取。
	//-------------------------------------------------------------------------------
	pcl::HarrisKeypoint3D <pcl::PointXYZ, pcl::PointXYZI> harris;
	pcl::PointCloud<pcl::PointXYZI>::Ptr Harris_keypoints(new pcl::PointCloud<pcl::PointXYZI>);

	harris.setInputCloud(cloud);     // 提供指向输入数据集的指针
	cout << "input successful" << endl;
	harris.setMethod(harris.LOWE);
	//输入法向量
	harris.setNormals(cloud_normals);
	//设置Harris3D小立方体的半径
	harris.setRadius(1);
	//是否进行R阈值检测,给定范围内的非极大值抑制(这个给定的范围跟求R值时使用到的球半径是一样的),无穷大响应值筛除
	harris.setNonMaxSupression(true);
	//阈值检测
	harris.setThreshold(0.01);
	//是否进行细化,细化后提取出来的点一定为点云中的点
	harris.setRefine(true);
	harris.setNumberOfThreads(6);

	cout << "提取关键点" << endl;
	harris.compute(*Harris_keypoints);

	cout << "提取关键点" << Harris_keypoints->points.size() << "个" << endl;
	pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>);
	//-----------------------获取关键点的索引-------------------------
	pcl::PointIndicesConstPtr keypoints2_indices = harris.getKeypointsIndices();
	//pcl::PointXYZI格式无法正确保存和显示,这里通过索引从原始点云中获取位于点云中特征点
	pcl::copyPointCloud(*cloud, *keypoints2_indices, *keypoints);
	pcl::io::savePCDFile("c1_keypointsrgb.pcd", *keypoints, true);
	//----------------------------可视化-----------------------------
	boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("显示点云"));
	viewer->setBackgroundColor(0,0,0);  //设置背景颜色为黑色
	viewer->setWindowName("Harris3D关键点检测");
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> harris_color_handler(keypoints, 255, 0, 0);
	viewer->addPointCloud<pcl::PointXYZ>(keypoints, harris_color_handler, "Harris_keypoints");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "Harris_keypoints");
	viewer->addPointCloud(cloud, "input_cloud");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "input_cloud");
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}

	return (0);
}


代码有问题30天内问我 再过几天我就忘了hhh

四、结果展示

在这里插入图片描述
效果还是不错的,窗户的角点,毛主席像台的角等等都检测出来啦!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值