我最初会考虑在ArcGIS中使用圆形焦点总和,尽管邻域设置是一个固定值,但不会考虑可变大小的冠状半径。
按像素值“缓冲”像素的好方法是什么?
#1 楼
这是在Python 2.7
中使用numpy
和scipy
的纯光栅解决方案: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
评论
您是否尝试过将栅格转换为点,然后按字段进行缓冲,然后再转换回栅格?它有助于认识到这是一个非本地操作,因为该非本地性表明对如何进行计算存在固有的限制。例如,如果仅将输入中的单个孤立像素更改为较大的值,则您的输出几乎在所有地方都会发生根本变化。因此,如果您知道输入值的限制,请共享它们,因为这可能会导致改进的解决方案。例如,您所有的输入值都将始终位于集合{2,3,4}中吗?
@Dan Patterson这就是我想到右边的图像的方式。但是,我试图完全避免矢量运算,并避免这些步骤。
@whuber此数据集表示树冠直径可变的树木。鉴于此,树冠半径测量值实际上可以在1-10之间变化。我还应该补充一点,如果没有冠冕,则缓冲输出只需要为0,就可以为冠冕存在。
好,谢谢。看起来您是通过将值3的点的3个缓冲区,值4的点的4个缓冲区和值5的点的5个缓冲区联合来创建示例输出的。(您似乎已经忘记了处理具有价值的点2。)该过程不仅可以回答您的问题,而且(我相信)这是使用Spatial Analyst中可用工具的最简单解决方案。