【PCL】(十七)从距离图像中提取点云的边界

news2024/11/15 9:35:34

(十七)从测距图像中提取边界

Object(Obstacle) border:属于物体的最外面的可见点;

Shadow border:背景中与物体相邻的点;

Veil points:Object border和Shadow border之间的插值点。

以下代码实现将点云投影为距离图像,然后再从距离图像中提取点云的边界。

range_image_border_extraction.cpp

/* \author Bastian Steder */
#include <iostream>
#include <pcl/range_image/range_image.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/range_image_visualizer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/features/range_image_border_extractor.h>
#include <pcl/console/parse.h>
#include <pcl/common/file_io.h> // for getFilenameWithoutExtension

typedef pcl::PointXYZ PointType;

// --------------------
// -----Parameters-----
// --------------------
float angular_resolution = 0.5f;
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
bool setUnseenToMaxRange = false;

// --------------
// -----Help-----
// --------------
void printUsage (const char* progName)
{
  std::cout << "\n\nUsage: "<<progName<<" [options] <scene.pcd>\n\n"
            << "Options:\n"
            << "-------------------------------------------\n"
            << "-r <float>   angular resolution in degrees (default "<<angular_resolution<<")\n"
            << "-c <int>     coordinate frame (default "<< (int)coordinate_frame<<")\n"
            << "-m           Treat all unseen points to max range\n"
            << "-h           this help\n"
            << "\n\n";
}

