如何对非常大的土地覆盖数据集进行分类?


10

考虑阿拉斯加的NLCD2001土地覆盖数据集(下载链接)。我需要对该数据集进行重新分类,以便仅保留值41、42和43的像素;所有其他像素值应变为NoData(如果需要,则为0)。

这似乎是一项简单的任务,只需要调用一次“重新分类”工具即可。不幸的是,每次调用都会导致模糊而无益的错误消息:

Executing: Reclassify "D:\ak_nlcd_2001_land_cover_3-13-08_se5.img" Value "0 40 0;41 41;42 42;43 43;44 255 0;NODATA 0" "D:\alaska_reclassified.tif" DATA 
Start Time: Thu Jan 03 09:23:13 2013
ERROR 999998: Unexpected Error.
Failed to execute (Reclassify).
Failed at Thu Jan 03 09:23:13 2013 (Elapsed Time: 0.00 seconds)

如何对该栅格数据集进行重新分类?我正在使用启用了Spatial Analyst扩展的ArcCatalog 10.0,Build 4000。


按属性提取似乎也可以满足我的需要,但不幸的是会导致另一个“意外错误”。
DoggoDougal

尝试过另一个数据集?两个进程在同一数据集上失败使您感到奇怪...
Chad Cooper

2
通常,这reclassify应该是不得已的做法,因为它的范围如此广泛,以至于它使用的效率可能比重分类容易用算术或逻辑表达的效率低。在当前情况下,重新分类的标准非常简单,您应该首先尝试使用Con甚至是直接的算术运算(因为它们很快)。例如,"grid" * ("grid" >= 41) * ("grid" <= 43)应该这样做。RAM不应成为问题-Spatial Analyst会自动打开其栅格I / O的窗口,这些是本地操作。
whuber

1
Inlist是一个不错的解决方案(+1)。con在操作过程中,我能够使用和监视RAM使用情况。它从未超过180 MB,仅略大于用于启动ArcMap的RAM。ArcGIS中的切片是自动的 -甚至不需要控制它(除非您正在编程C / Fortran界面)。似乎对RAM的限制并不在意。
whuber

1
@whuber,con在这种情况下也为我工作"Value" >= 41 AND "Value" <= 43。我本来会采用这种解决方案,但是我不确定将来是否会关注其他栅格值。显然,我可以OR在where子句中添加一个,但是随后它变得越来越复杂。InList在可读性和可维护性方面,似乎是最直接的解决方案。
DoggoDougal

Answers:


9

