Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie NumPy zum Lesen und Speichern von Punktwolkendaten in Python

So verwenden Sie NumPy zum Lesen und Speichern von Punktwolkendaten in Python

WBOY
WBOYnach vorne
2022-09-02 16:52:162425Durchsuche

【Verwandte Empfehlung: Python3-Video-Tutorial

Vorwort

Vor kurzem habe ich beim Erlernen der Punktwolkenverarbeitung den Datensatz Modelnet40 verwendet, der insgesamt enthält 40 Kategorien, die Punktwolkendaten jeder Probe werden in einer TXT-Datei gespeichert und die ersten 3 Daten in jeder Zeile repräsentieren die xyz-Koordinaten eines Punktes . Ich muss jeden Punkt in der TXT-Datei lesen und ihn dann mit Open3D anzeigen. Wie lese ich Daten aus einer TXT-Datei? NumPy bietet eine sehr leistungsstarke Funktion loadtxt, die diese Funktion sehr einfach implementieren kann. Schauen wir uns den Code an: Modelnet40数据集,该数据集总共有40个类别,每个样本的点云数据存放在一个TXT文件中,每行的前3个数据代表一个点的xyz坐标。我需要把TXT文件中的每个点读取出来,然后用Open3D进行显示。怎么把数据从TXT文件中读取出来呢?NumPy提供了一个功能非常强大的函数loadtxt可以非常简单地实现这个功能。来看一下代码:

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()

从上面的代码可以看到,只需要一行代码就可以把TXT文件中的点云数据读取进来了,接下来就可以调用Open3D的接口进行显示了。在介绍loadtxt函数的用法之前,

顺便看一下Open3D的显示效果:

loadtxt函数的用法

基本用法

在上面的例子中,由于TXT里面每一行的数据是用逗号分割的,所以在调用loadtxt函数的时候除了设置文件路径外,还需要设置参数delimiter=","。另外,该函数默认的数据类型为float64,如果是其他数据类型的话还需要设置dtype为对应类型。

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

结果:

shape:  (10000, 6)
data type:  float64 

指定每一列的数据类型

假如我们有一个CSV文件:

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

该文件前面3列的数据类型是浮点型,后面2列的数据类型为整型,那么按照前面的方式设置dtype来读取就不合适了。不过没关系,loadtxt函数可以设置每一列数据的数据类型,只不过稍微复杂一点,来看一下代码:

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)

这段代码的重点是dtype={}里面的内容,'names'用来设置每一列数据的名称,'formats'则用来设置每一列数据的数据类型,其中'f4'表示float32'i4'表示int32。另外,CSV文件中的第一行不是数据内容,可以设置参数skiprows=1跳过第一行的内容。

输出结果:

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', '

可以看到,通过这样的方式设置dtype,读取的每一行数据变成了一个tuple类型。

结合生成器使用

NumPy的文档中可以知道,loadtxt函数的第一个参数可以是文件对象、文件名或者生成器。传入生成器有什么用呢?我们来看几个例子。

处理多个分隔符

假如我们的文件内容是这样的,每一行数据有3个分隔符",","/"和"-":

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

这种情况下不能通过delimiter参数设置多个分隔符,这时候就可以通过生成器来进行处理:

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)

这段代码构建了一个生成器将文件中每一行的分隔符全部替换成loadtxt函数默认的空格分隔符,然后把生成器传入loadtxt函数,这样loadtxt

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)

Wie Sie dem obigen Code entnehmen können, ist nur eine Codezeile erforderlich, um die Punktwolkendaten in der TXT-Datei zu lesen, und dann können Sie sie aufrufen Die Benutzeroberfläche von Open3D wird angezeigt. Bevor Sie die Verwendung der Funktion loadtxt vorstellen, werfen Sie einen Blick auf den Anzeigeeffekt von Open3D:

Verwendung der Loadtxt-Funktion

Grundlegende Verwendung

