左侧的像素代表树的位置及其相关的树冠半径(即像素值范围为2-5)。我想通过它们的冠状半径值来缓冲这些栅格像素。右图是我希望仅使用栅格处理方法来完成的图像。

我最初会考虑在ArcGIS中使用圆形焦点总和,尽管邻域设置是一个固定值,但不会考虑可变大小的冠状半径。

按像素值“缓冲”像素的好方法是什么?



评论

您是否尝试过将栅格转换为点,然后按字段进行缓冲,然后再转换回栅格?

它有助于认识到这是一个非本地操作,因为该非本地性表明对如何进行计算存在固有的限制。例如,如果仅将输入中的单个孤立像素更改为较大的值,则您的输出几乎在所有地方都会发生根本变化。因此,如果您知道输入值的限制,请共享它们,因为这可能会导致改进的解决方案。例如,您所有的输入值都将始终位于集合{2,3,4}中吗?

@Dan Patterson这就是我想到右边的图像的方式。但是,我试图完全避免矢量运算,并避免这些步骤。

@whuber此数据集表示树冠直径可变的树木。鉴于此,树冠半径测量值实际上可以在1-10之间变化。我还应该补充一点,如果没有冠冕,则缓冲输出只需要为0,就可以为冠冕存在。

好,谢谢。看起来您是通过将值3的点的3个缓冲区,值4的点的4个缓冲区和值5的点的5个缓冲区联合来创建示例输出的。(您似乎已经忘记了处理具有价值的点2。)该过程不仅可以回答您的问题,而且(我相信)这是使用Spatial Analyst中可用工具的最简单解决方案。

#1 楼

这是在Python 2.7中使用numpyscipy的纯光栅解决方案:

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

#create tree location matrix with values indicating crown radius
A = np.zeros((120,320))
A[60,40] = 1
A[60,80] = 2
A[60,120] = 3
A[60,160] = 4
A[60,200] = 5
A[60,240] = 6
A[60,280] = 7

#plot tree locations
fig = plt.figure()
plt.imshow(A, interpolation='none')
plt.colorbar()

#find unique values
unique_vals = np.unique(A)
unique_vals = unique_vals[unique_vals > 0]

# create circular kernel
def createKernel(radius):
    kernel = np.zeros((2*radius+1, 2*radius+1))
    y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
    mask = x**2 + y**2 <= radius**2
    kernel[mask] = 1
    return kernel

#apply binary dilation sequentially to each unique crown radius value 
C = np.zeros(A.shape).astype(bool)   
for k, radius in enumerate(unique_vals):  
    B = ndimage.morphology.binary_dilation(A == unique_vals[k], structure=createKernel(radius))
    C = C | B #combine masks

#plot resulting mask   
fig = plt.figure()
plt.imshow(C, interpolation='none')
plt.show()


输入:


输出:


评论


+1为扩张方法!它也适用于近点。

– Antonio Falciano
2014年2月13日在16:01



这是一个很好的例子,说明了旧的喷射色彩设计为何如此糟糕。翠绿看起来更清晰。

–naught101
19年5月1日,1:11

#2 楼

基于向量的方法

可以通过三个步骤完成此任务:


Raster To Point;

Buffer(使用VALUE字段作为缓冲区字段);

Feature To Raster

注意:使用缓冲区字段可避免为每个冠状半径值计算缓冲区。


基于栅格的方法

为了避免基于矢量的解决方案,该问题建议使用一种基于最近邻的元胞自动机。假设所有黑色像素均为零,则将像素平方并且其大小等于1(或适当缩放),采用的规则非常简单:


如果像素值(VALUE)大于1,则其值变为VALUE-1,然后考虑其周围的像素。如果它们的值小于VALUE-1,则这些像素会生成或增长,并且它们的值将变为VALUE-1。否则,这些像素将保留并保持不变。
如果VALUE<=1,则不执行任何操作(像素已失效!)。

必须应用这些规则,直到所有像素都失效为止,即值等于0或1。所以N-1次,其中N是输入栅格中的最大值。
可以用一些Python和numpy轻松实现此方法。

