PCL拟合并绘制平面和柱面(三)

PCL绘制自定义图形

在使用PCL拟合平面和柱面后,需要绘制自定义大小和位置的平面和柱面以便于可视化。

//拟合类型
enum FitType
{FitPlane = 1,    //平面FitCylinder = 2  //圆柱
};

主要函数:

void PointCloudViewer(PointCloudT::Ptr cloudseg, PointCloudT::Ptr cloudfiltered, PointCloudT::Ptr cloudOut, pcl::ModelCoefficients::Ptr coefficients)
{pcl::visualization::PCLVisualizer viewer("viewer");float bckgr_gray_level = 0.0;float txt_gray_lvl = 1.0 - bckgr_gray_level;int v1(0);viewer.createViewPort(0.0, 0.0, 1.0, 1.0, v1);//分割点云pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_seg_color_h(cloudseg, 0, 255, 0);viewer.addPointCloud(cloudseg, cloud_seg_color_h, "cloudseg", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloudseg");//剩余点云pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_filter_color_h(cloudfiltered, 255, 255, 0);viewer.addPointCloud(cloudfiltered, cloud_filter_color_h, "cloudfilter", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloudfilter");//模型Eigen::Vector3f mass_center;if (mFitType == FitPlane){float width = 300.0, height = 300.0;  //x,yGetPointsBoundingBoxAABB(cloudseg, width, height, mass_center);//分割平面:自定义的平面大小float scale[2] = { width, height };//利用PCL函数计算质心Eigen::Vector4f centroid;					    // 质心pcl::compute3DCentroid(*cloudseg, centroid);	// 齐次坐标,(c0,c1,c2,1)auto plane = createPlane(*coefficients, centroid[0] - width / 2.0, centroid[1] - height / 2.0, centroid[2], scale);viewer.addModelFromPolyData(plane, "plane_1");viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 1.0, "plane_1", v1);viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.6, "plane_1", v1);viewer.addText("point cloud plane", 10, 940, 16, bckgr_gray_level, txt_gray_lvl, txt_gray_lvl, "plane", v1);}else if (mFitType == FitCylinder){float width = 300.0, height = 300.0;  //x,yGetPointsBoundingBoxAABB(cloudseg, width, height, mass_center);float scale = std::max(width / 2.0, height / 2.0);auto cylinder = createCylinder(*coefficients, mass_center, 100, scale);viewer.addModelFromPolyData(cylinder, "cylinder_1");viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 1.0, "cylinder_1", v1);viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.6, "cylinder_1", v1);viewer.addText("point cloud cylinder", 10, 940, 16, bckgr_gray_level, txt_gray_lvl, txt_gray_lvl, "cylinder", v1);}//描述viewer.addText("point cloud seg", 10, 1000, 16, bckgr_gray_level, txt_gray_lvl, bckgr_gray_level, "cloudseg", v1);viewer.addText("point cloud filter", 10, 980, 16, txt_gray_lvl, txt_gray_lvl, bckgr_gray_level, "cloudfilter", v1);//背景 viewer.setBackgroundColor(bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v1);//相机位置if (mFitType == FitPlane)viewer.setCameraPosition(0.0, 0.0, coefficients->values[3] / 2.0, mass_center[0], mass_center[1], mass_center[2], 0.0, 1.0, 0.0);if (mFitType == FitCylinder)viewer.setCameraPosition(0.0, 0.0, coefficients->values[2] / 20.0, mass_center[0], mass_center[1], mass_center[2], 1.0, 0.0, 0.0);viewer.setSize(1280, 1024);//显示while (!viewer.wasStopped())viewer.spinOnce();
}

获取点云质心等参数:

void GetPointsBoundingBoxAABB(PointCloudT::Ptr cloudSource, float& width, float& height, Eigen::Vector3f& mass_center)
{// 创建惯性矩估算对象,设置输入点云,并进行计算pcl::MomentOfInertiaEstimation <pcl::PointXYZ> feature_extractor;feature_extractor.setInputCloud(cloudSource);feature_extractor.compute();std::vector <float> moment_of_inertia;std::vector <float> eccentricity;pcl::PointXYZ min_point_AABB;pcl::PointXYZ max_point_AABB;pcl::PointXYZ min_point_OBB;pcl::PointXYZ max_point_OBB;pcl::PointXYZ position_OBB;Eigen::Matrix3f rotational_matrix_OBB;float major_value, middle_value, minor_value;Eigen::Vector3f major_vector, middle_vector, minor_vector;// 获取惯性矩feature_extractor.getMomentOfInertia(moment_of_inertia);// 获取离心率feature_extractor.getEccentricity(eccentricity);// 获取AABB盒子feature_extractor.getAABB(min_point_AABB, max_point_AABB);// 获取OBB盒子feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);feature_extractor.getEigenValues(major_value, middle_value, minor_value);// 获取主轴major_vector,中轴middle_vector,辅助轴minor_vectorfeature_extractor.getEigenVectors(major_vector, middle_vector, minor_vector);// 获取质心feature_extractor.getMassCenter(mass_center);//获取高度和宽度width = (max_point_AABB.x - min_point_AABB.x)*1.2;height = (max_point_AABB.y - min_point_AABB.y)*1.2;
}

创建一个自定义平面(源代码地址):

