当前位置: 首页 > news >正文

VS 2022,配置PCL 1.12.0,C#使用C++/CLI调用

总体思路:

  1. 安装PCL的安装包,包括依赖项;
  2. 配置系统的环境变量;
  3. 配置VS中项目的环境变量,Debug和Release都要配置;
  4. 然后才可以使用PCL库;

■下载PCL安装包

首先去 https://github.com/PointCloudLibrary/pcl/releases 下载点云库的安装包,我们需要的是AllInOne和pdb两个包。我下载的是1.12.0版本,如下图所示。

在这里需要根据自己机器的情况下载相应的版本(操作系统的位数,以及Visual Studio的版本)。我这里选择PCL-1.12.0-AllInOne-msvc2019-win64.exe(这是预编译的安装文件)和pcl-1.12.0-pdb-msvc2019-win64.zip(PDB文件,后期单步调试用)两个文件(这个也可以安装在VS2022上)。

下载结束之后,运行我们下载得到的PCL-1.12.0-AllInOne-msvc2019-win64.exe文件进行安装。下面几幅图显示出了几个必要的步骤,未做说明的步骤直接下一步或者根据自己的喜好配置即可。

■安装PCL

接下来点击安装便可以开始漫长的安装过程。安装主要是把对应的PCL库文件解压到指定的目录,同时安装第三方依赖项。

安装后,约2G,可以更改安装路径,放在其他盘中。

一段时间之后,会弹出来一个OpenNI2的安装窗口,它是一个依赖包,此时直接一路下一步就好,但是一定要记住自己设置的安装路径。有时没有弹出来,自动安装到C:\Program file目录中,安装的过程中会把所有的第三方库(除OpenNI2之外)全部安装在点云安装目录下的3rdparty文件夹里。因此,为了保持文件夹的整洁,便于调用,要卸载后重新安装。

首先进入E:\ PCL 1.12.0\3rdParty \OpenNI2,这里存放了安装包,双击安装包,如果让提示安装,就安装,如果已安装,出现下面的画面,选卸载,即从默认的C:\Program file里卸载。

然后重新安装,把安装目录设置成PCL的主目录的3rdparty文件夹里,即E:\PCL 1.12.0\3rdParty\OpenNI2。

安装后,OpenNI2的目录如下类似:

OpenNI2安装结束之后就完成了点云库的完整安装,安装目录下的样子和3rdparty文件夹下的样子如下图:

 

可以看到,所有的第三方库全部安装到了3rdparty文件夹中。

1、 Boost库,用于共享指针和线程操作,必需。

2、 Eigen库,用于矩阵、向量等数据操作,必需。

3、 FLANN库,在kd树模块中用于快速近邻搜索,必需。

4、 OpenNI版本,用于与OpenNI兼容的设备获取点云,可选。

5、 QHull库,用于凸或凹曲面的外包求解,可选。

6、 VTK(Visualization ToolKit)库,用于在可视化模块中用于3D点云渲染和可视化,必需。

解压pcl-1.12.0-pdb-msvc2019-win64.zip,将得到的pdb文件全部复制到:E:\PCL 1.12.0\bin中。

如果安装中出现下面的报警,表示字符数量超过了系统环境变量长度的要求。表示有一部分路径设置失败,就需要手动设置。

■系统环境变量配置

环境变量配置

点云库安装完成之后,还有一个比较重要的步骤,就是配置Windows的环境变量。

右键点击此电脑(我的电脑,计算机,这台电脑等名字),选择属性,接着点击左侧的高级系统设置,然后选择高级选项卡,点击下面的环境变量…按钮,此时便打开了环境变量的配置窗口。

此时,我们可以看到PCL的根目录以及OpenNI2的目录已经添加到了系统变量中。这只是一部分,还需要完整设置。

注意,由于我们在安装完毕后把OpenNI2放在3rdparty文件夹里,因此我们需要将OPENNI2_REDIST64的系统路径修改为E:\PCL 1.12.0\3rdParty\OpenNI2。改之前的路径是在C盘。

然后,我们双击系统变量中的Path,再将以下的目录添加到Path中(注意最后一个OpenNI2的路径,要和自己刚刚安装的路径一样才行),:

%PCL_ROOT%\bin

%PCL_ROOT%\3rdParty\VTK\bin

%PCL_ROOT%\3rdParty\FLANN\bin

%OPENNI2_REDIST64%

%PCL_ROOT%\3rdParty\Qhull\bin

%PCL_ROOT%\3rdParty\OpenNI2\Tools

以上步骤搞定之后,重启电脑来应用环境变量。这一步我没有做,也可以生效。

Visual Studio开发环境配置