评论


感谢您的回复afalciano。这种方法就是我在右侧创建图像并使用矢量方法的方法-我正尝试避免这种方法。

–亚伦♦
2014年2月10日在18:59

好的,亚伦,这是现在基于栅格的方法。希望这可以帮助。

– Antonio Falciano
2014年2月11日,9:29

#3 楼

另一种选择是为每个像素值创建一个有条件的单独栅格,在这种情况下为4个栅格。然后将栅格扩展对应于栅格值的像素数(可能通过遍历值列表)。最后,加入栅格(代数或空间栅格),为树冠创建一个二进制栅格。

评论


这个想法是正确的。细节可以改进:(1)选择为给定树冠半径的树创建二进制(0,1)指示器。 (2)使用FFT进行计算时,使用给定半径的圆形邻域进行选择的焦点总和很快。 (3)将焦点和(逐点)相加并将其与0进行比较,即可得到所需的缓冲区。

– hu
2014年2月10日在22:57

#4 楼

在栅格中执行此操作是一个具有挑战性的问题,因为您没有机会使用像素值来定义缓冲区的大小。因此,您将需要对每个值进行焦点过滤,就像您已经说过的那样。

这里可能的答案是仅使用3个过滤器(我找不到更少的过滤器),但这并不是很完美正如Whuber所提到的:当树木彼此靠近时,您的缓冲区将被截断。

1)编辑:Euclidian分配(这不能完全解决问题,因为它会剪切附近的缓冲区。较小的树木,但比我的第一个解决方案要好。

2)每个像素周围的欧式距离

3)带有条件语句的栅格计算器(地图代数)

Con("allocation_result" > ("distance_result" / pixel_size) , 1 , 0)


请注意,您可以根据需要调整半径(带或不带中心像素)的条件

评论


+1这是一种创造性的方法。我将进行测试,看看使用这种方法进行扩展是否可行。

–亚伦♦
2014年2月10日在19:06

欧几里得距离方法行不通,因为它仅计算到最近的树的距离,这不一定是到树冠覆盖该点的树的距离。

– hu
2014年2月10日在22:52

#5 楼

想知道为什么不使用ArcGIS的扩展工具吗?

import arcpy
from arcpy.sa import *

raster_in  = r'c:\test.tif'
raster_out = r'c:\test_out.tif'

outExpand1 = Expand(raster_in, 2, 2)
outExpand2 = Expand(outExpand1, 3, 3)
outExpand3 = Expand(outExpand3, 4, 4)
outExpand4 = Expand(outExpand4, 5, 5)

outExpand4.save(raster_out)


如果出现重叠:最新的expand命令将覆盖先前的命令。

#6 楼

如果您有像素位置,则可以使用半径和中点圆算法(不列颠罕算法的一种形式)为您提供线索。 IMO很容易通过这种方法创建多边形,而我认为在Python中实现这一点很容易。这一组多边形的并集为您提供覆盖区域。

评论


我知道这不是问题,但是,您是否想进一步了解图形基元和扫描线多边形填充?对于圆来说,这非常容易。凸组合是个流行词,等等。

– huckfinn
2014年2月10日在21:50



如何使用基本栅格操作来应用?

– hu
2014年2月10日在22:54

如果尝试在栅格空间中处理此问题,请确定圆点,将其按y或x排序,并用直线(扫描线)填充空间,以填充圆。在三角形方法中,如果您通过近似于三角形的扇形来构建圆并尝试填充三角形,则需要测试该点是在内部还是外部(凸组合),否则进行测试。在“ GIS”方法中,构建多边形(按顺时针方向排列的多边形)并使其成为联合体是第三种方法(IMO是计算最昂贵的一种方法)。

– huckfinn
2014-02-10 23:03



需要明确的是:在“ GIS”方法中……进行像代数,交集,接触之类的代数运算……是第三个IMO,计算上最昂贵的一个。

– huckfinn
2014年2月10日23:16