// --------------
// -----Main-----
// --------------
int main (int argc, char** argv)
{
      // --------------------------------------
      // -----Parse Command Line Arguments-----
      // --------------------------------------
      if (pcl::console::find_argument (argc, argv, "-h") >= 0)
      {
            printUsage (argv[0]);
            return 0;
      }
      if (pcl::console::find_argument (argc, argv, "-m") >= 0)
      {
            setUnseenToMaxRange = true;
            std::cout << "Setting unseen values in range image to maximum range readings.\n";
      }
      int tmp_coordinate_frame;
      if (pcl::console::parse (argc, argv, "-c", tmp_coordinate_frame) >= 0)
      {
            coordinate_frame = pcl::RangeImage::CoordinateFrame (tmp_coordinate_frame);
            std::cout << "Using coordinate frame "<< (int)coordinate_frame<<".\n";
      }
      if (pcl::console::parse (argc, argv, "-r", angular_resolution) >= 0)
            std::cout << "Setting angular resolution to "<<angular_resolution<<"deg.\n";
      angular_resolution = pcl::deg2rad (angular_resolution);

      // ------------------------------------------------------------------
      // -----Read pcd file or create example point cloud if not given-----
      // ------------------------------------------------------------------
      pcl::PointCloud<PointType>::Ptr point_cloud_ptr (new pcl::PointCloud<PointType>);
      pcl::PointCloud<PointType>& point_cloud = *point_cloud_ptr;
      pcl::PointCloud<pcl::PointWithViewpoint> far_ranges;
      Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());
      std::vector<int> pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");
      if (!pcd_filename_indices.empty ())
      {
            std::string filename = argv[pcd_filename_indices[0]];
            if (pcl::io::loadPCDFile (filename, point_cloud) == -1)
            {
                  std::cout << "Was not able to open file \""<<filename<<"\".\n";
                  printUsage (argv[0]);
                  return 0;
            }
      scene_sensor_pose = Eigen::Affine3f (Eigen::Translation3f (point_cloud.sensor_origin_[0],
                                                                  point_cloud.sensor_origin_[1],
                                                                  point_cloud.sensor_origin_[2]))* 
                                                                  Eigen::Affine3f (point_cloud.sensor_orientation_); 
      //


      std::string far_ranges_filename = pcl::getFilenameWithoutExtension (filename)+"_far_ranges.pcd";   "_far_ranges.pcd";
      if (pcl::io::loadPCDFile(far_ranges_filename.c_str(), far_ranges) == -1)
            std::cout << "Far ranges file \""<<far_ranges_filename<<"\" does not exists.\n";
      }
      else
      {
            std::cout << "\nNo *.pcd file given => Generating example point cloud.\n\n";
            for (float x=-0.5f; x<=0.5f; x+=0.01f)
            {
                  for (float y=-0.5f; y<=0.5f; y+=0.01f)
                  {
                        PointType point;  point.x = x;  point.y = y;  point.z = 2.0f - y;
                        point_cloud.push_back (point);
                  }
            }
                  point_cloud.width = point_cloud.size ();  point_cloud.height = 1;
      }

      // -----------------------------------------------
      // -----Create RangeImage from the PointCloud-----
      // -----------------------------------------------
      float noise_level = 0.0;
      float min_range = 0.0f;
      int border_size = 1;
      pcl::RangeImage::Ptr range_image_ptr (new pcl::RangeImage);
      pcl::RangeImage& range_image = *range_image_ptr;   
      range_image.createFromPointCloud (point_cloud, angular_resolution, pcl::deg2rad (360.0f), pcl::deg2rad (180.0f),
                                    scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);
      range_image.integrateFarRanges (far_ranges);
      if (setUnseenToMaxRange)
      	range_image.setUnseenToMaxRange ();

      // --------------------------------------------
      // -----Open 3D viewer and add point cloud-----
      // --------------------------------------------
      pcl::visualization::PCLVisualizer viewer ("3D Viewer");
      viewer.setBackgroundColor (1, 1, 1);
      viewer.addCoordinateSystem (0.5f,  scene_sensor_pose);
      pcl::visualization::PointCloudColorHandlerCustom<PointType> point_cloud_color_handler (point_cloud_ptr, 0, 0, 0);
      viewer.addPointCloud (point_cloud_ptr, point_cloud_color_handler, "original point cloud");
      //PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 150, 150, 150);
      //viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");
      //viewer.setPointCloudRenderingProperties (PCL_VISUALIZER_POINT_SIZE, 2, "range image");

      // -------------------------
      // -----提取边界-----
      // -------------------------
      pcl::RangeImageBorderExtractor border_extractor (&range_image);
      pcl::PointCloud<pcl::BorderDescription> border_descriptions;
      border_extractor.compute (border_descriptions);

      // ----------------------------------
      // -----Show points in 3D viewer-----
      // ----------------------------------
      // object border, veil points 和shadow points
      pcl::PointCloud<pcl::PointWithRange>::Ptr border_points_ptr(new pcl::PointCloud<pcl::PointWithRange>),
                                                veil_points_ptr(new pcl::PointCloud<pcl::PointWithRange>),
                                                shadow_points_ptr(new pcl::PointCloud<pcl::PointWithRange>);
      pcl::PointCloud<pcl::PointWithRange>& border_points = *border_points_ptr,
                                          & veil_points = * veil_points_ptr,
                                          & shadow_points = *shadow_points_ptr;
      // 不同类型的点
      for (int y=0; y< (int)range_image.height; ++y)
      {
            for (int x=0; x< (int)range_image.width; ++x)
            {        
                  if (border_descriptions[y*range_image.width + x].traits[pcl::BORDER_TRAIT__OBSTACLE_BORDER])
                        border_points.push_back (range_image[y*range_image.width + x]);
                  if (border_descriptions[y*range_image.width + x].traits[pcl::BORDER_TRAIT__VEIL_POINT])
                        veil_points.push_back (range_image[y*range_image.width + x]);
                  if (border_descriptions[y*range_image.width + x].traits[pcl::BORDER_TRAIT__SHADOW_BORDER])
                        shadow_points.push_back (range_image[y*range_image.width + x]);
            }
      }
      // 对不同类型的点采用不同颜色可视化
      pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> border_points_color_handler (border_points_ptr, 0, 255, 0);
      viewer.addPointCloud<pcl::PointWithRange> (border_points_ptr, border_points_color_handler, "border points");
      viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "border points");

      pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> veil_points_color_handler (veil_points_ptr, 255, 0, 0);
      viewer.addPointCloud<pcl::PointWithRange> (veil_points_ptr, veil_points_color_handler, "veil points");
      viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "veil points");

      pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> shadow_points_color_handler (shadow_points_ptr, 0, 255, 255);
      viewer.addPointCloud<pcl::PointWithRange> (shadow_points_ptr, shadow_points_color_handler, "shadow points");
      viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "shadow points");

      //-------------------------------------
      // -----Show points on range image-----
      // ------------------------------------
      pcl::visualization::RangeImageVisualizer* range_image_borders_widget = NULL;
      range_image_borders_widget =
      pcl::visualization::RangeImageVisualizer::getRangeImageBordersWidget (range_image, -std::numeric_limits<float>::infinity (), std::numeric_limits<float>::infinity (), false,
                                                                              border_descriptions, "Range image with borders");
      // -------------------------------------


      //--------------------
      // -----Main loop-----
      //--------------------
      while (!viewer.wasStopped ())
      {
	      range_image_borders_widget->spinOnce ();
	      viewer.spinOnce ();
	      pcl_sleep(0.01);
      }
}

