使用GDAL将栅格分割成较小的块?


18

我有一个栅格(实际上是USGS DEM),我需要将其分成较小的块,如下图所示。这是在ArcGIS 10.0中使用“分割栅格”工具完成的。我想要一个FOSS方法来做到这一点。我看过GDAL,可以肯定会这样做(使用gdal_translate可以做到),但是什么也找不到。最终,我希望能够获取栅格并说出我希望将栅格分成多大(4KM x 4KM块)。

在此处输入图片说明


我有一个使用subprocess.Popen的实用程序,它可以同时运行多个gdal转换,用于使用渔网将大栅格提取到图块,特别是在输入和/或输出高度压缩(例如LZW或deflate GeoTiff)时有用),如果两者都没有被高度压缩,则该过程将在HDD访问上达到高峰,并且不会比一次运行一个进程快得多。不幸的是,由于严格的命名约定,它的通用性不足以共享,但无论如何还是值得深思的。GDALWarp的-multi选项通常会引起麻烦,并且仅使用2个线程(一个读,一个写),但并非全部可用。
Michael Stimson

Answers:


18

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)

1
嗨,当我尝试对带有Geotiff图像的-projwin选项进行警告时,会收到警告:“警告:计算出的-srcwin -3005000 1879300 50 650完全落在栅格范围之外。但是,继续进行下去”我不确定我在哪里做错了,似乎并没有使用其地理参考坐标。
ncelik '16

@ncelik可能是因为您在projwin中使用单元格坐标,而应该使用srcwin。如果您遇到困难,请发布一个包含所有相关信息的新问题,以便我们为您的具体问题提供建议。
Michael Stimson

15

我的解决方案基于@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)

我认为应该是sys.argv [1],上面写着sys.argv [2],对吗?
oskarlin '17

3
我相信sys.argv [2]用作输出文件的前缀。超级有帮助-感谢@Ries!
查理·霍夫曼

4

有一个捆绑的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


4

对于@Aaron,谁问:

我希望找到@wwnick答案的gdalwarp版本,该版本利用-multi选项来增强多核和多线程操作

轻微免责声明

gdalwarp尽管我不完全相信会有很大的性能提升,但是使用了。到目前为止,我一直受I / O约束-在较大的栅格上运行此脚本并将其切成许多较小的部分,这似乎并不占用CPU,因此我认为瓶颈正在写入磁盘。如果您打算同时重新投影图块或类似图像,则可能会发生变化。有调整提示这里。简短的播放对我没有任何改善,CPU似乎从来不是限制因素。

除了免责声明外,这是一个脚本,可用于gdalwarp将栅格分割成几个较小的图块。地板分割可能会造成一些损失,但是可以通过选择所需的瓷砖数来解决。这将是n+1这里n是让你通过把数tile_widthtile_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))

3

您可以使用GRASS GIS的r.tile。r.tile根据用户定义的前缀为每个带有编号地图名称的图块生成单独的栅格地图。可以定义图块的宽度(列)和图块的高度(行)。

使用草期 Python API,只需几行Python代码即可从外部调用r.tile功能,即编写独立脚本。使用r.externalr.external.out,在GRASS GIS处理步骤中也不会发生数据重复。

伪代码:

  1. 初始化草场
  2. 使用r.external.out定义输出格式
  3. 用r.external链接输入文件
  4. 运行r.tile,以上面定义的格式生成图块
  5. 取消链接r.external.out
  6. 亲密会议
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.