使用ArcGIS Desktop查找栅格中最大值的位置?


12

使用ArcGIS 10,我有一个栅格,我想在其中找到栅格中最大值的像素,并以十进制度返回其位置(像素中心)。我想遍历此过程,返回栅格的第二个最高值的位置,然后返回第三个值,依此类推,如此一来,最后我得到了N个位置的列表,这些N个位置的栅格值最高。

我认为使用Python脚本最容易做到这一点,但是如果有更好的方法,我愿意接受其他想法。


您是否尝试过将网格转换为点,然后添加X,Y字段并进行排序?
Jakub Sisak GeoGraphics

栅格值是浮点型还是整数型?
ub

@Jakub-不,我没有。我可能只会对点的前1%左右感兴趣,所以我不知道是否值得为所有点添加x,y字段然后进行排序。也许没有更有效的选择?
mga

@whuber-栅格值为浮点型。
mga

@mga,值得一试。转换速度非常快,并且添加XY也是默认工具。删除不需要的记录是直接的操作,所有记录都可以捆绑到一个模型中。只是一个主意。
Jakub Sisak GeoGraphics

Answers:


5

如果您乐于使用R,则有一个名为raster的软件包。您可以使用以下命令读取栅格:

install.packages('raster')
library(raster)
test <- raster('F:/myraster')

然后,当您去查看它时(通过键入test),您可以看到以下信息:

class       : RasterLayer 
dimensions  : 494, 427, 210938  (nrow, ncol, ncell)
resolution  : 200, 200  (x, y)
extent      : 1022155, 1107555, 1220237, 1319037  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs +towgs84=0,0,0 
values      : F:/myraster 
min value   : 0 
max value   : 1 

可能有更好的处理栅格的方法,但是查找所需信息的一种方法可能是找到最大值,获取其矩阵位置,然后将其添加到较低的范围。


1
+1供参考。将栅格读入后R,就可以使用标准R函数或getValues方法来访问像元值。从那里可以直接确定最高值及其位置。
ub

1
感谢您的建议,这就是我最终要做的。与在ArcGIS中进行尝试相比,在R中使用栅格数据包非常容易。我也继续在R中使用其他空间分析,并对结果感到非常满意。很好的建议!
mga

8

可以通过值的前1%的指标网格与经度和纬度网格相结合来获得答案。诀窍在于创建该指标网格,因为ArcGIS(40年后仍是!)没有用于对栅格数据进行排名的过程。

浮点栅格的一种解决方案是迭代,但要快得多。令n为数据单元的数量。值的经验累积分布由所有对(z,n(z))组成,其中z是网格中的值,n(z)是网格中值小于或等于z的像元数。我们得到了一条曲线,该曲线将(-infinity,0)链接到(+ infinity,n),而这是由z排序的这些顶点的序列之外的。因此,它定义了一个函数f,其中(z,f(z))始终位于曲线上。您想在该曲线上找到一个点(z0,0.99 * n)。

换句话说,任务是找到f(z)-(1-0.01)* n的零。使用任何零查找例程(可以处理任意函数:这是不可微的)执行此操作。最简单且通常有效的方法是猜测并检查:最初,您知道z0介于最小值zMin和最大值zMax之间。严格猜测这两者之间的任何合理值。如果猜测太低,则设置zMin = z0; 否则设置zMax = z0。现在重复。您将迅速收敛到解决方案。当zMax和zMin足够接近时,您就足够接近了。保守起见,请选择zMin的最终值作为解决方案:它可能会吸收一些额外的点,以后可以丢弃。有关更复杂的方法,请参见数字食谱的第9章 (链接指向较早的免费版本)。

回顾此算法,您只需要执行两种栅格操作:(1)选择所有小于或等于某个目标值的像元,以及(2)对所选像元进行计数。这些都是最简单,最快的操作。(2)可以作为区域计数或通过从选择网格的属性表中读取一条记录来获得。


7

尽管我的解决方案使用的是GDAL,但我还是这样做的(因此,这不仅适用于ArcGIS)。我认为您可以从ArcGIS 10中的栅格中获取NumPy数组,但我不确定。NumPy提供了简单而强大的数组索引,argsort以及其他。此示例不处理NODATA也不将坐标从投影坐标转换​​为经度/经度(但是使用GDAL随附的osgeo.osr并不困难)

import numpy as np
from osgeo import gdal

# Open raster file, and get GeoTransform
rast_src = gdal.Open(rast_fname)
rast_gt = rast_src.GetGeoTransform()

def get_xy(r, c):
    '''Get (x, y) raster centre coordinate at row, column'''
    x0, dx, rx, y0, ry, dy = rast_gt
    return(x0 + r*dx + dx/2.0, y0 + c*dy + dy/2.0)

# Get first raster band
rast_band = rast_src.GetRasterBand(1)

# Retrieve as NumPy array to do the serious work
rast = rast_band.ReadAsArray()

# Sort raster pixels from highest to lowest
sorted_ind = rast.argsort(axis=None)[::-1]

# Show highest top 10 values
for ind in sorted_ind[:10]:
    # Get row, column for index
    r, c = np.unravel_index(ind, rast.shape)
    # Get [projected] X and Y coordinates
    x, y = get_xy(r, c)
    print('[%3i, %3i] (%.3f, %.3f) = %.3f'%
          (r, c, x, y, rast[r, c]))

为我的测试栅格文件显示以下内容:

[467, 169] (2813700.000, 6353100.000) = 844.538
[467, 168] (2813700.000, 6353200.000) = 841.067
[469, 168] (2813900.000, 6353200.000) = 840.705
[468, 168] (2813800.000, 6353200.000) = 840.192
[470, 167] (2814000.000, 6353300.000) = 837.063
[468, 169] (2813800.000, 6353100.000) = 837.063
[482, 166] (2815200.000, 6353400.000) = 833.038
[469, 167] (2813900.000, 6353300.000) = 832.825
[451, 181] (2812100.000, 6351900.000) = 828.064
[469, 169] (2813900.000, 6353100.000) = 827.514

+1感谢您分享。我不认为无法处理NoData是一种限制:只需在继续操作之前将所有NoData都转换为极负值即可。还要注意,如果发生网格的任何重新投影,答案可能会由于网格的重新采样而改变,因此通常人们不希望在这样的计算过程中自动发生重新投影。相反,可以在以后重新投影报告的坐标。因此,您的解决方案非常通用。
ub

可以通过首先从栅格中获取值NODATA = rast_band.GetNoDataValue(),然后使用NaN值(rast[rast == NODATA] = np.nan)或使用掩码数组rast = np.ma.array(rast, mask=(rast == NODATA)))来实现NODATA处理。更复杂的技巧是argsort设法以某种方式从分析中删除NODATA值,或者如果它们是NaN /掩码的,则只需跳过它们在for循环中。
Mike T
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.