[Cadangan berkaitan: Tutorial video Python3]
Baru-baru ini semasa saya belajar pemprosesan awan titik Set data Modelnet40
digunakan, yang mempunyai sejumlah kategori 40
Data awan titik setiap sampel disimpan dalam fail TXT
3 data pertama dalam setiap baris mewakili koordinat xyz
a titik. Saya perlu membaca setiap titik dalam fail TXT
dan kemudian menggunakan Open3D
untuk memaparkannya. Bagaimana untuk membaca data daripada fail TXT
? NumPy
Menyediakan fungsi yang sangat berkuasa loadtxt
yang boleh melaksanakan fungsi ini dengan sangat mudah. Mari lihat kod:
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()
Seperti yang anda lihat daripada kod di atas, anda hanya memerlukan satu baris kod untuk membaca data awan titik dalam fail TXT
, dan kemudian anda boleh antara muka panggilan Open3D
dipaparkan. Sebelum memperkenalkan penggunaan fungsi loadtxt
,
lihat pada kesan paparan Open3D:
Dalam contoh di atas, memandangkan data dalam setiap baris dalam TXT
dipisahkan dengan koma, selain daripada menetapkan laluan fail apabila memanggil loadtxt
fungsi, Perlu menetapkan parameter delimiter=","
. Selain itu, jenis data lalai bagi fungsi ini ialah float64
Jika jenis data lain, anda perlu menetapkan dtype
kepada jenis yang sepadan.
points_data = np.loadtxt("airplane_0001.txt", delimiter=",") #没有指定数据类型 print('shape: ', points_data.shape) print('data type: ', points_data.dtype)
Hasil:
bentuk: (10000, 6)
jenis data: float64
Jika kita mempunyai fail 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
Jenis data bagi 3 lajur pertama fail ialah titik terapung dan jenis data 2 lajur terakhir ialah jenis integer, maka ia tidak sesuai untuk menetapkan dtype
untuk membaca dengan cara sebelumnya. Tetapi tidak mengapa Fungsi loadtxt
boleh menetapkan jenis data setiap lajur data, tetapi ia lebih rumit sedikit:
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)
Tumpuan bagi kod ini ialah kandungan di dalam dtype={}
, 'names'
digunakan untuk menetapkan nama setiap lajur data dan 'formats'
digunakan untuk menetapkan jenis data setiap lajur data, dengan 'f4'
mewakili float32
dan 'i4'
mewakili int32
. Selain itu, baris pertama dalam fail CSV
bukan kandungan data dan anda boleh menetapkan parameter skiprows=1
untuk melangkau kandungan baris pertama.
Hasil keluaran:
data: [(-0.09879, -0.1823 , 0.1638 , 1, 1) ( 0.9946 , 0.25, 0.0420 )
( 0.1899 , -0.2922 , -0.9263 , 3, 3) (-0.9892 , 0.07461, -0.01235, 4, 4)]
jenis data: [('x', '
Anda boleh melihat bahawa dengan menetapkan dtype
dengan cara ini, setiap baris data yang dibaca menjadi jenis tuple
.
Daripada dokumentasi NumPy
, anda boleh tahu bahawa parameter pertama fungsi loadtxt
boleh menjadi objek fail, nama fail atau penjana. Apakah kegunaan hantaran dalam penjana? Mari lihat beberapa contoh.
Mengendalikan berbilang pembatas
Jika kandungan fail kami seperti ini, setiap baris data mempunyai 3 pembatas ",", "/" dan "-" :
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
Dalam kes ini, berbilang pembatas tidak boleh ditetapkan melalui parameter delimiter
boleh diproses melalui penjana pada masa ini:
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)
dan kemudian menghantar penjana ke dalam fungsi loadtxt
, seperti ini loadtxt
fungsi berjaya menghuraikan data dalam fail. loadtxt
Hasil keluaran:
[[ 9.87 1.82 1.63 1. 11. 1. ][ 9.94 7.44 1.02 ] 2. .
[ 1.89 2.92 9.26 1. 11. 3. ]
[ 0.98 7.46 1.23 1. 11. 4. ]]
Baca baris yang ditentukan >
在某些情况下,我们需要读取指定几行的数据,那么也可以通过生成器来实现。还是上面的文件内容,我们通过生成器来读取第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
函数结合生成器使用可以实现很多的功能。
从TXT
文件中读取到点云数据后,我想把数据保存到二进制文件中,需要怎么操作呢?NumPy
的ndarray
类提供了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视频教程 】
Atas ialah kandungan terperinci Cara menggunakan NumPy untuk membaca dan menyimpan data awan titik dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!