IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 点云统一法线方向 -> 正文阅读

[人工智能]点云统一法线方向

大致思路:定义起始种子点后通过当前点k邻域搜索最邻近点,调整邻近点法线朝向与当前种子点法线朝向同向,然后传播出去。
具体实现:(1)用vector模拟两个栈points和normals,存放点云的点和法线。首先将初始种子点压入这两个栈。
(2)设置一个和点云点数相同大小的flags用来标记点云中的点是否被生长过,并将初始种子点的标志位置为true。
(3)建立点云的kd树。
(4)分别从points和normals弹出最后一个值作为当前种子点,计算该点对应的法线,并求出其k邻域点。
(5)遍历该点的k邻域点,若该点未被标记过,判断该点与当前种子点法线朝向是否同向,如果反向则翻转法线方向。将该点压入栈中并将该点的标志位置为true。
(6)返回(4),直到栈为空。

/**
* @brief normal_flip   法线方向翻转
* @param cloud         点云
* @param cloud_normals 点云法线
* @param seed_index    种子点索引
*/
void normal_flip(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::Normal>::Ptr& cloud_normals, int seed_index)
{
	std::vector<pcl::PointXYZ> points;
	std::vector<pcl::Normal> normals;
	points.push_back(cloud->points[seed_index]);
	normals.push_back(cloud_normals->points[seed_index]);

	std::vector<int> flags(cloud->size(), 0);   //用来标记点云中的点是否被生长过
	flags[seed_index] = 1;

	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
	kdtree.setInputCloud(cloud);
	int K = 20;
	std::vector<int> pointsIdx(K);          //索引
	std::vector<float> pointsDistance(K);   //距离

	while (!normals.empty())
	{
		pcl::PointXYZ seed_point = points.back();   //种子点
		pcl::Normal seed_normal = normals.back();   //种子点法线
		points.pop_back();
		normals.pop_back();

		Eigen::Vector3f v1(seed_normal.normal_x, seed_normal.normal_y, seed_normal.normal_z);

		kdtree.nearestKSearch(seed_point, K, pointsIdx, pointsDistance);    //k近邻搜索

		for (size_t i = 0; i < pointsIdx.size(); i++)
		{
			if (flags[pointsIdx[i]] == 0)   //如果该点没有被生长到
			{
				Eigen::Vector3f	v2(cloud_normals->points[pointsIdx[i]].normal_x,
					cloud_normals->points[pointsIdx[i]].normal_y,
					cloud_normals->points[pointsIdx[i]].normal_z);

				if (v1.dot(v2) < 0) //如果该点法线方向与种子点法线方向相反(夹角为钝角),则翻转法线方向
				{
					cloud_normals->points[pointsIdx[i]].normal_x *= -1;
					cloud_normals->points[pointsIdx[i]].normal_y *= -1;
					cloud_normals->points[pointsIdx[i]].normal_z *= -1;
				}
				points.push_back(cloud->points[pointsIdx[i]]);
				normals.push_back(cloud_normals->points[pointsIdx[i]]);
				flags[pointsIdx[i]] = 1;    //标记该点已经被生长过
			}
		}
	}

	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_flag(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::copyPointCloud(*cloud, flags, *cloud_flag);
	//pcl::io::savePCDFile("cloud_flag.pcd", *cloud_flag);
}

效果展示:
pcl法线提取结果(法线朝向有内有外)
在这里插入图片描述

统一法线方向结果(法线朝向都朝外侧)
在这里插入图片描述
参考:无序点云的法线全局定向

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:02:58  更:2022-04-01 00:06:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 0:47:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码