我有一个栅格(实际上是USGS DEM),我需要将其分成较小的块,如下图所示。这是在ArcGIS 10.0中使用“分割栅格”工具完成的。我想要一个FOSS方法来做到这一点。我看过GDAL,可以肯定会这样做(使用gdal_translate可以做到),但是什么也找不到。最终,我希望能够获取栅格并说出我希望将栅格分成多大(4KM x 4KM块)。
我有一个栅格(实际上是USGS DEM),我需要将其分成较小的块,如下图所示。这是在ArcGIS 10.0中使用“分割栅格”工具完成的。我想要一个FOSS方法来做到这一点。我看过GDAL,可以肯定会这样做(使用gdal_translate可以做到),但是什么也找不到。最终,我希望能够获取栅格并说出我希望将栅格分成多大(4KM x 4KM块)。
Answers:
gdal_translate将使用-srcwin或-projwin选项工作。
-srcwin xoff yoff xsize ysize:根据像素/线的位置从源图像中选择一个子窗口进行复制。
-projwin ulx uly lrx lry:从源图像中选择一个子窗口进行复制(例如-srcwin),但其角在地理参考坐标中给出。
您将需要提出像素/线位置或角坐标,然后使用gdal_translate遍历这些值。如果使用像素值并且-srcwin适合您,则类似于下面的快速且肮脏的python会起作用,使用坐标进行整理会需要更多的工作。
import os, gdal
from gdalconst import *
width = 512
height = 512
tilesize = 64
for i in range(0, width, tilesize):
for j in range(0, height, tilesize):
gdaltranString = "gdal_translate -of GTIFF -srcwin "+str(i)+", "+str(j)+", "+str(tilesize)+", " \
+str(tilesize)+" utm.tif utm_"+str(i)+"_"+str(j)+".tif"
os.system(gdaltranString)
我的解决方案基于@wwnick的解决方案,它从文件本身读取栅格尺寸,并在需要时通过减小边缘瓦片来覆盖整个图像:
import os, sys
from osgeo import gdal
dset = gdal.Open(sys.argv[1])
width = dset.RasterXSize
height = dset.RasterYSize
print width, 'x', height
tilesize = 5000
for i in range(0, width, tilesize):
for j in range(0, height, tilesize):
w = min(i+tilesize, width) - i
h = min(j+tilesize, height) - j
gdaltranString = "gdal_translate -of GTIFF -srcwin "+str(i)+", "+str(j)+", "+str(w)+", " \
+str(h)+" " + sys.argv[1] + " " + sys.argv[2] + "_"+str(i)+"_"+str(j)+".tif"
os.system(gdaltranString)
有一个捆绑的python脚本,专门用于重新整理栅格gdal_retile:
gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeight]
[-overlap val_in_pixel]
[-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
CInt16/CInt32/CFloat32/CFloat64}]'
[ -tileIndex tileIndexName [-tileIndexField tileIndexFieldName]]
[ -csv fileName [-csvDelim delimiter]]
[-s_srs srs_def] [-pyramidOnly]
[-r {near/bilinear/cubic/cubicspline/lanczos}]
-levels numberoflevels
[-useDirForEachRow]
-targetDir TileDirectory input_files
例如:
gdal_retile.py -ps 512 512 -targetDir C:\example\dir some_dem.tif
对于@Aaron,谁问:
我希望找到@wwnick答案的gdalwarp版本,该版本利用-multi选项来增强多核和多线程操作
轻微免责声明
gdalwarp
尽管我不完全相信会有很大的性能提升,但是使用了。到目前为止,我一直受I / O约束-在较大的栅格上运行此脚本并将其切成许多较小的部分,这似乎并不占用CPU,因此我认为瓶颈正在写入磁盘。如果您打算同时重新投影图块或类似图像,则可能会发生变化。有调整提示这里。简短的播放对我没有任何改善,CPU似乎从来不是限制因素。
除了免责声明外,这是一个脚本,可用于gdalwarp
将栅格分割成几个较小的图块。地板分割可能会造成一些损失,但是可以通过选择所需的瓷砖数来解决。这将是n+1
这里n
是让你通过把数tile_width
和tile_height
变数。
import subprocess
import gdal
import sys
def gdalwarp(*args):
return subprocess.check_call(['gdalwarp'] + list(args))
src_path = sys.argv[1]
ds = gdal.Open(src_path)
try:
out_base = sys.argv[2]
except IndexError:
out_base = '/tmp/test_'
gt = ds.GetGeoTransform()
width_px = ds.RasterXSize
height_px = ds.RasterYSize
# Get coords for lower left corner
xmin = int(gt[0])
xmax = int(gt[0] + (gt[1] * width_px))
# get coords for upper right corner
if gt[5] > 0:
ymin = int(gt[3] - (gt[5] * height_px))
else:
ymin = int(gt[3] + (gt[5] * height_px))
ymax = int(gt[3])
# split height and width into four - i.e. this will produce 25 tiles
tile_width = (xmax - xmin) // 4
tile_height = (ymax - ymin) // 4
for x in range(xmin, xmax, tile_width):
for y in range(ymin, ymax, tile_height):
gdalwarp('-te', str(x), str(y), str(x + tile_width),
str(y + tile_height), '-multi', '-wo', 'NUM_THREADS=ALL_CPUS',
'-wm', '500', src_path, out_base + '{}_{}.tif'.format(x, y))
您可以使用GRASS GIS的r.tile。r.tile根据用户定义的前缀为每个带有编号地图名称的图块生成单独的栅格地图。可以定义图块的宽度(列)和图块的高度(行)。
使用草期 Python API,只需几行Python代码即可从外部调用r.tile功能,即编写独立脚本。使用r.external和r.external.out,在GRASS GIS处理步骤中也不会发生数据重复。
伪代码: