Python-在光栅单元上循环,速度非常慢

Python-在光栅单元上循环,速度非常慢,python,numpy,raster,Python,Numpy,Raster,作为不是最精明的python用户,我一直在试图找到一种解决方案来加速我的代码。 我有两个光栅文件,都有相同的尺寸和范围。一个光栅是从激光雷达图像中提取的河流,高程值范围很窄,河流文件中的所有其他值均为0。因此,基本上,除了河流宽度(包含高程数据的像素),99%的河流光栅的值为0。另一个光栅文件从激光雷达图像中提取,并在其整个范围内包含高程数据 我的计划是检查河流文件中没有0值的每个像素,向其添加1(如果河流水位上升1米),并将其与相邻的像素高程数据(基本上是激光雷达高程的像素位置)进行比较。如果

作为不是最精明的python用户,我一直在试图找到一种解决方案来加速我的代码。 我有两个光栅文件,都有相同的尺寸和范围。一个光栅是从激光雷达图像中提取的河流,高程值范围很窄,河流文件中的所有其他值均为0。因此,基本上,除了河流宽度(包含高程数据的像素),99%的河流光栅的值为0。另一个光栅文件从激光雷达图像中提取,并在其整个范围内包含高程数据

我的计划是检查河流文件中没有0值的每个像素,向其添加1(如果河流水位上升1米),并将其与相邻的像素高程数据(基本上是激光雷达高程的像素位置)进行比较。如果它更高,则将其值设为1(这意味着该像素被淹没)。 我提出的代码可以工作,但看起来很糟糕,而且速度非常慢(油漆干得比代码运行的速度快…) 所以我在寻找一种加速的方法。我看了矢量化、numpy等,但还没弄明白(可能是因为我已经工作了9个多小时了……)

因此,如果您有任何建议,我们将不胜感激:

river = arcpy.Raster(r'C:\Flood.gdb\Clip_River1')
lidar = arcpy.Raster(r'C:\Flood.gdb\Clip_Lidar_1')

arrayRiver = arcpy.RasterToNumPyArray(river,nodata_to_value=0)
(rHeight, rWidth)=arrayRiver.shape

arrayLidar = arcpy.RasterToNumPyArray(lidar,nodata_to_value=0)
(lHeight, lWidth)=arrayLidar.shape

# extent of the 2 rasters: columns 3822, rows 10129

flood = 1
while flood == 1:   
    flood = 0
    for row in range(0,rHeight-1):
        for col in range(0,rWidth-1):
            if arrayRiver.item(row,col) <> 0 and arrayRiver[row,col] <> 1:
                if arrayLidar[row,col-1] <> 1 and arrayLidar.item(row,col-1) < arrayRiver.item(row,col)+1:
                    arrayLidar[row,col-1] = 1
                    arrayRiver[row,col-1] = arrayRiver.item(row,col)
                    flood = 1

                [....doing the same concept for each possible neighboring pixel]

                if arrayLidar[row+1,col+1] <> 1 and arrayLidar.item(row+1,col+1) < arrayRiver.item(row,col)+1:
                    arrayLidar[row+1,col+1] = 1 
                    arrayRiver[row+1,col+1] = arrayRiver.item(row,col)
                    flood = 1

            arrayRiver[row,col] = 1

newRaster = arcpy.NumPyArrayToRaster(arrayLidar,lowerLeft,cellSize,value_to_nodata=0)
newRaster.save(r"C:\Flood.gdb\newRastaRiver_small")

newEmptyRaster = arcpy.NumPyArrayToRaster(arrayEmpty,lowerLeft,cellSize,value_to_nodata=0)
newEmptyRaster.save(r"C:\Flood.gdb\newEmptyRastaRiver_small")
river=arcpy.graster(r'C:\Flood.gdb\Clip\u River1')
lidar=arcpy.graster(r'C:\Flood.gdb\Clip\u lidar\u 1')
arrayRiver=arcpy.RasterToNumPyArray(河流,节点到值=0)
(rHeight,rWidth)=阵列形式
arrayLidar=arcpy.RasterToNumPyArray(激光雷达,节点数据到值=0)
(lHeight,lWidth)=arrayLidar.shape
#2个光栅的范围:第3822列,第10129行
洪水=1
洪水=1时:
洪水=0
对于范围(0,rHeight-1)中的行:
对于范围(0,rWidth-1)中的列:
如果ArrayVersion.item(行,列)为0,ArrayVersion[行,列]为1:
如果ArrayDar[row,col-1]1和ArrayDar.item(row,col-1)
这只是一个部分答案,但应该让您开始

使用numpy排除(遮罩)所有低值像素

arrayRiver = arcpy.RasterToNumPyArray(river,nodata_to_value=0)
# Create a any array makring pixels less than zero.
mask = arrayRiver > 0
arrayRiver = arrayRiver[mask]
arrayLidar = arrayLidar[mask]

您的arrayRiver&ArrayDar现在应该更小,其余的代码应该更快。顺便说一句,您的示例代码似乎没有生成arrayLidar数组

在做任何应该进行分析的事情之前,先抛出整个if语句,看看代码本机需要多长时间,然后再看看主要瓶颈在哪里。您没有添加单元格的尺寸,因此不清楚瓶颈可能来自何处。我会在gis.stackexchange.com上问这个问题。一般来说,不要在数组中循环。作为一个例子,我最近问了一个问题,关于在没有循环的情况下获取每个元素的所有邻居:好的,我删除了整个if语句,整个代码(包括光栅到阵列语句)在8.2秒内运行。光栅的尺寸是3822列,10129行。在我删除它之前,我让它运行了48(!)小时,最后在光栅上进行了1530次迭代后终止了它。如果arrayLidar[row+1,col+1]1-那是什么?感谢您的输入。我尝试了你的建议,但似乎
arrayRiver=arrayRiver[mask]
行创建了一个列表(如果我错了,请纠正我),我无法再访问它的原始位置(行,列)以将其与lidarArray[row,col]高程进行比较。