vtkSmartPointer<vtkPolyData> VisionTrajectory::createPlane(const pcl::ModelCoefficients &coefficients, double x, double y, double z, float scale[2])
{vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();double norm_sqr = 1.0 / (coefficients.values[0] * coefficients.values[0] +coefficients.values[1] * coefficients.values[1] +coefficients.values[2] * coefficients.values[2]);plane->SetNormal(coefficients.values[0], coefficients.values[1], coefficients.values[2]);double t = x * coefficients.values[0] + y * coefficients.values[1] + z * coefficients.values[2] + coefficients.values[3];x -= coefficients.values[0] * t * norm_sqr;y -= coefficients.values[1] * t * norm_sqr;z -= coefficients.values[2] * t * norm_sqr;plane->SetCenter(x, y, z);{double pt1[3], pt2[3], orig[3], center[3];plane->GetPoint1(pt1);plane->GetPoint2(pt2);plane->GetOrigin(orig);plane->GetCenter(center);float scale1 = 3.0;float scale2 = 3.0;if (scale != nullptr){scale1 = scale[0];scale2 = scale[1];}//延长pt1,pt2. 延长origin到pt1连线的方向向量double _pt1[3], _pt2[3];for (int i = 0; i < 3; i++) {_pt1[i] = scale1 * (pt1[i] - orig[i]);_pt2[i] = scale2 * (pt2[i] - orig[i]);}//pt1相对于原坐标系下的坐标值for (int i = 0; i < 3; ++i){pt1[i] = orig[i] + _pt1[i];pt2[i] = orig[i] + _pt2[i];}plane->SetPoint1(pt1);plane->SetPoint2(pt2);}plane->Update();return (plane->GetOutput());

创建一个自定义柱面:

vtkSmartPointer<vtkPolyData> createCylinder(const pcl::ModelCoefficients &coefficients, Eigen::Vector3f mass_center, int numsides, float scale)
{if (coefficients.values.size() != 7){PCL_WARN("[addCylinder] Coefficients size does not match expected size (expected 7).\n");return (false);}//质心在轴线上的投影点P2double P0[3], P2[3];P0[0] = coefficients.values[0];P0[1] = coefficients.values[1];P0[2] = coefficients.values[2];double dlambda = (mass_center[0] - P0[0])*coefficients.values[3] + (mass_center[1] - P0[1])*coefficients.values[4] + (mass_center[2] - P0[2])*coefficients.values[5];P2[0] = P0[0] + dlambda * coefficients.values[3];P2[1] = P0[1] + dlambda * coefficients.values[4];P2[2] = P0[2] + dlambda * coefficients.values[5];//投影点平移double pt[3];pt[0] = coefficients.values[3] * scale;pt[1] = coefficients.values[4] * scale;pt[2] = coefficients.values[5] * scale;vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();line->SetPoint1(P2[0] - pt[0], P2[1] - pt[1], P2[2] - pt[2]);line->SetPoint2(P2[0] + pt[0], P2[1] + pt[1], P2[2] + pt[2]);vtkSmartPointer<vtkTubeFilter> tuber = vtkSmartPointer<vtkTubeFilter>::New();tuber->SetInputConnection(line->GetOutputPort());tuber->SetRadius(coefficients.values[6]);tuber->SetNumberOfSides(numsides);tuber->Update();return (tuber->GetOutput());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/786937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Php_Code_challenge12

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 字符串拼接。

文献阅读:通过 NeuronChat 从单细胞转录组推断神经元-神经元通信

文献介绍 「文献题目」 Inferring neuron-neuron communications from single-cell transcriptomics through NeuronChat 「研究团队」 聂青&#xff08;加利福尼亚大学欧文分校&#xff09; 「发表时间」 2023-02-28 「发表期刊」 Nature Communications 「影响因子」 16.6…

15 - grace序列处理 - 十三点滑动平均法

grace序列处理 -十三点滑动平均法 滑动平均是一种常用的平滑数据的方法,可以用于去除噪声或者提取趋势。十三点滑动平均是指使用窗口大小为13的滑动平均,应用于GRACE序列处理中可以去除周年项的影响。 十三点滑动平均的计算公式为: y [ n ] = ( x [ n − 6 ]

互联网轻量级框架整合之JavaEE基础I

不得不解释得几个概念 JavaEE SUN公司提出来的企业版Java开发中间件&#xff0c;主要用于企业级互联网系统的框架搭建&#xff0c;同时因为Java语言优质的平台无关性、可移植性、健壮性、支持多线程和安全性等优势&#xff0c;其迅速成为构建企业互联网平台的主流技术&#x…

关于Linux系统中Python核心包的重要性和恢复误卸载软件的方法

&#xff08;首发地址&#xff1a;学习日记 https://www.learndiary.com/2024/04/dont-remove-system-python/&#xff09; 大家好&#xff0c;我是来自淘宝网“学习日记小店”的 learndiary&#xff0c;专注于提供 Linux 相关的技术服务。昨日&#xff0c;一位使用 Ubuntu 20…

基于UML的系统分析与设计

统一建模语言(Unified Modeling Language&#xff0c;UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言&#xff0c;是非专利的第三代建模和规约语言。UML是面向对象设计的建模工具&#xff0c;独立于任何具体程序设计语言。 毕业设计是实现本科教学培…

Php_Code_challenge16

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 所以科学计数法绕过即可。

爬虫 知识点2

article_url url_tag[href]article_response requests.get(article_url, headersheaders)article_soup BeautifulSoup(article_response.content, "html.parser")print(index)&#xff08;1&#xff09;article_url url_tag[‘href’] 这行代码从一个名为url_tag…

Go 源码之切片 Slice

目录 Go 源码之切片 Slice一、总结二、源码&#xff08;一&#xff09;数据结构&#xff08;二&#xff09;创建Slice&#xff08;三&#xff09;append-扩容-growslice&#xff08;四&#xff09;切片深拷贝 Go 源码之切片 Slice go源码之Slice - Jxy 博客 一、总结 slice是…

python pip使用国内镜像

让PIP源使用国内镜像&#xff0c;提升下载速度和安装成功率。 对于Python开发用户来讲&#xff0c;PIP安装软件包是家常便饭。但国外的源下载速度实在太慢&#xff0c;浪费时间。而且经常出现下载后安装出错问题。所以把PIP安装源替换成国内镜像&#xff0c;可以大幅提升下载速…

Division(UVA 725)

网址如下&#xff1a; Division - UVA 725 - Virtual Judge (vjudge.net) &#xff08;第三方网站&#xff09; 考完CSP认证之后动力就有点不足&#xff0c;之后还有一个蓝桥杯&#xff0c;虽然说考的还行&#xff0c;混了个370&#xff0c;但是昨天一天都不怎么想敲代码 昨…

macOS Sonoma 14.4 23E214 VMware系统包下载地址,简单便捷,导入即可用!

这回分享的是VMware虚拟机macOS 14.4版本的系统包&#xff0c;这种系统包是已经在VMware虚拟机中安装好了的macOS系统。省去了繁琐的安装步骤与稍微漫长的等待时间。此次更新的包为诗林工作室制作的最新一个VMware系统包版本。分享给那些想快速体验macOS 14版本的朋友。 使用方…

C++ AVL树(旋转)

我们之前学习了搜索二叉树&#xff0c;我们知道普通的搜索二叉树会有特殊情况出现使得二叉树的两枝极其不平衡形成我们通俗说的歪脖子树&#xff1a; 这样的树一定会使得我们的增删查的效率变低&#xff1b;为了避免这种极端的情况出现&#xff0c;在1962年有两位伟大的俄罗斯数…

Unix消息队列实例

我们创建三个文件&#xff0c;一个recieve.c和pa.c,pb.c 。用recieve.c来监听pa.c和pb.c发送的消息&#xff1a; recieve.c代码&#xff1a; #include<t_stdio.h>#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <str…

数据库理论

什么是表空间 表空间是数据库的逻辑划分&#xff0c;一个表空间只能属于一个数据库。所有的数据库对象都存放在指定的表空间中。但主要存放的是表&#xff0c; 所以称作表空间。Oracle数据库中至少存在一个表空间&#xff0c;即SYSTEM的表空间。表空间不足怎么办 先查看Oracle数…

计算机断层扫描采集软件

计算机断层扫描采集软件&#xff0c;通过x采集2D和3D投影&#xff0c;利用投影可以进行体积的重建&#xff0c;软件还集成了CNC和x射线球管控制功能&#xff0c; 用PDM进程数据管理器对数据和进程进行管理&#xff0c;并对外提供与数据通信的接口 PDM通信基于AMQP&#xff0c…

Apple Vision Pro 的组成结构

Apple Vision Pro的组成结构相当复杂且精密,下面我将为您详细介绍其主要组成部分: 3D层压抛光玻璃面板与铝合金框架:Vision Pro的正面设计独特,类似于一副滑雪镜。它采用一块弧形的3D层压抛光玻璃面板,与定制的铝合金框架紧密结合。这个框架在用户的脸周围轻轻弯曲,以更好…

EasyExcel 复杂表头的导出(动态表头和静态表头)

问题&#xff1a;如图&#xff0c;1部分的表头是动态的根据日期变化&#xff0c;2部分是数据库对应的字段&#xff0c;静态不变的&#xff1b; 解决方案&#xff1a;如果不看1的部分&#xff0c;2部分内容可以根据实体类注解的方式导出&#xff0c;那么我们是不是可以先将动态表…

Centos7 安装 Oracle19c

下载oracle预安装包 wget http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm 下载19c安装包 https://www.oracle.com/cn/database/technologies/oracle-database-software-downloads.html#19c 选择…

Oracle 数据库工作中常用知识点:sql语法与常用函数

.to_date()函数 to_date函数是Oracle特有的函数&#xff0c;该函数用来做日期转换。 举例&#xff1a; SELECT TO_DATE(‘2006-05-01 19:25:34’, ‘YYYY-MM-DD HH24:MI:SS’) FROM DUAL   日期格式&#xff1a;     YYYY、YYY、YY 分别代表4位、3位、2位的数字年    …