• 鬼影、雨雪天气点云噪声处理


    雨雪天气点云噪声处理

    在雨雪天气中,点云噪声可能来自以下几个方面:

    1. 雨滴、雪花等降水物体对激光雷达的反射造成的干扰;
    2. 湿度、温度等气象因素对激光雷达的影响;
    3. 环境中的遮挡物或反射体造成的多次反射或回波。

    为解决点云噪声问题,可以考虑以下处理算法:

    1. 点云过滤:通过高斯滤波、中值滤波等方式去除噪声点;
    2. 点云降采样:对点云进行降采样处理,将稠密的点云数据变为稀疏的点云数据,减少噪声的数量;
    3. 反射强度滤波:通过设定反射强度阈值,过滤掉反射强度较低的点;
    4. 平面分割:将点云分割成不同的平面,过滤掉非平面的噪声点;
    5. 可视化筛选:通过可视化工具,手动筛选出噪声点。

    以下是一个简单的雨水、雪花等噪声点云处理的算法和对应的C++代码:

    算法步骤:

    1. 从点云中提取出每个点的法向量。
    2. 对于每个点,计算其与其周围点的法向量的差异。如果法向量差异较大,则将其标记为噪声点。
    3. 对于标记为噪声点的点,将其删除或用其周围的点进行替换。

    C++代码实现:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main (int argc, char** argv)
    {
      // 读取点云
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
      pcl::PCDReader reader;
      reader.read ("input_cloud.pcd", *cloud);
    
      // 下采样滤波
      pcl::PointCloud<pcl::PointXYZ>::Ptr downsampled_cloud (new pcl::PointCloud<pcl::PointXYZ>);
      pcl::VoxelGrid<pcl::PointXYZ> sor;
      sor.setInputCloud (cloud);
      sor.setLeafSize (0.1f, 0.1f, 0.1f);
      sor.filter (*downsampled_cloud);
    
      // 计算法向量
      pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
      pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
      ne.setInputCloud (downsampled_cloud);
      pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
      ne.setSearchMethod (tree);
      ne.setRadiusSearch (0.5);
      ne.compute (*normals);
    
      // 标记噪声点
      pcl::PointCloud<pcl::PointXYZ>::Ptr denoised_cloud (new pcl::PointCloud<pcl::PointXYZ>);
      float threshold = 0.5;
      for (int i = 0; i < downsampled_cloud->size (); ++i)
      {
        pcl::PointXYZ point = downsampled_cloud->points[i];
        pcl::Normal normal = normals->points[i];
        pcl::PointXYZ neighbor_point;
        bool neighbor_found = false;
        for (int j = 0; j < downsampled_cloud->size (); ++j)
        {
          if (i == j)
            continue;
          neighbor_point = downsampled_cloud->points[j];
          pcl::Normal neighbor_normal = normals->points[j];
          float normal_diff = acos (normal.normal_x * neighbor_normal.normal_x +
                                    normal.normal_y * neighbor_normal.normal_y +
                                    normal.normal_z * neighbor_normal.normal_z);
          if (normal_diff > threshold)
          {
            neighbor_found = true;
            break;
          }
        }
        if (!neighbor_found)
          denoised_cloud->push_back (point);
      }
    
      // 保存结果
      pcl::PCDWriter writer;
      writer.write<pcl::PointXYZ> ("denoised_cloud.pcd", *denoised_cloud, false);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    这里使用了PCL库,需要安装和配置好PCL库才能编译运行。代码中的注释应该可以帮助你理解如何实现这一算法。


    在雨雪天气中,点云噪点通常是由于雨滴或雪花的撞击和反射造成的,它们会被误认为是点云数据中的有效点。

    处理点云噪点的一种方法是使用统计学滤波器,例如高斯滤波器、中值滤波器或平均值滤波器。这些滤波器都可以根据周围点云数据的统计信息来过滤掉噪点。

    以下是一个简单的cpp代码示例,使用PCL库中的统计学滤波器来过滤点云中的噪点:

    #include 
    #include 
    #include 
    
    int main(){
      // 创建点云对象
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    
      // 从文件中读取点云数据
      pcl::io::loadPCDFile<pcl::PointXYZ> ("input_cloud.pcd", *cloud);
    
      // 创建统计学滤波器
      pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
      sor.setInputCloud (cloud);
      sor.setMeanK (50); // 设置在计算统计信息时使用的邻域点的数量
      sor.setStddevMulThresh (1.0); // 设置标准偏差的乘数阈值
      sor.filter (*cloud_filtered); // 应用滤波器
    
      // 将过滤后的点云数据保存到文件中
      pcl::io::savePCDFile ("output_cloud.pcd", *cloud_filtered);
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在上面的代码中,输入点云数据存储在名为“input_cloud.pcd”的文件中,滤波后的点云数据存储在名为“output_cloud.pcd”的文件中。可以根据需要修改统计学滤波器的参数来达到更好的滤波效果。


    雨雪天气可能会引起点云中的噪点,这是由于水滴或雪花落在激光扫描器上,会干扰激光扫描器的测量。这些干扰信号会被误认为是点云中的物体,从而产生噪声点。

    为了处理这种噪声,通常采用以下算法:

    1. 空间过滤:通过对点云数据进行距离过滤,删除与相邻点距离过大的点。这种方法可以有效地去除孤立的噪点。

    2. 时间过滤:通过比较连续两帧点云之间的相似性,删除在两帧之间变化较大的点。这种方法适用于在静态背景下的运动物体。

    3. 自适应高斯滤波:采用高斯滤波器对点云进行滤波,较短的滤波器窗口用于去除小的噪声,较长的滤波器窗口用于保留点云中的大型结构和物体。

    4. 统计滤波:采用统计方法对点云进行滤波,去除与平均值相差过大的点。这种方法适用于非常密集的点云数据。

    关于CPP实现,您可以使用点云处理库如PCL (Point Cloud Library) 或Open3D。这些库中包含了许多现成的点云滤波算法。您可以在网上找到许多相关的代码示例,这里提供一个使用PCL库的示例代码:

    #include  // 空间过滤
    #include  // 深度过滤
    #include  // 统计滤波
    #include  // 半径滤波
    
    pcl::PointCloud::Ptr noisy_cloud (new pcl::PointCloud);
    pcl::PointCloud::Ptr filtered_cloud (new pcl::PointCloud);
    
    // 加载点云数据
    pcl::io::loadPCDFile ("noisy_cloud.pcd", *noisy_cloud);
    
    // 定义空间过滤器
    pcl::VoxelGrid sor;
    sor.setInputCloud (noisy_cloud);
    sor.setLeafSize (0.01f, 0.01f, 0.01f);
    sor.filter (*filtered_cloud);
    
    // 定义深度过滤器
    pcl::PassThrough passthrough;
    passthrough.setInputCloud (filtered_cloud);
    passthrough.setFilterFieldName ("z");
    passthrough.setFilterLimits (0.0, 1.0);
    passthrough.filter (*filtered_cloud);
    
    // 定义统计滤波器
    pcl::StatisticalOutlierRemoval sor;
    sor.setInputCloud (filtered_cloud);
    sor.setMeanK (50);
    sor.setStddevMulThresh (1.0);
    sor.filter (*filtered_cloud);
    
    // 定义半径滤波器
    pcl::RadiusOutlierRemoval ror;
    ror.setInputCloud (filtered_cloud);
    ror.setRadiusSearch (0.1);
    ror.setMinNeighborsInRadius (10);
    ror.filter (*filtered_cloud);
    
    // 保存处理后的点云数据
    pcl::io::savePCDFile ("filtered_cloud.pcd", *filtered_cloud);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    以上是一个简单的点云滤波处理示例,其中包含了空间过滤、深度过滤、统计滤波和半径滤波。您可以根据需要进行修改和调整,以适应您的应用场景。

    鬼影现象

    点云中的鬼影现象通常指的是由于激光雷达扫描时产生的多次反射和强度变化所导致的噪点或伪影。这些噪点可能会干扰点云的质量和精度,因此需要进行一些预处理或滤波来消除它们。

    常见的处理算法包括:

    1. 点云降噪:使用滤波器或聚类算法来删除噪点或稀疏的数据点;

    2. 点云平滑:使用平滑算法来平滑点云中的噪点或伪影;

    3. 点云配准:通过配准算法来将多个点云数据融合到一起,从而减少噪点和伪影;

    4. 点云分割:对点云中不同对象进行分割和分类,以减少噪点和伪影的影响。

    对于这些算法的CPP实现,可以使用开源库如PCL(点云库)或OpenCV(计算机视觉库)来实现。这些库提供了许多现成的滤波器、聚类算法、平滑算法和配准算法,方便用户进行点云数据处理。


    点云中的鬼影现象指的是在点云数据中出现重影或重叠部分的现象。这可能是由于激光雷达扫描重叠区域的多次反射导致的。这种现象使得点云数据变得混乱,影响后续的点云分析和处理。因此,需要对鬼影进行去除处理。

    鬼影消除算法通常涉及以下步骤:

    1. 根据激光雷达扫描的特性,将点云数据分割为不同的组或子区域。

    2. 同一组或子区域内的点云数据进行配准,以去除重影,通常使用ICP(Iterative Closest Point)算法或其他配准算法。

    3. 使用点云滤波算法,如高斯滤波或中值滤波等消除噪声。

    4. 将处理过的点云数据重新组合。

    以下是一个基于PCL库实现的C++示例代码,用于去除鬼影:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char** argv)
    {
        pcl::PointCloud::Ptr cloud_in(new pcl::PointCloud);
        pcl::PointCloud::Ptr cloud_out(new pcl::PointCloud);
    
        pcl::io::loadPCDFile("input.pcd", *cloud_in);
    
        // 分割点云
        pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud);
        pcl::PassThrough pass;
        pass.setInputCloud(cloud_in);
        pass.setFilterFieldName("z");
        pass.setFilterLimits(0.0, 1.0);
        pass.filter(*cloud_filtered);
    
        // Voxel降采样
        pcl::VoxelGrid sor;
        sor.setInputCloud(cloud_filtered);
        sor.setLeafSize(0.01f, 0.01f, 0.01f);
        sor.filter(*cloud_out);
    
        // 配准
        pcl::IterativeClosestPoint icp;
        icp.setInputSource(cloud_out);
        icp.setInputTarget(cloud_in);
        pcl::PointCloud::Ptr Final (new pcl::PointCloud);
        icp.align(*Final);
    
        pcl::io::savePCDFileASCII("output.pcd", *Final);
    
        return (0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    以上代码将输入的点云数据分割为高度为0到1的区域,然后使用Voxel降采样和ICP算法进行处理。最后,将处理过的点云数据保存到输出文件中。您可以根据需要自行调整参数以获得更好的结果。

  • 相关阅读:
    C++ LibCurl 库的使用方法
    AJAX学习第一章
    50、OAK的VideoEncoder节点编码h265和使用ffmpeg进行解码播放
    java 程序员工作问题
    Javascript 常见的循环方式总结
    源代码保密软件分析选型
    中小企业的公司财务管理系统
    武汉凯迪正大—高压信号发生器
    海量数据去重的hash,bitmap与布隆过滤器Bloom Filter
    跨境电商背景下,DolphinScheduler 在 SHEIN 的二开实践
  • 原文地址:https://blog.csdn.net/qq_39506862/article/details/130913339