\quad 点云ISS特征提取:
文章:《Intrinsic shape signatures: A shape descriptor for 3D object recognition》
\qquad 内部形状描述子(ISS)是一种表示立体几何形状的方法,该算法含有丰富的几何特征信息。
算法流程:
\qquad 设点云数据有M个点,其任意一点 p i p_i pi坐标为 ( x i , y i , z i ) (x_i,y_i,z_i) (xi,yi,zi), i = 0 , 1 , . . . , M − 1 i=0,1,...,M-1 i=0,1,...,M−1
(1)对点云上的每个点 p i p_i pi定义一个局部坐标系,并给定每一个点一个搜索半径 r f r a m e r_{frame} rframe。
(2)查询点云数据中每个点 p i p_i pi在半径 r f r a m e r_{frame} rframe周围内的所有点,并计算其权值。 ω i j = 1 / ∣ p i − p j ∣ , ∣ p i − p j ∣ < r frama \omega_{i j}=1 /\left|p_{i}-p_{j}\right|,\left|p_{i}-p_{j}\right|
cov ( p i ) = ∑ ∣ p i − p j ∣ < r f fnux ω i j ( p i − p j ) ( p i − p j ) T / ∑ ∣ p i − p j ∣ < r franx ω i j \operatorname{cov}\left(p_{i}\right)=\sum_{\left|p_{i}-p_{j}\right|
(5)设置阈值 ε 1 \varepsilon_{1} ε1和 ε 2 \varepsilon_{2} ε2,满足下式条件的点视为ISS特征点。
λ i 2 / λ i 1 ≤ ε 1 , λ i 3 / λ i 2 ≤ ε 2 \lambda_{ i }^{2} / \lambda_{i}^{1} \leq \varepsilon_{1}, \lambda_{ i }^{3} / \lambda_{i}^{2} \leq \varepsilon_{2} λi2/λi1≤ε1,λi3/λi2≤ε2
\quad PCL实现
\qquad 程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
void CreateCloudFromTxt(const std::string& file_path,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
std::ifstream file(file_path.c_str());
std::string line;
std::string no_use;
pcl::PointXYZ point;
while (getline(file, line)) {
string::iterator it;
for (it = line.begin(); it < line.end(); it++)
{
if (*it == ',')
{
line.erase(it);
line.insert(it, ' ');
it--;
}
}
std::stringstream ss(line);
ss >> point.x;
ss >> point.y;
ss >> point.z;
cloud->push_back(point);
}
file.close();
}
int main(int, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
CreateCloudFromTxt(argv[1],cloud);
cout << "读取点云个数: " << cloud->points.size() << endl;
pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss;
pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>());
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
iss.setInputCloud(cloud);
iss.setSearchMethod(tree);
iss.setSalientRadius(0.08f);//设置用于计算协方差矩阵的球邻域半径
iss.setNonMaxRadius(0.06f);//设置非极大值抑制应用算法的半径
iss.setThreshold21(0.65); //设定第二个和第一个特征值之比的上限
iss.setThreshold32(0.5); //设定第三个和第二个特征值之比的上限
iss.setMinNeighbors(10); //在应用非极大值抑制算法时,设置必须找到的最小邻居数
iss.setNumberOfThreads(4); //初始化调度器并设置要使用的线程数
iss.compute(*keypoints);
cout << keypoints->points.size() << endl;
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("ISS"));
viewer->setBackgroundColor(255,255,255);
viewer->setWindowName("ISS关键点提取");
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color(cloud, 0.0, 255, 0.0);
viewer->addPointCloud<pcl::PointXYZ>(cloud, color, "cloud");
viewer->addPointCloud<pcl::PointXYZ>(keypoints, "keypoint_cloud");//特征点
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "keypoint_cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "keypoint_cloud");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100));
}
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(iss)
find_package(PCL REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (iss iss.cpp)
target_link_libraries (iss ${PCL_LIBRARIES})