c#界面中实现点云动态显示
c#界面中实现点云动态显示
我在之前的文章中介绍了关于C#界面中实现点云显示的解决方案,整个过程是基于c++开发的动态库实现的。
如果对本文即将介绍的C#实现点云实时显示感兴趣的可以先前往c#系统界面中可视化PCL点云数据简单了解一下实现的流程。
开发工具:PCL C# C++
在使用本文提供的方法前,需要掌握的知识点有:
1、C++ dll动态库的开发
2、PCL点云读取和点云显示
3、C#与C++动态库之间的调用
4、安装好可使用的PCL工具包
需要说明的是本文介绍的内容是将pcl实时显示的功能嵌入c#开发的软件中,相当于是上一篇文章的升级版。
开发流程(思路与上一篇类似)
0、首先系统启动时采用委托自动实例化dll中用于点云显示的模块(将显示位置的句柄传递给pcl显示窗口)
1、c#端选择提前准备好的点云文件(对于实时显示部分,本文是模拟激光雷达的数据。从指定的文件夹中读取提前采集好的数据然后存储起来,使用的时候读取的点云中一次输出)
2、数据读取完后返回存储数据位置的地址,这个地方是方便我们后期可以从C#端直接读取点云
3、实时显示:将数据的地址再次发送到dll中
代码实现
本文同样提供全套的可执行代码
源码地址:https://download.csdn.net/download/qq_43627520/85024460
有咨询方面的需求可通过邮箱与我联系:1499961892@qq.com
效果展示:
c#端
该部分与上一篇文章的差异:
1、增加了实时显示的功能区
2、在文件读取阶段增加了点云文件夹地址提取
委托部分结构没有变化,只是新增了一个句柄
IntPtr m_hwnd1 = (IntPtr)0;IntPtr m_hwnd2 = (IntPtr)0;// 点云界面初始化if (0 == type){if (pictureBox1.IsHandleCreated == true && pictureBox1.IsHandleCreated == true){m_hwnd1 = pictureBox1.Handle;m_hwnd2 = pictureBox2.Handle;dll_ShowPointCloud.EX_SysInit(m_hwnd1, m_hwnd2); //界面点云显示初始化}}
其中文件读取部分的代码如下:
private void button1_Click(object sender, EventArgs e){try{OpenFileDialog file = new OpenFileDialog();file.InitialDirectory = ".";file.Filter = "所有文件(*.*)|*.*";file.ShowDialog();if (file.FileName != string.Empty){pcdFile = file.FileName; //获得文件的绝对路径 pcdFile为选定的pcd文件路 也可以是ply文件pcdPath = Path.GetDirectoryName(file.FileName); //获取文件夹的路径 pcdPath是存储点云的文件夹路径Console.WriteLine("Path:" + pcdPath);label1.Text = pcdFile;int res = dll_ShowPointCloud.EX_PointCloud_Init(pcdFile,pcdPath);Console.WriteLine("returnPath:"+ DLL_ShowPointCloud.readFilePtrPath);if (res == 0){label2.Text = "点云读取完毕";}}}catch (Exception ex){MessageBox.Show(ex.Message);}}
点云显示动态库开发
在动态库这块相比于之前发生了一个较大的变化,因为涉及到实时显示,所以对整体实现的过程进行了调整。
动态库的调用接口
#define DLL_API extern"C" _declspec(dllexport)
#include "FlowPCLshow.hpp"
#include "pointProcess.hpp"
#include <boost/thread/thread.hpp># define POINTTYPE pcl::PointXYZIPointCloudProcess<POINTTYPE>* pointCloudProcess = NULL;PointCloudShowWindows<POINTTYPE>* pointCloudShowWindows = NULL;// 定义点云结构体
struct DataPointXYZI
{float x, y, z, i;
}dataPointXYZI;typedef struct DataPointCloud
{int size = 0;std::vector<DataPointXYZI> data;}dataPointCloud;//设置钩子函数
DLL_API int __stdcall EX_PCLSHOW_SetCallback(PCLSHOW_PResHook callback, int imode)
{try{pointCloudShowWindows->pCLSHOW_PResHook = callback;return 1;}catch (...){return 0;}
}//文件读取
void loadFile(std::string path, pcl::PointCloud<POINTTYPE>::Ptr cloud) {std::string fileType = path.substr(path.find_last_of('.') + 1);//获取文件后缀if (fileType == "ply") {if (pcl::io::loadPLYFile <POINTTYPE>(path, *cloud) == -1){std::cout << "Cloud reading .ply failed." << std::endl;}}else if (fileType == "pcd") {if (pcl::io::loadPCDFile <POINTTYPE>(path, *cloud) == -1){std::cout << "Cloud reading .pcd failed." << std::endl;}}//cout << "point cloud size:" << cloud->size() << endl;
}
//界面初始化
DLL_API int Sys_Init(HWND InitWindow, HWND INPUTWindow) {try {cout << "Sys_Init start" << endl;pointCloudShowWindows = new PointCloudShowWindows<POINTTYPE>();int ShowSR = pointCloudShowWindows->PCL_SHOW_Init((HWND)InitWindow); //初始化结果int input = pointCloudShowWindows->PCL_SHOW_INPUT((HWND)INPUTWindow); //初始化结果cout << "input end" << endl;return input;}catch (...) {return 0;}
}
// 点云显示动态库
DLL_API int PointCloud_Show(int itype) {try {if (1 == itype) {// 显示输入点云pointCloudShowWindows->PCL_Show_InitCloud();}else {//显示彩色点云pointCloudShowWindows->PCL_Show_PointCloud();}return 1;}catch (...) {return 0;}
}
// 设置的全局变量
std::vector<pcl::PointCloud<POINTTYPE>>* p;
pcl::PointCloud<POINTTYPE>::Ptr inputCloud(new pcl::PointCloud<POINTTYPE>);
std::vector<pcl::PointCloud<POINTTYPE>> data_cloud;
std::vector<pcl::PointCloud<POINTTYPE>> cloud_list;
int threadPclShowStop = 1;DLL_API std::vector<pcl::PointCloud<POINTTYPE>>* PointCloud_Init(char* filePathName, char* PathName) {//pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud(new pcl::PointCloud<pcl::PointXYZ>);cout << "filePathName:" << filePathName << endl;loadFile(filePathName, inputCloud);pointCloudShowWindows->PCL_SHOW_WinTypeSet();pointCloudShowWindows->PCL_Updata_InitCloud(inputCloud);data_cloud.push_back(*inputCloud);cout << "filePathName:" << filePathName << endl;pointCloudProcess = new PointCloudProcess<POINTTYPE>();if (PathName != "") {pointCloudProcess->PointCloudList(PathName);cloud_list = pointCloudProcess->pointCloudList;}pointCloudProcess->~PointCloudProcess();p = &cloud_list;cout << "ptr path:" << p << endl;return p;
}
//用于控制点云实时显示的中断过程
DLL_API int Thread_PclShow() {threadPclShowStop = 0;return threadPclShowStop;
}
//读取指定地址中的点云文件进行实时显示
DLL_API int LoadDataFromPtr(std::vector<pcl::PointCloud<POINTTYPE>>* Path) {cout << "LoadDataFromPtr:" << Path << endl;pcl::PointCloud<POINTTYPE> input;std::vector<pcl::PointCloud<POINTTYPE>> data;data = *Path;std::cout << "data size:" << data.size() << endl;threadPclShowStop = 1;int i = 0;while(1){if (threadPclShowStop == 0) {std::cout << "LoadDataFromPtr->input stop!" << endl;break;}input = data.at(i);pointCloudShowWindows->PCL_Updata_InputCloud(input.makeShared());pointCloudShowWindows->input_viewer->spinOnce(100);i++;if (i == data.size()) {//break;i = 0;}}threadPclShowStop = 1;return threadPclShowStop;
}
// 结束时释放点云显示空间
DLL_API int StopAllClass() {pointCloudShowWindows->~PointCloudShowWindows();return 1;
}
上述代码中涉及到的点云读取类 pointCloudProcess 的实现过程如下:
template<typename PointT>
PointCloudProcess<PointT>::PointCloudProcess()
{
}template<typename PointT>
PointCloudProcess<PointT>::~PointCloudProcess()
{
}
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr PointCloudProcess<PointT>::load_File(std::string filePath) {typename pcl::PointCloud<PointT>::Ptr cloud(new typename pcl::PointCloud<PointT>);std::string fileType = filePath.substr(filePath.find_last_of('.') + 1);//获取文件后缀if (fileType == "ply") {if (pcl::io::loadPLYFile <PointT>(filePath, *cloud) == -1){std::cout << "Cloud reading .ply failed." << std::endl;}}else if (fileType == "pcd") {if (pcl::io::loadPCDFile <PointT>(filePath, *cloud) == -1){std::cout << "Cloud reading .pcd failed." << std::endl;}}cout << "point cloud size:" << cloud->size() << endl;return cloud;
}
//获取所有的数据
template<typename PointT>
std::vector<typename pcl::PointCloud<PointT>> PointCloudProcess<PointT>::PointCloudList(std::string dataPath)
{std::vector<std::string> pathList = getFilesList(dataPath);typename pcl::PointCloud<PointT>::Ptr loadCloud(new typename pcl::PointCloud<PointT>);for (int i = 0; i < pathList.size(); i++) {std ::string file = pathList[i];loadCloud = load_File(file);pointCloudList.push_back(*loadCloud);}return pointCloudList;
}
/** 读取文件夹数据*/
template<typename PointT>
std::vector<std::string> PointCloudProcess<PointT>::getFilesList(std::string Path) {std::string PathList = Path + "/*.*";std::vector<std::string> allFilePath;intptr_t handle;_finddata_t findData;handle = _findfirst(PathList.c_str(), &findData);//检测是否成功if (handle == -1) {cout << "can not found the file ... " << endl;return allFilePath;}do{if (findData.attrib & _A_SUBDIR) //是否含有子目录{//若该子目录为"."或"..",则进行下一次循环,否则输出子目录名,并进入下一次搜索if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)continue;// 在目录后面加上"\\"和搜索到的目录名进行下一次搜索std::string dirNew = Path + "/" + findData.name;std::vector<std::string> tempPath = getFilesList(dirNew);allFilePath.insert(allFilePath.end(), tempPath.begin(), tempPath.end());}else //不是子目录,即是文件,则输出文件名和文件的大小{std::string filePath = Path + "/" + findData.name;allFilePath.push_back(filePath);cout << filePath << "\t" << findData.size << " bytes.\n";}} while (_findnext(handle, &findData) == 0);return allFilePath;
}
为了使我们写的函数可以适用于不同数据类型的点云(xyz,xyzi,xyzrgb),我们使用了template<typename PointT>
来定义类中点云的数据类型
点云显示
在上一篇文章的基础上新增了一个点云初始化的窗口
// 用于更新实时显示的点云
template<typename PointT>
int PointCloudShowWindows<PointT>::PCL_Updata_InputCloud(typename pcl::PointCloud<PointT>::Ptr Cloud) {Input_cloud.reset(new typename pcl::PointCloud<PointT>);Input_cloud->resize(Cloud->size());Input_cloud = Cloud;pcl::visualization::PointCloudColorHandlerGenericField<PointT> fildColor(Input_cloud, "z"); // 按照x字段进行渲染input_viewer->removeAllPointClouds();input_viewer->addPointCloud<PointT>(Input_cloud, fildColor, "sample"); // 显示点云,其中fildColor为颜色显示return 0;
}
//初始化实时显示点云的窗口
template<typename PointT>
int PointCloudShowWindows<PointT>::PCL_SHOW_INPUT(HWND InputCloudDispWindow)
{try{input_viewer.reset(new pcl::visualization::PCLVisualizer("Input_Viewer", false));//初始化viewer对象//m_viewer->setShowFPS(false);input_viewer->addCoordinateSystem(1.0);input_viewer->setBackgroundColor(0, 0, 0);//设置背景颜色input_viewer->initCameraParameters();//初始化相机的参数input_viewer_win = input_viewer->getRenderWindow();//将view中的渲染窗口的句柄传递给vtk windowinput_viewer_iren = vtkRenderWindowInteractor::New();//初始化vtkwindow交互的对象input_viewer->resetCamera();//使点云显示在屏幕中间,并绕中心操作RECT Input_Window;::GetClientRect(InputCloudDispWindow, &Input_Window);input_viewer_i_ui_w = Input_Window.right - Input_Window.left;input_viewer_i_ui_h = Input_Window.bottom - Input_Window.top;input_viewer_win->SetSize(input_viewer_i_ui_w, input_viewer_i_ui_h);//根据当前窗口的大小设置vtk 窗口的大小//m_win->SetSize(300, 300);//根据当前窗口的大小设置vtk 窗口的大小input_viewer_win->SetParentId(InputCloudDispWindow);//设置vtk窗口的句柄//input_viewer_iren->SetRenderWindow(input_viewer_win);//将vtk交互对象与vtk window绑定input_viewer->createInteractor();input_viewer_win->Render();//开始渲染return 1;}catch (...){return 0;}}template<typename PointT>
int PointCloudShowWindows<PointT>::PCL_SHOW_WinTypeSet() {Init_viewer->setCameraPosition(11.6749, 17.4117, 27.2977, -0.404992, -0.6874, 0.602879);Init_viewer->setCameraClipDistances(0.160147, 160.147);input_viewer->setCameraPosition(11.6749, 17.4117, 27.2977, -0.404992, -0.6874, 0.602879);input_viewer->setCameraClipDistances(0.160147, 160.147);return 0;
}
template<typename PointT>
int PointCloudShowWindows<PointT>::PCL_Show_InitCloud()
{try{Init_viewer->removeAllPointClouds();//将前一次点云移除pcl::visualization::PointCloudColorHandlerGenericField<PointT> fildColor(Init_cloud, "z"); // 按照x字段进行渲染Init_viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample"); // 用于改变显示点云的尺寸。用户可以利用该方法控制点云在视窗中的显示方式。Init_viewer->addPointCloud<PointT>(Init_cloud, fildColor, "sample"); // 显示点云,其中fildColor为颜色显示Init_viewer->spinOnce();return 1;}catch (...){return 0;}
}
最终效果
C#窗体实时显示点云
c#界面中实现点云动态显示相关推荐
- 百度云同盘在计算机显示不出来的,wps网盘图标消失了如何让其显示在“我的电脑”界面中...
wps网盘图标消失了如何让其显示在"我的电脑"界面中 不知道大家有没有遇到过明明安装了wps却没显示器图标的情况,今天小编就告诉大家wps网盘图标消失了如何让其显示在"我 ...
- 禾赛40M如何成功在rviz中显示点云数据
禾赛40M如何成功在rviz中显示点云数据 文章目录 禾赛40M如何成功在rviz中显示点云数据 前言 一.安装雷达的ROS驱动包 二.启动雷达 三.启动rviz查看点云 1.启动launch文件与r ...
- pycharm中配置华为云服务器
之前上课老师给了华为云的代金券,实在用不惯网页版的python编辑器,而且文件同步很麻烦,检索全网也没有怎么将华为云服务器配置到pycharm的说明.于是,摸索了一会,记录下配置流程,供大家参考使用. ...
- 部署CentOS可视化界面GUI-之腾讯云服务器
目录 一.购买云服务器实例 二.配置安全组.设置管理员密码 三.远程登录 四.安装CentOS可视化界面GUI 4.1.系统GUI配置 4.2.系统GUI配置 五.GUI或Console之间的界面切换 ...
- [施工中]Java阿里云服务器ECS建站操作不完全指北
[施工中]Java阿里云服务器ECS建站操作不完全指北 ECS建站操作记录 前言 一 .Xshell6与Xftp6 1.1Xshell与Xftp的作用 1.2如何从官网下载xshell与xftp 1. ...
- 怎样在计算机里恢复云文档图标,电脑常识科普:Win10资源管理器中的WPS云文档图标怎么彻底删除...
如今我们的生活当中不仅仅是办公会实用到电脑,我们日常当中很多时候都需要电脑来帮助我们解决一些问题,那么在使用电脑的时候肯定就会遇到各种各样的问题,那么我们应该怎么去解决这些问题呢?那么这个时候我们就需 ...
- 整合Tkinter GUI界面的古诗词词云生成
Python语言提供的wordcloud词云功能,使文本数据的可视化,简单而美丽.但网上的大多数词云生成功能,多半没有可交互的GUI界面,使用起来稍觉不便.笔者结合网上的中文词云功能,以唐诗三百首,宋 ...
- 关于在python的tkinter界面中镶嵌mayplotlib动态图
关于在python的tkinter界面中镶嵌mayplotlib动态图 很多的时候,我们需要给客户展示一些比较美观的界面,中间就必然需要一些精美的图表,让客户看起来更加的专业,因此,我们就需要tkin ...
- Gox语言中进行屏幕截图并显示在Sciter图形界面中-GX38.2
本例承接GX38.1一文中的例子,加了一些改进,在进行界面截图后,将图片展示在用Sciter包编写的图形界面上. 代码如下: // 设置github.com/kbinani/screenshot包的简 ...
最新文章
- Insert Interval
- golang goroutine的调度模型:MPG模式
- AI产业化应用落地,飞桨三大服务平台帮你开启加速模式
- java数据类型及其说明
- c++ winpcap开发(8)
- .Net的 Web项目的打包过程
- 问题记录——sqlserver视图重命名的陷阱
- SSL 3.0曝出Poodle漏洞的解决方案-----开发者篇(转自:http://blog.csdn.net/lyq8479/article/details/40709175)...
- SQL 2005数据库函数基本应用
- UVA722 LA5359 Lakes【DFS】
- 如何自定义安装mysql_安装MySQL
- Landsat8—ANG.txt文件
- geotoolkit 测井曲线显示时间、深度双刻度
- 如何识别服务器网站有病毒,网站有病毒怎么解决?
- Tableau安装详解及密钥申请
- c#中regex的命名空间_C# Regex类用法
- R实战 | 环状热图(circos)
- 夜神模拟器adb连接电脑
- 2022年贵州二级建造师建设工程法规及相关知识模拟题及答案
- JAVA团队开发手册 - 1.环境搭建