Im Obigen Beispiel: Da die Daten in jeder Zeile von TXT durch Kommas getrennt sind, müssen Sie beim Aufruf der Funktion loadtxt zusätzlich zum Festlegen des Dateipfads auch den Parameter delimiter=" ,". Darüber hinaus ist der Standarddatentyp dieser Funktion float64. Wenn es sich um andere Datentypen handelt, müssen Sie dtype auf den entsprechenden Typ festlegen.

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()


Ergebnis:

Form: (10000, 6)Datentyp: float64

🎜

Geben Sie den Datentyp jeder Spalte an

🎜Wenn wir einen CSVhaben > Datei: 🎜rrreee🎜Der Datentyp der ersten drei Spalten dieser Datei ist Gleitkomma und der Datentyp der letzten beiden Spalten ist Ganzzahl. Daher ist es nicht angemessen, dtype auf zu setzen Lesen Sie es auf die vorherige Art und Weise. Aber das spielt keine Rolle. Die Funktion loadtxt kann den Datentyp jeder Datenspalte festlegen, aber es ist etwas komplizierter. Schauen wir uns den Code an: 🎜rrreee🎜Der entscheidende Punkt Dieser Code lautet dtype={}Im Inhalt des Codes> wird <code>'names' verwendet, um den Namen jeder Datenspalte und 'formats' wird verwendet, um den Datentyp jeder Datenspalte festzulegen, wobei <code> 'f4' für float32 und 'i4' für int32. Darüber hinaus enthält die erste Zeile in der Datei CSV keinen Dateninhalt. Sie können den Parameter skiprows=1 festlegen, um den Inhalt der ersten Zeile zu überspringen. 🎜🎜🎜Ausgabeergebnis: 🎜🎜🎜🎜Daten: [(-0,09879, -0,1823, 0,1638, 1, 1) (0,9946, 0,07442, 0,01025, 0, 2)🎜 (0,1899, -0,2 922, -0,9263, 3, 3 ) (-0,9892, 0,07461, -0,01235, 4, 4)]🎜Datentyp: [('x', 'dtype auf diese Weise festgelegt ist , wird jede gelesene Datenzeile zum Typ tuple. 🎜

Wird in Kombination mit Generatoren verwendet

🎜Aus der Dokumentation von NumPy können wir wissen, dass der erste Parameter der Funktion loadtxt ein Dateiobjekt sein kann , Dateiname oder Generator. Welchen Nutzen hat die Einschaltung eines Generators? Schauen wir uns ein paar Beispiele an. 🎜🎜🎜Umgang mit mehreren Trennzeichen🎜🎜🎜🎜Wenn unser Dateiinhalt so ist, hat jede Datenzeile 3 Trennzeichen „“, „/“ und „-“: 🎜🎜rrreee🎜In diesem Fall nicht möglich. Setzen Sie mehrere Trennzeichen durch der delimiter-Parameter, 🎜Dieses Mal können Sie ihn über den Generator verarbeiten: 🎜🎜rrreee🎜Dieser Code erstellt einen Generator, um alle Trennzeichen in jeder Zeile der Datei durch das Standard-Leerzeichentrennzeichen des loadtxt-Funktion und übergeben Sie dann den Generator an die loadtxt-Funktion, damit die loadtxt-Funktion die Daten in der Datei erfolgreich analysieren kann. 🎜🎜🎜Ausgabeergebnis: 🎜🎜🎜🎜[[ 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. ]]🎜🎜🎜🎜Lesen Sie die angegebene Zeile🎜🎜

在某些情况下,我们需要读取指定几行的数据,那么也可以通过生成器来实现。还是上面的文件内容,我们通过生成器来读取第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 = &#39;airplane_0001.bin&#39;
    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__ == &#39;__main__&#39;:
    main()

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

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

【相关推荐:Python3视频教程

Das obige ist der detaillierte Inhalt vonSo verwenden Sie NumPy zum Lesen und Speichern von Punktwolkendaten in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:jb51.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen