2021SC@SDUSC

文章目录

  • open3D体素化
    • VoxelGrid.h
    • VoxelGridIO
    • 小结

open3D体素化

本篇解读voxel(体元/体素)的基本类Voxel,以及VoxelGrid和VoxelGridIO两个体素网格的基本类。

VoxelGrid.h

包含Voxel和VoxelGrid类。

Voxel(体素),包含网格 ID 和颜色;VoxelGrid(体素网格)是在网格中对齐的体素的集合。

  • 注意点:

    1. 由于需要解析的代码较多,为使代码解读更加清晰,我将代码分析的详细过程写在代码段的注释中。

    2. 中文部分是源码解读,包含代码分析和遇到的问题。

#pragma once#include <Eigen/Core>
#include <memory>
#include <unordered_map>
#include <vector>#include "open3d/geometry/Geometry3D.h"
#include "open3d/utility/Helper.h"
#include "open3d/utility/Logging.h"namespace open3d {namespace camera {
class PinholeCameraParameters;
}namespace geometry {class PointCloud;
class TriangleMesh;
class Octree;
class Image;/// \class Voxel
/// 基本体素类,包含网格id和颜色。
class Voxel {
public:/// 默认构造函数。Voxel() {}/// 参数化构造函数。/// grid_index 体素的网格坐标索引。Voxel(const Eigen::Vector3i &grid_index) : grid_index_(grid_index) {}/// 参数化构造函数。/// grid_index 体素的网格坐标索引。/// color 体素的颜色。Voxel(const Eigen::Vector3i &grid_index, const Eigen::Vector3d &color): grid_index_(grid_index), color_(color) {}~Voxel() {}public:/// 体素的网格坐标索引。Eigen::Vector3i grid_index_ = Eigen::Vector3i(0, 0, 0);/// 体素的颜色。Eigen::Vector3d color_ = Eigen::Vector3d(0, 0, 0);
};/// \class VoxelGrid
/// VoxelGrid是一个在网格中对齐的体素集合。
class VoxelGrid : public Geometry3D {
public:/// 默认构造函数VoxelGrid() : Geometry3D(Geometry::GeometryType::VoxelGrid) {}/// 拷贝构造函数。VoxelGrid(const VoxelGrid &src_voxel_grid);~VoxelGrid() override {}VoxelGrid &Clear() override;bool IsEmpty() const override;Eigen::Vector3d GetMinBound() const override;Eigen::Vector3d GetMaxBound() const override;Eigen::Vector3d GetCenter() const override;AxisAlignedBoundingBox GetAxisAlignedBoundingBox() const override;OrientedBoundingBox GetOrientedBoundingBox() const override;VoxelGrid &Transform(const Eigen::Matrix4d &transformation) override;VoxelGrid &Translate(const Eigen::Vector3d &translation,bool relative = true) override;VoxelGrid &Scale(const double scale,const Eigen::Vector3d &center) override;VoxelGrid &Rotate(const Eigen::Matrix3d &R,const Eigen::Vector3d &center) override;VoxelGrid &operator+=(const VoxelGrid &voxelgrid);VoxelGrid operator+(const VoxelGrid &voxelgrid) const;/// 如果体素网格包含体素,返回true。bool HasVoxels() const { return voxels_.size() > 0; }/// 如果体素网格包含体素颜色,返回true。bool HasColors() const {return true;  // 默认情况下,颜色是(0,0,0)。}/// 返回给定查询点的体素索引。Eigen::Vector3i GetVoxel(const Eigen::Vector3d &point) const;/// 返回查询的体素中心的3d坐标的函数。Eigen::Vector3d GetVoxelCenterCoordinate(const Eigen::Vector3i &idx) const {auto it = voxels_.find(idx);if (it != voxels_.end()) {auto voxel = it->second;return ((voxel.grid_index_.cast<double>() +Eigen::Vector3d(0.5, 0.5, 0.5)) *voxel_size_) +origin_;} else {return Eigen::Vector3d::Zero();}}/// 添加一个具有指定网格索引和颜色的体素。void AddVoxel(const Voxel &voxel);/// 返回一个定义索引体素立方体的3D坐标向量。std::vector<Eigen::Vector3d> GetVoxelBoundingPoints(const Eigen::Vector3i &index) const;///逐个元素检查列表中的查询是否包含在VoxelGrid中。 ///Queries是双精度和映射到最近的体素。std::vector<bool> CheckIfIncluded(const std::vector<Eigen::Vector3d> &queries);/// 从VoxelGrid中移除所有的体素,其中没有一个体素的边界点投射到小于或等于边界点的投影深度值。/// 如果keep_voxels_outside_image为真,那么只有当所有边界点投射到一个有效的图像位置时,体素才会被雕刻。////// depth_map 用于VoxelGrid中分的深度映射(图像)。/// camera_parameter 输入摄像头参数。/// ???keep_voxels_outside_image 将所有的体素展现到一个有效的位置。VoxelGrid &CarveDepthMap(const Image &depth_map,const camera::PinholeCameraParameters &camera_parameter,bool keep_voxels_outside_image);/// 从VoxelGrid中移除所有的体素,其中没有体素的边界点投射到一个有效的掩模像素(像素值>0)。/// 如果keep_voxels_outside_image为真,那么只有当所有边界点投射到一个有效的图像位置时,体素才会被分开。////// silhouette_mask Silhouette mask(Image)用于雕刻VoxelGrid。/// camera_parameter 将所有的体素项目到一个有效的位置。/// keep_voxels_outside_image 将所有的体素展现到一个有效的位置。VoxelGrid &CarveSilhouette(const Image &silhouette_mask,const camera::PinholeCameraParameters &camera_parameter,bool keep_voxels_outside_image);/// 从Octree中创建VoxelGrid。////// Octree 输入的八叉树。void CreateFromOctree(const Octree &octree);/// Convert to Octree.////// \param max_depth Maximum depth of the octree.std::shared_ptr<geometry::Octree> ToOctree(const size_t &max_depth) const;/// 创建一个体素网格,每个体素都是已设置状态(因此密集)。这是voxel carving的一个有效开始。////// origin VoxelGrid坐标中心/// color VoxelGrid中所有体素的颜色。/// voxel_size VoxelGrid构造的体素大小。/// width VoxelGrid的空间宽度扩展。/// height 对VoxelGrid的空间高度扩展。/// depth 对VoxelGrid的空间深度扩展。static std::shared_ptr<VoxelGrid> CreateDense(const Eigen::Vector3d &origin,const Eigen::Vector3d &color,double voxel_size,double width,double height,double depth);/// 从给定的PointCloud创建一个VoxelGrid。给定体素的颜色值是落入其中的点的平均颜色值(如果PointCloud有颜色)。/// 创建的VoxelGrid的边界是从PointCloud计算的。////// input 输入的PointCloud。/// voxel_size VoxelGrid构造的体素大小。static std::shared_ptr<VoxelGrid> CreateFromPointCloud(const PointCloud &input, double voxel_size);/// 从给定的PointCloud创建一个VoxelGrid。给定体素的颜色值是落入其中的点的平均颜色值(如果PointCloud有颜色)。/// 创建的VoxelGrid的边界是从PointCloud计算的。////// input 输入的PointCloud。/// voxel_size VoxelGrid构造的体素大小。/// min_bound 用于创建VoxelGrid的最小边界点。/// max_bound 用于创建VoxelGrid的最大边界点。static std::shared_ptr<VoxelGrid> CreateFromPointCloudWithinBounds(const PointCloud &input,double voxel_size,const Eigen::Vector3d &min_bound,const Eigen::Vector3d &max_bound);/// 从给定的三角形网格创建一个VoxelGrid。没有颜色信息被转换。创建的VoxelGrid的边界是从TriangleMesh计算出来的。////// input 输入的三角形网格。/// voxel_size VoxelGrid构造的体素大小。static std::shared_ptr<VoxelGrid> CreateFromTriangleMesh(const TriangleMesh &input, double voxel_size);/// 从给定的三角形网格创建一个VoxelGrid。没有颜色信息被转换。创建的VoxelGrid的边界是由给定的参数定义的。////// input 输入的三角形网格。/// voxel_size VoxelGrid构造的体素大小。/// min_bound 用于创建VoxelGrid的最小边界点。/// max_bound 用于创建VoxelGrid的最大边界点。static std::shared_ptr<VoxelGrid> CreateFromTriangleMeshWithinBounds(const TriangleMesh &input,double voxel_size,const Eigen::Vector3d &min_bound,const Eigen::Vector3d &max_bound);///返回“体素”列表:包含在体素网格中的体素。///从这个方法返回的体素的更改不会反映在体素网格中。std::vector<Voxel> GetVoxels() const;public:///体素的大小。double voxel_size_ = 0.0;///起始点的坐标。Eigen::Vector3d origin_ = Eigen::Vector3d::Zero();///包含在体素网格中的体素。std::unordered_map<Eigen::Vector3i,Voxel,utility::hash_eigen<Eigen::Vector3i>>voxels_;
};/// \class AvgColorVoxel
///在一个体素中聚合不同votes的颜色值的类。
///计算体素的平均颜色值。
class AvgColorVoxel {
public:AvgColorVoxel() : num_of_points_(0), color_(0.0, 0.0, 0.0) {}public:void Add(const Eigen::Vector3i &voxel_index) {if (num_of_points_ > 0 && voxel_index != voxel_index_) {utility::LogWarning("Tried to aggregate ColorVoxel with different ""voxel_index");}voxel_index_ = voxel_index;}void Add(const Eigen::Vector3i &voxel_index, const Eigen::Vector3d &color) {Add(voxel_index);color_ += color;num_of_points_++;}Eigen::Vector3i GetVoxelIndex() const { return voxel_index_; }Eigen::Vector3d GetAverageColor() const {if (num_of_points_ > 0) {return color_ / double(num_of_points_);} else {return color_;}}public:int num_of_points_;Eigen::Vector3i voxel_index_;Eigen::Vector3d color_;
};}  // namespace geometry
}  // namespace open3d

