将大型 .tiff 文件导入为稀疏矩阵

Import large .tiff file as sparse matrix

我有一个带有 1 个波段的大型 .tiff 文件(4.4gB,79530 x 54980 值)。由于只有 16% 的值有效,我认为最好将文件导入为稀疏矩阵,以节省 RAM。当我第一次将它打开为 np.array 然后使用 csr_matrix() 将其转换为稀疏矩阵时,我的内核已经崩溃了。请参阅下面的代码。

from osgeo import gdal
import numpy as np
from scipy.sparse import csr_matrix

ds = gdal.Open("file.tif")
band =  ds.GetRasterBand(1)
array = np.array(band.ReadAsArray())
csr_matrix(array)

有没有更好的方法来处理这个文件?最后,我必须根据栅格中的值进行计算。 (很遗憾,由于保密,我无法附上相关文件。)

假设您知道矩阵的大小,您可以创建一个空的稀疏矩阵,然后仅设置有效值 one-by-one。

from osgeo import gdal
import numpy as np
from scipy.sparse import csr_matrix

ds = gdal.Open("file.tif")
band =  ds.GetRasterBand(1)
matrix_size = (1000, 1000) # set you size
matrix = csr_matrix(matrix_size)

# for each valid value
matrix[i, j] = your_value

编辑 1

如果您不知道矩阵的大小,您应该可以这样检查:

from osgeo import gdal

ds = gdal.Open("file.tif")
width  = ds.GetRasterXSize()
height = ds.GetRasterYSize()
matrix_size = (width, height)

编辑 2

我测量了评论中建议的指标(已填满)。 This is how I measured memory usage.

尺寸 500x500

matrix empty size full size filling time
csr_matrix 2856 2992 477.67 s
doc_matrix 726 35807578 3.15 s
lil_matrix 8840 8840 0.54 s

尺寸 1000x1000

matrix empty size full size filling time
csr_matrix 4856 4992 7164.94 s
doc_matrix 726 150578858 12.81 s
lil_matrix 16840 16840 2.19 s

最好的解决方案可能是使用 lil_matrix

你能说出崩溃发生在哪里吗?

band =  ds.GetRasterBand(1)
temp = band.ReadAsArray()
array = np.array(temp)    # if temp is already an array, you don't need this
csr_matrix(array)

如果array是4.4gB,(79530, 54980)

In [62]: (79530 * 54980) / 1e9
Out[62]: 4.3725594    # 4.4gB makes sense for 1 byte/element
In [63]: (79530 * 54980) * 0.16        # 16% density
Out[63]: 699609504.0                # number of nonzero values

创建 csr 需要执行 np.nonzero(array) 来获取索引。这将产生 2 个 0.7 * 8 Gb 大小的数组(索引是 8 字节整数)。 coo 格式实际上需要这 2 个数组加上非零值的 0.7 - 大约 12 Gb。转换为 csrrow 属性减少到 79530 个元素 - 大约 7 Gb。 (更正为 8 bytes/element)

所以在 16% 的密度下,稀疏格式在最好的情况下仍然比密集版本大。

Memory error when converting matrix to sparse matrix, specified dtype is invalid

最近发生了内存错误 - 发生在 nonzero 步骤中。