请问各位,PCL中编写的调整法向量方向一致的函数在运行之后输出的点与输入的点点数不一致,少了部分点,是什么原因呢?
点数不一致的话在三维视窗中没办法显示相应的法线以及后面的处理了
cloud_normals.pcd文件已上传至网盘中:
链接:https://pan.baidu.com/s/194d2uHQXft5sSZRELL0Awg
提取码:1234
以下是我的代码:
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/kdtree/kdtree_flann.h>
// 调整法向量方向函数定义
void normal_flip(pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normal)
{
int seed_index = cloud_with_normal->size();
std::vector<pcl::PointNormal> points;
points.push_back(cloud_with_normal->points[seed_index]);
std::vector<bool> flags(cloud_with_normal->size(), false); //用来标记点云中的点是否被生长过
flags[seed_index] = true;
pcl::KdTreeFLANN<pcl::PointNormal> kdtree;
kdtree.setInputCloud(cloud_with_normal);
int K = 20;
std::vector<int> pointsIdx(K); //索引
std::vector<float> pointsDistance(K); //距离
while (!points.empty())
{
pcl::PointNormal seed_normal = points.back(); //种子点法线
points.pop_back();
kdtree.nearestKSearch(seed_normal, K, pointsIdx, pointsDistance); //k近邻搜索
Eigen::Vector3f v1(seed_normal.normal_x, seed_normal.normal_y, seed_normal.normal_z);
for (size_t i = 0; i < pointsIdx.size(); i++)
{
if (!flags[pointsIdx[i]]) //如果该点没有被生长到
{
Eigen::Vector3f v2(cloud_with_normal->points[pointsIdx[i]].normal_x,
cloud_with_normal->points[pointsIdx[i]].normal_y,
cloud_with_normal->points[pointsIdx[i]].normal_z);
if (v1.dot(v2) < -1) //如果该点法线方向与种子点法线方向夹角大于180度,则翻转法线方向
{
cloud_with_normal->points[pointsIdx[i]].normal_x *= -1;
cloud_with_normal->points[pointsIdx[i]].normal_y *= -1;
cloud_with_normal->points[pointsIdx[i]].normal_z *= -1;
}
points.push_back(cloud_with_normal->points[pointsIdx[i]]);
flags[pointsIdx[i]] = true; //标记该点已经被生长过
}
}
}
std::vector<int> indexs;
for (size_t i = 0; i < flags.size(); ++i)
{
if (flags[i])
indexs.push_back(i);
}
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_flag(new pcl::PointCloud<pcl::PointNormal>);
pcl::copyPointCloud(*cloud_with_normal, indexs, *cloud_flag);
pcl::io::savePCDFile("cloud_flag.pcd", *cloud_flag);
}
int main()
{
// 1. 打开一个pcd文件,创建指针为cloud维护该数据
pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal>);
if (pcl::io::loadPCDFile<pcl::PointNormal>("cloud_normals.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read file input.pcd \n");
return (-1);
}
// 2. 调整法向量方向函数实现,输出cloud_flag.pcd
normal_flip(cloud);
return 0;
}
根据提供的参考资料和代码片段,看起来是关于PCL库的安装和使用问题。根据段落0中的安装过程,你使用的是PCL-1.12.1版本的库。
首先,你需要安装PCL库。根据段落0,你已经安装了PCL-1.12.1-AllInOne-msvc2019-win64.exe文件。在安装过程中,确保勾选了"Add PCL to the system Path for all users"选项,并设置了你的路径。此外,还需要在系统变量中添加PCL_ROOT变量,并在系统变量Path中添加PCL库的路径中的bin文件夹。
接下来,根据段落7中的代码片段,你可以使用PCL库进行点云处理。这段代码通过使用ISS关键特征点检测算法,在给定的点云数据上计算关键点。具体步骤如下:
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/keypoints/iss_3d.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/cloud_viewer.h>
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\julei\\准确参考4.pcd", *cloud) == -1)
{
PCL_ERROR("Could not read pcd file\n");
}
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.7f);
iss.setNonMaxRadius(0.5f);
iss.setThreshold21(0.65);
iss.setThreshold32(0.5);
iss.setMinNeighbors(10);
iss.setNumberOfThreads(4);
iss.compute(*keypoints);
cout << "总点个数" << cloud->size() << endl;
cout << "ISS关键点个数" << keypoints->size() << endl;
pcl::io::savePCDFile("D:\\julei\\准确参考4的关键点.pcd", *keypoints, true);
system("pause");
return 0;
请注意,代码中的文件路径可能需要根据你的实际情况进行修改。如果你已经按照参考资料中的步骤进行了安装和配置,且代码中的路径正确无误,那么这段代码应该可以顺利运行并计算出关键点。
希望这个解决方案对你有所帮助!如果你还有其他问题,请随时提问。