VoxelGridIO

注:注释中文部分为源码分析

#pragma once#include <string>#include "open3d/geometry/VoxelGrid.h"namespace open3d {
namespace io {///从一个文件创建一个voxelgrid的工厂函数。
///如果读取失败,返回一个空的voxelgrid。
std::shared_ptr<geometry::VoxelGrid> CreateVoxelGridFromFile(const std::string &filename,const std::string &format = "auto",bool print_progress = false);///从文件中读取VoxelGrid的常规入口。
///该函数基于扩展名filename调用read函数。
///如果读取成功,返回true,否则返回false。
bool ReadVoxelGrid(const std::string &filename,geometry::VoxelGrid &voxelgrid,const std::string &format = "auto",bool print_progress = false);///写入VoxelGrid到文件的一般入口
///函数调用基于扩展名filename的write函数。
///如果write函数支持二进制编码和压缩,则使用后两个参数。否则它们将被忽略。
///如果写入成功,返回true,否则返回false。
bool WriteVoxelGrid(const std::string &filename,const geometry::VoxelGrid &voxelgrid,bool write_ascii = false,bool compressed = false,bool print_progress = false);bool ReadVoxelGridFromPLY(const std::string &filename,geometry::VoxelGrid &voxelgrid,bool print_progress = false);bool WriteVoxelGridToPLY(const std::string &filename,const geometry::VoxelGrid &voxelgrid,bool write_ascii = false,bool compressed = false,bool print_progress = false);}  // namespace io
}  // namespace open3d