第一个附带的脚本在大约15分钟内成功地将AK NLCD数据重新分类(i7,12GB RAM计算机)。由于原始数据集将近7GB,因此您可能会遇到内存问题。如果您无法在一整个块中处理整个数据集,请在重新分类之前尝试使用第二个脚本将其拆分。我的建议是获取一小部分数据(在“目录”>“数据”>“导出数据”>“范围(数据帧)”中单击栅格图层并测试第一个脚本。一旦输入了用于reclassify命令的参数,然后进行重新分类整个数据集或将其拆分。或者,尝试下载适用于ArcGIS 10.1 SP1 的64位背景地理处理产品(请参见此处)

脚本1

# Import system modules
import arcpy
from arcpy import env
from arcpy.sa import *

# Overwrite output
env.overwriteOutput = 1

# Set environment settings
env.workspace = r'C:\temp'
Dir = env.workspace

# Set local variables
inRaster = Dir + "\\" + "nlcd_subset.img"
reclassField = "Value"
remap = RemapValue([[0, 40, 0], [41, 41],[42,42], [43,43], [44, 256, 0]])

# Check out the ArcGIS Spatial Analyst extension license
arcpy.CheckOutExtension("Spatial")

# Execute Reclassify
outReclassify = Reclassify(inRaster, reclassField, remap, "NODATA")

# Save the output 
outReclassify.save(r"C:\temp\nlcd_test.img")

编辑:如果您需要在处理之前拆分数据,此脚本应该可以帮助:

剧本2

# Import system modules
import arcpy
from arcpy import env
from arcpy.sa import *

# Check out the ArcGIS Spatial Analyst extension license
arcpy.CheckOutExtension("Spatial")

# Overwrite output
env.overwriteOutput = 1

# Set environment settings
env.workspace = r'C:\temp'
Dir = env.workspace

# Set local variables
inRaster = Dir + "\\" "nlcd" + "\\" + "nlcd_ak.img"
outFolder = Dir
reclassField = "Value"
remap = RemapValue([[0, 40, 0], [41, 41],[42,42], [43,43], [44, 256, 0]])

# Split Rasters
# Equally split a large TIFF image by number of images
arcpy.SplitRaster_management(inRaster, outFolder, "split", "NUMBER_OF_TILES", "#",
                             "NEAREST", "2 2", "#", "4", "PIXELS",\
                             "#", "#")

# List rasters for processing
rasters = arcpy.ListRasters()


for ras in rasters:
    print "processing..." + ras

    # Define new name
    name = "class_" + ras  

    # Execute Reclassify
    outReclassify = Reclassify(ras, reclassField, remap, "NODATA")

    # Save the output 
    outReclassify.save(Dir + "\\" + name)

3
从性能的角度来看,尝试使用arcpy.RasterToNumPyArray()替代方法并在numpy中进行重分类将很有趣。无论如何,您都可能出于存储目的将栅格拆分为图块,但是我知道使用GDAL,重新分类numpy数组非常快。
DavidF

@DavidF同意,性能可能会大大提高。
亚伦

谢谢您的提示,亚伦。一旦完成另一个变通方法,我将立即运行它,这似乎需要删除色图(在此引用)。此方法还需要拆分栅格,因此我想知道是否由于内存使用或其他原因而导致对原始文档进行重新分类失败。
DoggoDougal

@torik没问题-我很高兴给我两美分。我认为删除颜色图不是要走的路。相反,我将专注于拆分数据或64位后台处理。
亚伦

@Aaron,请牢记您提供了完成平铺的代码,如何创建用于生成图片结果的子集栅格?我已经完成了SplitRaster平铺(产生了整个栅格数据集的100个子集),并试图遍历它们全部以进行重新分类。不幸的是,重新分类失败,导致出现相同的“意外错误”消息。
DoggoDougal

4

Whuber 对使用逻辑工具表达这种重新分类发表了评论。经过一番挖掘,我发现InList作为Spatial Analyst的Logical Math工具集的一部分,满足了我的需求。

import arcpy

# Check out the ArcGIS Spatial Analyst extension license
arcpy.CheckOutExtension("Spatial")
from arcpy.sa import InList

# Pixel values of interest, named according to Table 2 of
#  http://landcover.usgs.gov/pdf/anderson.pdf
DECIDUOUS_FOREST = 41
EVERGREEN_FOREST = 42
MIXED_FOREST = 43

inRaster = r'D:\AK_NLCD_2001_land_cover_3-13-08\ak_nlcd_2001_land_cover_3-13-08_se5.img'
accepted_raster_values = [DECIDUOUS_FOREST, EVERGREEN_FOREST, MIXED_FOREST]
filteredAlaska = InList(inRaster, accepted_raster_values)
filteredAlaska.save(r'C:\alaska\ak_woods')

到目前为止,它是我可以找到的简化列表解决方案,执行速度最快,并且无需考虑汇总原始数据集。无需考虑机器的可用RAM,因为此工具将直接从磁盘读取并将结果直接存储在磁盘上。

使用InList过滤的阿拉斯加结果


+1做得好,很好的解决方案。出于好奇,处理花了多长时间?
亚伦

@Aaron,处理整个阿拉斯加需要13分钟23.4秒。的样本子集,这是由所创建的100相等大小的子集中的一个SplitRaster_management,需要7.04秒。
DoggoDougal

有趣的是,两种方法之间的处理时间大致相同(即假设我们正在运行类似的系统)。
亚伦

我有一个Intel Core 2 Duo E6850 @ 3 Ghz,4GB RAM,运行64位Windows7。我将尽快对您的解决方案进行时序分析。我暂时还停留在Arc 10.0上,否则我将研究64位背景处理。
DoggoDougal

1

我已将原始发布中提到的数据集与arcmap的10.4开发版一起使用。当输出栅格是网格时,重新分类失败,因为重新分类的像元计数溢出了可以存储在网格增值税的COUNT字段中的内容。当输出栅格为fgdb时,它将在运行Windows 8的较旧的4核计算机上在11分钟内成功为我成功执行。非栅格栅格格式应能工作,因为它们对count字段使用双精度浮点值。我希望您应该在10.2或10.3发行版本中得到相同的行为。我们将调查使用不同的栅格格式作为Reclassify的默认输出。

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.