Visual Studio提供了两种编译模式:Debug和Release。Debug模式下,生成的应用程序中会插入许多的调试指令,因此调试起来及其方便,但是大幅度降低了程序的运行速度;Release模式便会提高程序的速度,但是调试相对较困难一些。本教程将对两种模式分别进行配置,适应不同的需求。

在VS中新建一个CLR C++类库项目,用来封装PCL库,便于C#来调用。

接下来,配置工程的属性管理器。

我们先来配置Debug模式。点击该窗口左侧的VC++ 目录,然后点击右侧的包含目录右侧的下拉菜单,选择编辑…,将以下目录填入窗口中:

E:\PCL 1.12.0\3rdParty\Boost\include\boost-1_76

E:\PCL 1.12.0\3rdParty\Eigen\eigen3

E:\PCL 1.12.0\3rdParty\FLANN\include

E:\PCL 1.12.0\3rdParty\Qhull\include

E:\PCL 1.12.0\3rdParty\VTK\include\vtk-9.0

E:\PCL 1.12.0\include\pcl-1.12

E:\PCL 1.12.0\3rdParty\OpenNI2\Include

注意:这里的E:\PCL 1.12.0是刚刚安装点云库的路径,根据刚刚安装点云的路径进行修改。同时还要注意高亮字体的版本问题。要试一下是否每个路径都可以打开,不同的PCL版本可能有差别。配置好之后点击确定即可。

然后点击右侧的库目录右侧的下拉菜单,选择编辑…,将以下目录填入窗口中:

E:\PCL 1.12.0\lib

E:\PCL 1.12.0\3rdParty\Boost\lib

E:\PCL 1.12.0\3rdParty\FLANN\lib

E:\PCL 1.12.0\3rdParty\Qhull\lib

E:\PCL 1.12.0\3rdParty\VTK\lib

E:\PCL 1.12.0\3rdParty\OpenNI2\Lib

同样需要注意路径问题,配置好之后点击确定即可。

然后点击属性页中的C/C++下的预处理器,点击右侧的预处理器定义右侧的下拉菜单,选择编辑…,添加如下两条定义:(这两条不懂什么意思,很多教程也用别的,这个可能是个坑,编译报错可能和这个有关,目前还没搞懂,学习中)

_SCL_SECURE_NO_WARNINGS

_CRT_SECURE_NO_WARNINGS

然后再点击预编译头,将右侧的预编译头设置为不使用预编译头。这个设置可以依据自己的习惯决定,可以省略。如果使用编译头,要自己比较熟悉如何操作,如果不熟悉,就不使用。

接着点击属性页中的链接器下的输入,点击右侧的附加依赖项右侧的下拉菜单,选择编辑…,将pcl和3rdParty相关lib文件填写到窗口中:(注意:Debug模式下的lib和Release里面的lib必须输入不同的lib,不能混在一起,否则程序运行,会报内存有关的各种错误,还有link链接错误之类的)


 

这时,点击确定,我们在Debug模式下的点云开发环境就配置完成了。去网上找个实例代码粘贴,如果成功编译运行就代表配置成功了。

接下来说一下Release模式的配置。Release模式的配置和Debug模式一模一样,除了附加依赖项。两个模式必须都要配置,否则会报莫名其妙的错误,这里说一句,NND PCL。

这样,我们的Debug模式和Release模式就全部配置完成了。

■CLR项目编程

   新建一个CLR项目,新建一个头文件PclProcessor‌.h,内容如下:

#pragma once

#include <pcl/point_types.h>

#include <pcl/point_cloud.h>

#include <pcl/filters/passthrough.h>

#include <pcl/sample_consensus/ransac.h>

#include <pcl/sample_consensus/sac_model_line.h>

#include <msclr/marshal_cppstd.h>

using namespace System;

using namespace System::Collections::Generic;

namespace PclBridge {

    public ref class PclProcessor {

    public:

        // 处理点云数据并返回直线参数

        List<float>^ ProcessPointCloud(List<System::Numerics::Vector2>^ points);

    };

}

新建一个cpp文件,内容如下:

#include "PclProcessor‌.h"

#include <msclr/marshal_cppstd.h>

#include <pcl/common/common.h>

using namespace pcl;

using namespace msclr::interop;

using namespace System::Numerics;

namespace PclBridge {

    // 非托管部分: 执行 PCL 库的算法(滤波、RANSAC 等)

    void ProcessPointCloudNative(std::vector<Eigen::Vector2f>& points, std::vector<float>& result)

    {

        PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);

        for (auto& pt : points) {

            cloud->push_back(PointXYZ(pt.x(), pt.y(), 0.0f)); // 将 Vector2 转为 PointXYZ

        }

        // 1. 直通滤波(X轴范围切割)

        pcl::PassThrough<PointXYZ> pass;

        pass.setInputCloud(cloud);

        pass.setFilterFieldName("x");

        pass.setFilterLimits(-5.0, 5.0); // 根据实际雷达范围调整