CmakeLists.txt

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(range_image_border_extraction)

find_package(PCL 1.3 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (range_image_border_extraction range_image_border_extraction.cpp)
target_link_libraries (range_image_border_extraction ${PCL_LIBRARIES})

编译并运行:

./range_image_border_extraction -m

指定点云:

./range_image_border_extraction table_scene_lms400.pcd  -m -r 0.4 -c 1

在这里插入图片描述

绿点为object border; 红色为veil points; 蓝色为shadow border

数据样本

官方文档

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

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

相关文章

web坦克大战小游戏

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的订阅后,私信本人,发源码,含60+小游戏源码。如五子棋、象棋、植物大战僵尸、贪吃蛇、飞机大战、坦克大战、开心消消乐、扑鱼达人、扫雷、打地鼠、斗地主等等。 <!DOCTYPE htm…

express+mysql+vue,从零搭建一个商城管理系统8--文件上传,大文件分片上传

提示&#xff1a;学习express&#xff0c;搭建管理系统 文章目录 前言一、安装multer&#xff0c;fs-extra二、新建config/upload.js三、新建routes/upload.js四、修改routes下的index.js五、修改index.js六、新建上传文件test.html七、开启jwt验证token&#xff0c;通过login接…

渗透测试专用firefox浏览器 v2024.2最新版!!!

前言 之前做了一个firefox渗透测试专用浏览器v1&#xff0c;并且经过广大师傅的意见以及建议部分功能进行了调整以及新增。 如有相关意见&#xff0c;可以加入我们交流群进行反馈。 更新内容 去除DarkReader&#xff08;夜间模式&#xff09; 修改firefox主题&#xff0c;使…

【促销定价】背后的算法技术3-数据挖掘分析

【促销定价】背后的算法技术3-数据挖掘分析 01 整体分析1&#xff09;整体概览2&#xff09;类别型特征概览3&#xff09;数值型特征概览 02 聚合分析1&#xff09;天维度2&#xff09;品维度3&#xff09;价格维度4&#xff09;数量维度 03 相关分析1&#xff09;1级品类2&…

如何准备2024年汉字小达人:历年考题练一练-18道选择题解析

距离2024年第11届汉字小达人比赛还有八个多月的时间&#xff0c;建议如果有可能都让孩子参加一下&#xff0c;无需报名费&#xff0c;如果没时间准备也可以直接上阵参赛&#xff0c;检验一下孩子语文字、词、成语和古诗文方面的掌握情况。一方面可以激发孩子学习语文的兴趣&…

高级货,极大提高效率,个人非常喜欢

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; FileConverter中文版是一款免费软件&#xff0c;具有强大的功能。它支持多种文件格式的转换&#xff0c;包括视频、音频、文档等。您可以批量转换文件…

Unity 动态加载音频和音效

想要加载音效和音频需要两个组件&#xff1a; 听&#xff1a; 播&#xff1a; 一收一发 在层级中&#xff0c;右键创建 音频源 &#xff0c;放入物体的子物体中。 播放 方式一 拖动需要播放的音频文件到&#xff0c;音频源组件中。 using System.Collections; using Syst…

如何在Linux系统使用docker部署Apache Superset并结合内网穿透实现公网远程访问

文章目录 前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透&#xff0c;实现公网访问3. 设置固定连接公网地址 前言 Superset是一款由中国知名科技公司开源的“现代化的…

C# WinForm AndtUI第三方库 Tree控件使用记录

环境搭建 1.在NuGet中搜索AndtUI并下载至C# .NetFramework WinForm项目。 2.添加Tree控件至窗体。 使用方法集合 1.添加节点、子节点 using AntdUI; private void UpdateTreeView() {Tree tvwTestnew Tree();TreeItem rootTreeItem;TreeItem subTreeItem;Dictionary<str…

微信小程序用户隐私保护指引设置

场景&#xff1a;开发小程序时&#xff0c;有时候需要获取用户隐私信息&#xff0c;在提交小程序审核时&#xff0c;需要填写一份隐私保护协议&#xff0c;经常由于填写不规范导致审核不通过&#xff0c;在网上找到了一份模块可供参考 步骤&#xff1a;小程序后台-》设置-》服…

精品网站分享,建议关注收藏!~

01 练习打字 一个简约风格的可自定义主题、可切换字体的打字记录和键盘测试网站。 Typing | 一个简约风格的可自定义主题、可切换字体的打字记录和键盘测试网站。 typing.yasinchan.com 是一个可以测试键盘按键与打字速度并可以记录到排行榜的具有多主题简约风格的网站&#x…

llc半桥开关电源基础知识2(电路图简化)

llc半桥开关电源拓扑图如下 稳态:LLC电源已经正常工作,已经输出电压稳定稳态:LLC电源已经正常工作,已经输出电压稳定。 我们在分析拓扑结构的时候,都是基于他已经正常稳定输出的时候来分析的,毕竟LC电源只要以工作啊,绝大多数时间都是工作在稳态。 具体电路图化简分析如…

教育知识与能力保分卷一(中学)

2.在教育学的发展过程中&#xff0c;代表马克思主义的教育学著作是&#xff08;A &#xff09;。 A.凯洛夫的《教育学》 B.赞可夫的《教学与发展》 C.杜威的《民主主义与教育》 D.昆体良的《论演说家的教育》 8.小贺在一次期…

mysql学习笔记7——数据库查询深入

.sql文件 在实际使用数据库时&#xff0c;常常要对数据库文件进行备份&#xff0c;以便在数据库遭到入侵或者非人为因素导致损坏后&#xff0c;快速恢复数据 .sql文件便提供了这种功能&#xff0c;首先.sql文件是由一串串mysql指令组成的&#xff0c;我们插入.sql文件实际相当…

OpenDDS 在 Windows 上的编译环境部署指南

目录 1、OpenDDS2、编译OpenDDS2.1、准备工作2.2、配置环境变量2.3、编译-TAO_IDL_ACE2.4、编译-TAO_ACE2.5、编译-ACE2.7、生成OpenDDS的解决方案2.8、编译-DDS_no_test2.9、编译-DDS 1、OpenDDS OpenDDS是使用C语言针对OMG数据分发服务(DDS)的一种开源实现。由OCI公司设计和…

K8s集群调度,亲和性,污点,容忍,排障

目录 1.调度约束 调度过程 指定调度节点 查看详细事件 获取标签帮助 修改成 nodeSelector 调度方式 2.亲和性 节点亲和性 Pod 亲和性 键值运算关系 硬策略 软策略 Pod亲和性与反亲和性 创建一个标签为 appmyapp01 的 Pod 使用 Pod 亲和性调度&#xff0c;创建多…

CUDA学习笔记03:封装CUDA函数给Qt使用

参考资料 QT 调用 CUDA实现GPU加速图像处理&#xff08;chapter1&#xff09;_qt 如何使用cuda加速-CSDN博客 平时工作用Qt多一些&#xff0c;需要将封装的CUDA函数在Qt里调用&#xff0c;这里举一个简单的例子。 1. 建立vs dll工程 在vs2019中建立一个dll工程&#xff0c;…

LLM春招准备(1)

llm排序 GPT4V GPT-4V可以很好地理解直接绘制在图像上的视觉指示。它可以直接识别叠加在图像上的不同类型的视觉标记作为指针&#xff0c;例如圆形、方框和手绘&#xff08;见下图&#xff09;。虽然GPT-4V能够直接理解坐标&#xff0c;但相比于仅文本坐标&#xff0c;GPT-4V在…

06. Nginx进阶-Nginx代理服务

proxy代理功能 正向代理 什么是正向代理&#xff1f; 正向代理&#xff08;forward proxy&#xff09;&#xff0c;一个位于客户端和原始服务器之间的服务器。 工作原理 为了从原始服务器获取内容&#xff0c;客户端向代理发送一个请求并指定目标&#xff08;即原始服务器…

14 数值稳定性 + 模型初始化和激活函数【李沐动手学深度学习v2笔记】

1. 数值稳定性 神经网络的梯度 向量对向量求导&#xff08;梯度&#xff09;得到矩阵&#xff0c;太多的矩阵进行乘法会导致常见的两个问题 梯度消失和梯度爆炸 MLP MLP使用ReLU作为激活函数 梯度爆炸的问题 输入很大的时候梯度接近为0 梯度消失 梯度消失的问题 只能训练比…