小结

本篇我分析了体素相关的三个类,对open3D在体素方面的应用有了更深的理解。下一篇是对点云的一些应用,结合了open3D点云的python部分,用python代码实现了点云的一些应用。

open3D源码解读第四篇相关推荐

  1. open3D源码分析第四篇

    2021SC@SDUSC PointCloud.h 注释中文部分是源码解读,分析和问题在源码之后 #include <Eigen/Core> #include <memory> ...

  2. faster rcnn源码解读(四)之数据类型imdb.py和pascal_voc.py(主要是imdb和roidb数据类型的解说)

    转载自:faster rcnn源码解读(四)之数据类型imdb.py和pascal_voc.py(主要是imdb和roidb数据类型的解说) - 野孩子的专栏 - 博客频道 - CSDN.NET ht ...

  3. mobx 源码解读(四):讲讲 autorun 和 reaction

    原文地址:mobx autorun 文本是 mobx 源码解读系列 第四篇 本系列文章全部采用 mobx 较新版本:v5.13.0 mobx 源码解读 issue,欢迎讨论 技术前提 在阅读之前,希望 ...

  4. spring beans源码解读之--总结篇

    spring beans下面有如下源文件包: org.springframework.beans, 包含了操作java bean的接口和类. org.springframework.beans.ann ...

  5. Flask源码阅读-第四篇(flask\app.py)

    flask.app该模块2000多行代码,主要完成应用的配置.初始化.蓝图注册.请求装饰器定义.应用的启动和监听,其中以下方法可以重点品读和关注 def setupmethod(f): @setupm ...

  6. 若依框架源码解读之数据源篇

    读源码过程中读到yml中有设置主次数据源,次数据源没有启用,在看到DruidConfig中的配置时,没有搞明白,怎么让mybatis找到主数据源的,请教大神在哪里实现的. 附上数据源配置 @Bean( ...

  7. 【转】[Hadoop源码解读](四)MapReduce篇之Counter相关类

    转自:http://www.cnblogs.com/lucius/p/3449922.html 当我们定义一个Counter时,我们首先要定义一枚举类型: 1 public static enum M ...

  8. JStorm/Storm源码解读(二)--启动篇

    为了在解读分析时有个统一的思路,本文将从启动一个集群开始分析. (说明:为了测试方便,采用的是本地模式). 1.参数设置 Config conf = new Config(); //设置Topolog ...

  9. Bootstrap源码解读之栅格化篇

    本文纯属自己研究所写笔记,如果有错误还请多多指教提出 版心(container) 版心:class名为.container的容器,其版心的宽度在各个屏幕设备下是不一样的值,版心两边就是留白.  各尺寸 ...

最新文章

  1. html怎么使用伪类清除浮动,JS中使用 after 伪类清除浮动实例
  2. 创建非矩形的Windows 窗体
  3. mysql 备份到别的机器_物理拷贝备份mysql到其他机器上恢复
  4. 文件服务器 之 VSFTPD的高手篇
  5. 如何在用户区显示一张位图
  6. Mac 下更新 .bash_profile 文件
  7. 使用Visio 2003画UML类图之使用实现接口图标
  8. 身份证后四位是否唯一
  9. 计算机网络专业综合实践报告,计算机网络专业实习报告.doc
  10. 想在体制内吃得开,不要有这5种表现,不受领导待见,越混越糟糕
  11. 一个离职程序员的找工作历程(2021.4.28更新)
  12. circos 可视化手册-highlights 篇
  13. QSocketNotifier: Socket notifiers cannot be enabled or disabled from another
  14. 跟着Cell学作图 | 12.韦恩图(Vennerable包)
  15. 七个初学者必下载的Python编程器
  16. 优步北京B组奖励政策
  17. bzoj4521【CQOI2016】手机号码
  18. 标准解读系列:行标发布,道路交通信号控制机从管控到服务
  19. DORIS单节点部署
  20. # MAC备份/导出IDEA配置

热门文章

  1. html点击图片产生事件,javascript里怎么实现点击图片弹出对话框?
  2. ATTCK v10版本战术介绍-初始访问
  3. Springboot之Excel表格导出
  4. 使用fastDFS上传压缩包,下载后格式有误,大乌龙
  5. centos6安装eclipse
  6. 获取键盘通知的 UserInfo
  7. 基于socket实现虚拟手柄使用手机控制电脑游戏(下)-手机端虚拟手柄
  8. Jenkins 基于Kubernetes 弹性构建池
  9. 经典飞控-APM中文参考手册
  10. netty自定义消息实现心跳检测与重连