        pass.filter(*cloud);

        // 2. RANSAC 直线拟合(2D 数据需投影到 XY 平面)

        pcl::SampleConsensusModelLine<PointXYZ>::Ptr model(new pcl::SampleConsensusModelLine<PointXYZ>(cloud));

        pcl::RandomSampleConsensus<PointXYZ> ransac(model);

        ransac.setDistanceThreshold(0.05); // 设置距离阈值(单位:米)

        ransac.computeModel();

        // 获取直线参数 ax + by + c = 0 

        Eigen::VectorXf coefficients;

        ransac.getModelCoefficients(coefficients);

        // 提取方向向量和一个点,计算直线方程

        float dir_x = coefficients[3];

        float dir_y = coefficients[4];

        float point_x = coefficients[0];

        float point_y = coefficients[1];

        // 计算直线方程的系数 a, b, c

        float a = dir_y;

        float b = -dir_x;

        float c = dir_x * point_y - dir_y * point_x;

        result.push_back(a);

        result.push_back(b);

        result.push_back(c);

    }

    // 托管部分: 将 C# List<Vector2> 转为 C++ 的 std::vector,并调用非托管代码

    List<System::Single>^ PclProcessor::ProcessPointCloud(List<System::Numerics::Vector2>^ points)

    {

        // 转换 C# 点云 List<Vector2> 到 std::vector<Eigen::Vector2f>

        std::vector<Eigen::Vector2f> nativePoints;

        for each (Vector2 pt in points) {

            nativePoints.push_back(Eigen::Vector2f(pt.X, pt.Y));

        }

        执行非托管处理

        std::vector<float> nativeResult;

        ProcessPointCloudNative(nativePoints, nativeResult);

        // 将结果转换回托管 List<System::Single>

        List<System::Single>^ result = gcnew List<System::Single>();

        for (float val : nativeResult) {

            result->Add(val);

        }

        return result;

    }

}

因为要在CLR项目中使用断点调试,需要确认符号文件(PDB)生成‌:

确认 PclBridge 项目的属性中已生成 PDB 文件:

代码优化关闭‌:
确保 PclBridge 的代码优化已禁用(避免断点失效):

如果出现无法查找ntdll.pdb 之类的报警(可能有问题):

■C#项目编程

目标平台默认为AnyCPU,可能系统自动选择了AMD64,为了避免不一致,统一选为x64.

在C#项目属性这里打勾,启用混合调试,这样就可以在C++/CLI项目中使用断点了。

  public void ProcessData(List<Vector2> points)

  {

      // 调用 PCL 处理

      List<float> coefficients = _processor.ProcessPointCloud(points);

      // 解析直线参数 ax + by + c = 0

      float a = coefficients[0];

      float b = coefficients[1];

      float c = coefficients[2];

      // 计算雷达中心点到直线的距离和角度

      Vector2 radarCenter = new Vector2(0, 0); // 假设雷达中心在原点

      float distance = (a * radarCenter.X + b * radarCenter.Y + c) / MathF.Sqrt(a * a + b * b);

      float angle = MathF.Atan2(b, a) * (180 / MathF.PI);

      // 更新 UI 或日志

      Console.WriteLine($"距离: {distance}, 角度: {angle}°");

  }

相关文章:

  • Spring Boot 3.4.3 基于 SpringDoc 2 和 Swagger 3 实现项目接口文档管理
  • C++26 编译时反射简介
  • 0101数学_算法-常用符号-常用模板.md
  • stm32week9
  • 【Es】基础入门:开启全文搜索的大门
  • 数据结构每日一题day4(顺序表)★★★★★
  • conda的基础命令
  • VLAN的高级特性
  • 苹果与安卓,鸿蒙下跨设备,应用分享
  • Matlab_Simulink中导入CSV数据与仿真实现方法
  • 基于Spring Boot的木里风景文化管理平台的设计与实现(LW+源码+讲解)
  • 1.2 斐波那契数列模型:LeetCode 面试题 08.01. 三步问题
  • 【NLP】13. NLP推理方法详解 --- 穷举和贪心搜索
  • Hyperlane 框架的临时上下文数据功能:助力高效 Web 开发
  • NoSQL数据库
  • JS 手撕题高频考点
  • MATLAB详细图文安装教程(附安装包)
  • 域渗透(web安全)
  • 归并排序与快速排序的简单实现(C语言)
  • 前端自动创建react项目脚手架
  • 在哪些网站做收录比较快/今天发生的重大新闻5条
  • 西安网站建设排行榜/sem工资
  • 网站备案是域名备案还是服务器备案/知乎小说推广对接平台
  • 在上海做网站/产品市场营销策划方案
  • 郴州企业网站建设制作/湖南专业关键词优化
  • 福州网站制作有限公司/360优化大师旧版本