在 R 中处理大型光栅马赛克,无需将它们合并到单个文件(如 lidR 目录)
Work with large raster mosaics in R without merging them to a single file (like lidR catalog)
lidR 包有一种处理大型(点云)数据集的巧妙方法:catalog
函数(此处为 doc)避免将数据集加载到内存中,并且可以处理马赛克 [数据集是分布在多个(非重叠)图块]作为单个数据集。它以智能方式在计算过程中即时加载所需的图块。如果只处理数据集的一小部分,最好避免处理大文件(多个 GB)并保持内存需求精简。
在 R 中是否有类似的 convenient/memory-efficient/"lidR-catalog-way" 来处理大型光栅马赛克?
或者更笼统地说:
有没有一种方法可以在 R 中使用马赛克栅格数据集而不先合并它们?
我知道 mosaic
(doc) 和 merge
函数,它们允许我将我的分块栅格镶嵌合并到单个栅格数据集中。我还发现 gdal
会 很多 更快并且内存效率更高。这是一个 R 片段:
mosaicgdal <- function(files, out) {
in_files = do.call(paste, c(as.list(files), sep = " "))
cmd = paste("gdal_merge.py -a_nodata -32767 -ps 25 25 -o", out, in_files)
system(cmd)
}
然而,两者都需要将整个数据集具体化为内存中(或至少在磁盘上)的一个文件。有没有办法避免这种情况?
我的申请:
我正在处理一个巨大的 LAS 点云(数 TB,所有内容都平铺在 100 MB 的文件中)和相应的栅格数据集(大约 100 GB),例如高分辨率地形模型。我通常处理小部分(通过空间多边形 [.shp/.kml] 分隔)或整个 LAS 切片。这在 lidR 中非常节省内存,只加载必要的图块:
# load several TB las tiles as catalog (only file-paths and metadata)
las_data = catalog("D:/FOLDER/WITH/11TB/OF/LAS/TILES")
# load polygon of region of interest
region_of_interest = readOGR("D:/EG/SHP/FILE/OF/ROI")
# cut out the portion of las_data overlapping the polygon
# this will load only the required tiles in memory
las_data_roi = clip_roi(las_data, extent(region_of_interest ))
# ... and create a DTM for example
dtm_roi = grid_terrain(las_data_roi , algorithm = kriging(k = 10L))
我想对栅格数据集执行相同的操作:
# load raster dataset only as pointers to files (and metadata such as extent)
raster_data = raster("D:/FOLDER/WITH/LOTS/OF/RASTER/TILES")
# e.g. crop from mosaic without having to call mosaic/merge first
# avoiding having a huge single file/reading the whole dataset
raster_roi = crop(raster_data, roi)
我通常使用 raster 包,但它似乎没有提供任何此类功能。
您应该查看 terra
包,它通过虚拟栅格图块 (VRT) 提供了您正在寻找的功能。我们可以使用它们将磁盘上的一组光栅文件视为单个光栅文件,同时利用 API 来完成大部分与通过 raster
包可以完成的任务相同的任务。
首先,让我们使用直接来自 ?terra::vrt()
文档的示例创建一个包含 4 个栅格的样本。
library(terra)
r <- rast(ncols=100, nrows=100)
values(r) <- 1:ncell(r)
x <- rast(ncols=2, nrows=2)
filename <- paste0(tempfile(), "_.tif")
ff <- makeTiles(r, x, filename)
ff
#> [1] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_1.tif"
#> [2] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_2.tif"
#> [3] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_3.tif"
#> [4] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_4.tif"
现在,我们再次将它们作为 VRT 读入,直接来自同一示例。这允许
vrtfile <- paste0(tempfile(), ".vrt")
v <- vrt(ff, vrtfile)
head(readLines(vrtfile))
#> [1] "<VRTDataset rasterXSize=\"100\" rasterYSize=\"100\">"
#> [2] " <SRS dataAxisToSRSAxisMapping=\"2,1\">GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]</SRS>"
#> [3] " <GeoTransform> -1.8000000000000000e+02, 3.6000000000000001e+00, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.8000000000000000e+00</GeoTransform>"
#> [4] " <VRTRasterBand dataType=\"Float32\" band=\"1\">"
#> [5] " <NoDataValue>nan</NoDataValue>"
#> [6] " <ColorInterp>Gray</ColorInterp>"
v
#> class : SpatRaster
#> dimensions : 100, 100, 1 (nrow, ncol, nlyr)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326)
#> source : filedf6b216a737.vrt
#> name : filedf6b216a737
#> min value : 1
#> max value : 10000
现在,我们可以创建一个简单的示例多边形来将我们感兴趣的区域限制在 -180 到 180 到 -90 到 90 经度之间。
library(sf)
pl <- list(rbind(c(-90,-90), c(-90,90), c(90,90), c(90,-90), c(-90,-90)))
roi <- st_sfc(st_polygon(pl), crs = "EPSG:4326")
crop(v, roi)
#> class : SpatRaster
#> dimensions : 100, 50, 1 (nrow, ncol, nlyr)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -90, 90, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326)
#> source : memory
#> name : filedf6b216a737
#> min value : 26
#> max value : 9975
lidR 包有一种处理大型(点云)数据集的巧妙方法:catalog
函数(此处为 doc)避免将数据集加载到内存中,并且可以处理马赛克 [数据集是分布在多个(非重叠)图块]作为单个数据集。它以智能方式在计算过程中即时加载所需的图块。如果只处理数据集的一小部分,最好避免处理大文件(多个 GB)并保持内存需求精简。
在 R 中是否有类似的 convenient/memory-efficient/"lidR-catalog-way" 来处理大型光栅马赛克? 或者更笼统地说: 有没有一种方法可以在 R 中使用马赛克栅格数据集而不先合并它们?
我知道 mosaic
(doc) 和 merge
函数,它们允许我将我的分块栅格镶嵌合并到单个栅格数据集中。我还发现 gdal
会 很多 更快并且内存效率更高。这是一个 R 片段:
mosaicgdal <- function(files, out) {
in_files = do.call(paste, c(as.list(files), sep = " "))
cmd = paste("gdal_merge.py -a_nodata -32767 -ps 25 25 -o", out, in_files)
system(cmd)
}
然而,两者都需要将整个数据集具体化为内存中(或至少在磁盘上)的一个文件。有没有办法避免这种情况?
我的申请: 我正在处理一个巨大的 LAS 点云(数 TB,所有内容都平铺在 100 MB 的文件中)和相应的栅格数据集(大约 100 GB),例如高分辨率地形模型。我通常处理小部分(通过空间多边形 [.shp/.kml] 分隔)或整个 LAS 切片。这在 lidR 中非常节省内存,只加载必要的图块:
# load several TB las tiles as catalog (only file-paths and metadata)
las_data = catalog("D:/FOLDER/WITH/11TB/OF/LAS/TILES")
# load polygon of region of interest
region_of_interest = readOGR("D:/EG/SHP/FILE/OF/ROI")
# cut out the portion of las_data overlapping the polygon
# this will load only the required tiles in memory
las_data_roi = clip_roi(las_data, extent(region_of_interest ))
# ... and create a DTM for example
dtm_roi = grid_terrain(las_data_roi , algorithm = kriging(k = 10L))
我想对栅格数据集执行相同的操作:
# load raster dataset only as pointers to files (and metadata such as extent)
raster_data = raster("D:/FOLDER/WITH/LOTS/OF/RASTER/TILES")
# e.g. crop from mosaic without having to call mosaic/merge first
# avoiding having a huge single file/reading the whole dataset
raster_roi = crop(raster_data, roi)
我通常使用 raster 包,但它似乎没有提供任何此类功能。
您应该查看 terra
包,它通过虚拟栅格图块 (VRT) 提供了您正在寻找的功能。我们可以使用它们将磁盘上的一组光栅文件视为单个光栅文件,同时利用 API 来完成大部分与通过 raster
包可以完成的任务相同的任务。
首先,让我们使用直接来自 ?terra::vrt()
文档的示例创建一个包含 4 个栅格的样本。
library(terra)
r <- rast(ncols=100, nrows=100)
values(r) <- 1:ncell(r)
x <- rast(ncols=2, nrows=2)
filename <- paste0(tempfile(), "_.tif")
ff <- makeTiles(r, x, filename)
ff
#> [1] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_1.tif"
#> [2] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_2.tif"
#> [3] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_3.tif"
#> [4] "/var/folders/b7/_6hwb39d43l71kpy59b_clhr0000gn/T//RtmpACJYNv/filedf6b65d4fca4_4.tif"
现在,我们再次将它们作为 VRT 读入,直接来自同一示例。这允许
vrtfile <- paste0(tempfile(), ".vrt")
v <- vrt(ff, vrtfile)
head(readLines(vrtfile))
#> [1] "<VRTDataset rasterXSize=\"100\" rasterYSize=\"100\">"
#> [2] " <SRS dataAxisToSRSAxisMapping=\"2,1\">GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]</SRS>"
#> [3] " <GeoTransform> -1.8000000000000000e+02, 3.6000000000000001e+00, 0.0000000000000000e+00, 9.0000000000000000e+01, 0.0000000000000000e+00, -1.8000000000000000e+00</GeoTransform>"
#> [4] " <VRTRasterBand dataType=\"Float32\" band=\"1\">"
#> [5] " <NoDataValue>nan</NoDataValue>"
#> [6] " <ColorInterp>Gray</ColorInterp>"
v
#> class : SpatRaster
#> dimensions : 100, 100, 1 (nrow, ncol, nlyr)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326)
#> source : filedf6b216a737.vrt
#> name : filedf6b216a737
#> min value : 1
#> max value : 10000
现在,我们可以创建一个简单的示例多边形来将我们感兴趣的区域限制在 -180 到 180 到 -90 到 90 经度之间。
library(sf)
pl <- list(rbind(c(-90,-90), c(-90,90), c(90,90), c(90,-90), c(-90,-90)))
roi <- st_sfc(st_polygon(pl), crs = "EPSG:4326")
crop(v, roi)
#> class : SpatRaster
#> dimensions : 100, 50, 1 (nrow, ncol, nlyr)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -90, 90, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326)
#> source : memory
#> name : filedf6b216a737
#> min value : 26
#> max value : 9975