其他工具

namespace: tool

工具模块定义了一些其他模块需要使用的,比较杂的功能,目前tool中包含了图片的基本处理,对于控制台颜色输出的控制,Ply文件的读取,计时器,多线程等等。

ConsoleColor

定义了一些对于控制台输出颜色的控制。作者希望OnePiece整个构架清晰,输出也尽量优雅。在该头文件中定义了红黄绿蓝四种颜色,红色对应Error,黄色对应Warning,而绿色表示运行成功,蓝色则是输出一些相关信息,利于Debug之类的。使用方法,包含了ConsoleColor头文件后,输出:

//输出ERROR
std::cout<<RED<<"[ERROR]::There is a error."<<RESET<<std::endl;

相应的,黄绿蓝分别对应YELLOW,GREEN,BLUE。RESET会使得输出颜色恢复默认的白色。

ImageProcessing

图片处理的相关内容,封装了一些OpenCV的函数,包括高斯滤波,sobel滤波,创建图像金字塔等等。

PLYManager

基于tinyply来进行ply文件的读写。除了顶点,颜色,法向以及三角面片之外,PLYManager也支持任意元素与属性以及注释的读写,不过想要添加的别的元素需要包装到AdditionalElement中才能正确被PLYManager读写:

struct AdditionalElement
{
    //元素个数
    size_t count;
    //数据占的总的比特数。一般来说等于(count * sizeof(type) * element_property.size())
    size_t byte_size;
    //元素名称
    std::string element_key;
    //元素属性名
    std::vector<std::string> element_property;
    //元素属性类型(char, short, int,以及无符号类型, float, double这些)
    tinyply::Type type;
    //元素属性可以是一个list,这是list的大小的类型
    tinyply::Type list_type = tinyply::Type::INVALID;
    //元素属性list的大小
    size_t list_count = 0;
    //指向数据的指针
    unsigned char *data; 
};
//读取附加的元素时候,转化后要注意delete掉data指针
bool ReadPLY(const std::string &filename, geometry::Point3List &points, geometry::Point3List &normals,
    geometry::Point3List &colors, geometry::Point3uiList &triangles, 
    std::vector<AdditionalElement> & additional_labels);
bool WritePLY(const std::string &filename, const geometry::Point3List&points, 
    const geometry::Point3List &normals, const geometry::Point3List &colors,
    const geometry::Point3uiList &triangles = geometry::Point3uiList(), 
    const std::vector<std::string> & comments = std::vector<std::string>(),
    const std::vector<AdditionalElement> & additional_labels = std::vector<AdditionalElement>(),
    bool use_ascii = false);

RPLYManager(已弃用)

使用RPLY库来进行PLY的读写,可以读取点云与三角网格,geometry::PointCloud以及geometry::TriangleMesh中load,write操作是对这个类的封装。

同时,OnePiece支持对vertex的其他属性或者label的读写,你可以读写语义信息等。用法如下:

//模板函数。读某个label的信息,你需要提供的是label名,value的类型,以及对应的容器vector
//每次读一个label,你可以只读自己感兴趣的label
template<typename T>
    bool ReadVertexLabelFromPLY(const std::string &filename, const std::string &label_name,
        std::vector<T> &vertex_labels);
//将附加的label信息写入ply。写的时候稍微有点麻烦,规定只能写int32, float, double, unchar, ushort几种类型。
//你需要将要写的信息打包成进一个容器vector,而这个vector的类型是AdditionalLabel,是tuple类型,包含了label_name, label_type, 以及一个指向要写的数据的指针。
//可以一次性写入多个属性
typedef std::tuple<std::string, e_ply_type, void *> AdditionalLabel;
bool WritePLY(const std::string &filename, const geometry::Point3List&points, 
    const geometry::Point3List &normals, const geometry::Point3List &colors,
    const std::vector<Eigen::Vector3i> &triangles, 
    const std::vector<AdditionalLabel> & additional_labels = std::vector<AdditionalLabel>(),
    bool use_ascii = true);

对于其他属性或者label的读写,可以查看example/GetLabelUsingKDTree.cpp,会读写mesh中的语音信息。这里可以将Read打包成与Write一样的形式,但是实际上Write在调用时候是比较麻烦的,而且意味着要为void指针分配空间(之后还需要释放)。这是比较危险的行为,因此放弃了这种做法。

OBJManager

对OBJ文件的读写,与RPLYManager相似。

MultiThreads

一个对于循环的多线程实现的模板函数。你需要提供的是参数,也就是输入,以及需要改变的输出,以及调用的函数。参数与返回,分别存放在两个std::vector中。函数原型如下:

template <class T1, class T2>
void MultiThreads(const std::vector<T1> &p1, std::vector<T2> &p2, std::function<void(const T1 &, T2&)> &f);

对于具体的使用也很简单,将输入和输出分别放到两个std::vector中,接着使用std::function绑定函数,一起传入上述函数中即可,之后介绍的网格生成会有使用的例子。

这里的实现还是太简单了,就意味着只能有一个输入一个输出,是为了满足作者需要的某个功能临时写的。

MultiThreads不会管你的循环能不能并行,所以确保循环可以并行加速是使用者的责任。

TickTock

TickTock是计时器,里面定义了一个计时器类Timer。Timer可以给多个过程计时,只要名字不同就可以。没错,使用Timer必须要给计时的过程定义一个独特的名字。使用起来很简单:

tool::Timer timer;
timer.TICK("My Process");
// code of process
timer.TOCK("My Process");
timer.Log("My Process");

Log函数用来输出使用的时间,单位是毫秒,你可以使用LogAll()来输出所有的统计。但是对于只Tick比Tock大的情况会输出警告。所以就尽量正确地使用这些工具吧。

OpenNIReader

封装了OpenNI读取深度图与颜色图的接口,有待完善。

KeyframeBasedSlam

基于关键帧的slam系统的一个基类,example/BAFusion.cpp以及example/FBAFusion.cpp都是基于这个类的。

CPPExtension

关于CPP的一些拓展,目前包含了对字符串的切片操作SplitRSplit,以及模板函数ShuffleVector,来随机打乱一个std::vector

IO

这里包含了对TUM数据集格式以及Scannet数据集格式的读写,并且函数AlignColorToDepth可以用来在颜色相机与深度相机参数不一致时,对齐颜色深度图(一般来说color map比depth map更大)。