我一直试图将用laspy读取的点云的点列表附加到另一个点列表,基本上是合并两个点云。合并多个点云时,我一直将所有点附加到同一np.ndarray上,以便将其保存回一个松散的文件中。现在,只要我要合并的所有点云的总大小超过约350 MB,我就会得到MemoryError
。
我尝试使用另一种写入点云文件的方法,这样我就不必一次将所有点读入内存,但这失败了,因为在写入点云文件时,laspy确实很奇怪,这是我想出的几件事:
laspy.File.points
具有以下格式:array([((24315, 12245, 12080, 0, 24, 0, 0, 0, 202, 23205, 24735, 21930),),
...,
((15155, -23292, -6913, 0, 56, 0, 0, 0, 343, 36975, 37230, 37485),)],
dtype=[('point', [('X', '<i4'), ('Y', '<i4'), ('Z', '<i4'), ('intensity', '<u2'), ('flag_byte', 'u1'), ('raw_classification', 'u1'), ('scan_angle_rank', 'i1'), ('user_data', 'u1'), ('pt_src_id', '<u2'), ('red', '<u2'), ('green', '<u2'), ('blue', '<u2')])])
laspy.File.points
的变量类型为numpy.ndarray
laspy.File.points
的形状为(<numberOfRows>,)
=>一维数组,即使每行有12个值(?)numpy.void
laspy.File
,您需要在写入模式下创建一个新文件,从现有文件复制标头,然后将File.points设置为与上述类型完全相同的numpy数组。设置完一次点后,便无法再次设置它们,这意味着设置点时需要知道最终的行数。laspy.File.set_x(<arrayOfXValues>)
(和类似名称)更改行的值,其长度必须与laspy.File.points
现在,我的PC上有16 GB RAM,当我开始合并时,其中大约有10 GB可用空间。使用psutils
可以得到used和available的内存,而我的可用内存永远不会低于9 GB。使用psutil.Process(os.getpid()).memory_info().rss
,我获得了此过程所用的内存,该内存从未超过650 MB。
合并时,我读取了第一个文件,然后遍历其他文件,一个一个地读取它们,然后调用numpy.append(combinedPoints, otherPointcloudPoints)
将所有点堆叠在一起。但是,当上述条件为真时,将抛出MemoryError
。
这是将多个点云合并到一个新的点云的代码(这全部发生在类PointCloudFileIO
中,self.file
是laspy.File
的实例)。 util.inMB
计算字节到兆字节的大小。
def mergePointClouds(self, listPaths, newPath):
realSize = util.inMB(psutil.Process(os.getpid()).memory_info().rss)
print("Process Memory used at start: {:.2f}MB".format(realSize))
print("Available memory at start: {:.2f}MB".format(util.inMB(psutil.virtual_memory().available)))
pointsOwn = self.file.points
firstOtherReader = PointCloudFileIO(listPaths[0])
pointsCombined = np.append(pointsOwn, firstOtherReader.file.points)
realSize = util.inMB(psutil.Process(os.getpid()).memory_info().rss)
print("Process Memory used after first merge: {:.2f}MB".format(realSize))
print("Available memory after first merge: {:.2f}MB".format(util.inMB(psutil.virtual_memory().available)))
for i in range(1, len(listPaths)):
otherReader = PointCloudFileIO(listPaths[i])
otherPoints = otherReader.file.points
pointsCombined = np.append(pointsCombined, otherPoints)
realSize = util.inMB(psutil.Process(os.getpid()).memory_info().rss)
print("Process Memory used in loop: {:.2f}MB".format(realSize))
print("Available memory in loop: {:.2f}MB | Used: {:.2f}MB | Percent: {}%".format(util.inMB(psutil.virtual_memory().available), util.inMB(psutil.virtual_memory().used), psutil.virtual_memory().percent))
outFile = File(newPath, mode='w', header=self.file.header)
outFile.points = pointsCombined
outFile.close()
对于我所拥有的几乎所有用例,这都可以正常工作。它将所有提供的点云合并到新文件中的新点云。但是,当生成的点云有点太大时,尽管内存远远超出了需要,我得到了MemoryError
。
以下是当我使用these pointclouds (download .laz files)启动程序时的日志,您需要使用laszip解压缩.laz文件,然后才能将它们用于laspy(至少在使用Windows时):
Process Memory used at start: 21.18MB
Available memory at start: 9793.35MB | Used: 6549.50MB | Percent: 40.1%
Process Memory used after first merge: 381.63MB
Available memory after first merge: 9497.64MB | Used: 6845.20MB | Percent: 41.9%
Process Memory used in loop: 559.52MB
Available memory in loop: 9309.36MB | Used: 7033.48MB | Percent: 43.0%
Process Memory used in loop: 637.05MB
Available memory in loop: 9301.00MB | Used: 7041.85MB | Percent: 43.1%
Traceback (most recent call last):
File "optimization_test.py", line 7, in <module>
f1.mergePointClouds(paths, "someShiet.las")
File "C:\Users\viddie\Desktop\git\GeoLeo\geoleo\pointcloud.py", line 175, in mergePointClouds
pointsCombined = np.append(pointsCombined, otherPoints)
File "C:\Users\viddie\AppData\Local\Programs\Python\Python36-32\lib\site-packages\numpy\lib\function_base.py", line 5166, in append
return concatenate((arr, values), axis=axis)
MemoryError
如果有人知道原因,我们将不胜感激。
答案 0 :(得分:0)
即使该操作实际上不适合内存,您也可以将某些硬盘驱动器专用为内存。
或者您可以在Ubuntu上使用交换空间。
也许从此开始,直到您弄清楚如何减少内存消耗。或者至少这可以通过确保确实有足够的内存来帮助您进行故障排除。