Home  >  Article  >  Backend Development  >  How to use NumPy to read and save point cloud data in Python

How to use NumPy to read and save point cloud data in Python

WBOY
WBOYforward
2022-09-02 16:52:162347browse

[Related recommendations: Python3 video tutorial]

Preface

When I was learning point cloud processing recently The Modelnet40 data set is used. The data set has a total of 40 categories. The point cloud data of each sample is stored in a TXT file. Each line The first 3 data represent the xyz coordinates of a point. I need to read each point in the TXT file and then display it using Open3D. How to read data from the TXT file? NumPy provides a very powerful function loadtxt that can implement this function very simply. Let’s take a look at the code:

import open3d as o3d
import numpy as np

def main():
    points_data = np.loadtxt("airplane_0001.txt", delimiter=",", dtype=np.float32)
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(points_data[:, :3])
    o3d.visualization.draw_geometries([pcd])

if __name__ == '__main__':
    main()

As you can see from the above code, only one line of code is needed to read the point cloud data in the TXT file, and then you can call The interface of Open3D is displayed. Before introducing the usage of the loadtxt function,

take a look at the display effect of Open3D:

loadtxt Function Usage

Basic Usage

In the above example, since the data in each row of TXT is separated by commas, so when calling loadtxtIn addition to setting the file path when using the function, you also need to set the parameters delimiter=",". In addition, the default data type of this function is float64. If it is other data types, you need to set dtype to the corresponding type.

points_data = np.loadtxt("airplane_0001.txt", delimiter=",") #没有指定数据类型
print('shape: ', points_data.shape)
print('data type: ', points_data.dtype)

Result:

shape: (10000, 6)
data type: float64

Specify each column The data type

Suppose we have a CSV file:

x,y,z,label,id
-0.098790,-0.182300,0.163800,1,1
0.994600,0.074420,0.010250,0.2,2
0.189900,-0.292200,-0.926300,3,3
-0.989200,0.074610,-0.012350,4,4

The data type of the first three columns of the file is floating point, and the data type of the next two columns is integer type, then it is not appropriate to set dtype to read it in the previous way. But it doesn’t matter. The loadtxt function can set the data type of each column of data, but it is a little more complicated. Let’s take a look at the code:

data = np.loadtxt("test.txt", delimiter=",",
                      dtype={'names': ('x', 'y', 'z', 'label', 'id'), 
                            'formats': ('f4', 'f4', 'f4', 'i4', 'i4')},
                      skiprows=1)
print('data: ', data)
print('data type: ', data.dtype)

The key point of this code is dtype={ }The content inside, 'names' is used to set the name of each column of data, 'formats' is used to set the data type of each column of data, among which 'f4' represents float32, 'i4' represents int32. In addition, the first line in the CSV file is not the data content. You can set the parameter skiprows=1 to skip the content of the first line.

Output result:

data: [(-0.09879, -0.1823, 0.1638, 1, 1) (0.9946, 0.07442, 0.01025, 0, 2 )
( 0.1899 , -0.2922 , -0.9263 , 3, 3) (-0.9892 , 0.07461, -0.01235, 4, 4)]
data type: [('x', '

You can see that by setting dtype in this way, each row of data read becomes a tuple type.

Used in conjunction with the generator

From the documentation of NumPy, we can know that the first parameter of the loadtxt function can be a file object or a file name Or generator. What is the use of passing in a generator? Let's look at a few examples.

Handling multiple delimiters

If our file content is like this, each line of data has 3 delimiters ",", "/" and "-":

9.87,1.82,1.63,1/11-1
9.94,7.44,1.02,1/11-2
1.89,2.92,9.26,1/11-3
0.98,7.46,1.23,1/11-4

In this case, multiple delimiters cannot be set through the delimiter parameter. In this case, it can be processed through the generator:

def generate_lines(file_path, delimiters=[]):
    with open("test.txt") as f:
        for line in f:
            line = line.strip()
            for d in delimiters:
                line = line.replace(d, " ")
            yield line

delimiters = [",", "/", "-"]
generator = generate_lines("test.txt", delimiters)
data = np.loadtxt(generator)
print(data)

This code builds a generator to replace all the delimiters of each line in the file with the default space delimiter of the loadtxt function, and then passes the generator into loadtxt function, so that the loadtxt function can successfully parse the data in the file.

Output result:

[[ 9.87 1.82 1.63 1. 11. 1. ]
[ 9.94 7.44 1.02 1. 11. 2. ]
[ 1.89 2.92 9.26 1. 11. 3. ]
[ 0.98 7.46 1.23 1. 11. 4. ]]

Read the specified line

在某些情况下,我们需要读取指定几行的数据,那么也可以通过生成器来实现。还是上面的文件内容,我们通过生成器来读取第2行和第3行:

def generate_lines(file_path, delimiters=[], rows=[]):
    with open("test.txt") as f:
        for i, line in enumerate(f):
            line = line.strip()
            for d in delimiters:
                line = line.replace(d, " ")
            if i in rows:
                yield line

delimiters = [",", "/", "-"]
rows = [1, 2]
generator = generate_lines("test.txt", delimiters, rows)
data = np.loadtxt(generator)
print(data)

输出结果:

[[ 9.94  7.44  1.02  1.   11.    2.  ]
 [ 1.89  2.92  9.26  1.   11.    3.  ]]

通过上面的例子可以知道,loadtxt函数结合生成器使用可以实现很多的功能。

tofile和fromfile函数

TXT文件中读取到点云数据后,我想把数据保存到二进制文件中,需要怎么操作呢?NumPyndarray类提供了tofile函数可以非常方便地将数据保存到二进制文件中。把数据以二进制文件保存后又怎么读进来呢?NumPy还提供了一个fromfile函数用于从文本文件和二进制文件中读取数据。

import open3d as o3d
import numpy as np

def main():
    points_data = np.loadtxt(
        "airplane_0001.txt", delimiter=",", dtype=np.float32)

    bin_file = 'airplane_0001.bin'
    points_data = points_data[:, :3]
    points_data.tofile(bin_file)

    pc = np.fromfile(bin_file, dtype=np.float32)
    pc = pc.reshape(-1, 3)
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(pc)
    o3d.visualization.draw_geometries([pcd])

if __name__ == '__main__':
    main()

在上面这段示例代码中,我从airplane_0001.txt文件中读取了点云数据,然后通过tofile函数将数据保存到二进制文件airplane_0001.bin中,再用fromfile函数从二进制文件中把点云数据读取出来用Open3D进行显示。

为了前后呼应,让我们换个角度再看一眼显示效果:

【相关推荐:Python3视频教程

The above is the detailed content of How to use NumPy to read and save point cloud data in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:jb51.net. If there is any infringement, please contact admin@php.cn delete