天天看點

使用python建立arcmap腳本工具起因

ArcGIS中建立Python腳本工具

  • 起因
    • 腳本實作
    • 工具腳本建立

起因

ArcMap中本身就已內建了非常豐富的工具庫,但有時候由于一些特殊的使用需求,我們需要建構更适用于目前項目的工具。最近由于項目中需要計算多幅栅格影像的衆數,查了查已有的工具發現栅格計算中發現隻有較為常見的最大值、最小值、平均值等函數,于是決定自己寫個腳本來做個定制化工具。

腳本實作

求取多幅栅格影像的衆數的代碼如下,主要用到了numpy、gdal和arcgis自帶的arcpy這三個庫:

# -*- coding: utf-8 -*-
import arcpy
import os
import numpy as np
import gdal
import sys
from gdalconst import *
#Create a tool box for calculating mode number of rster datasets



#查詢目前檔案夾下所有同類型字尾名的檔案
def Search_File(BaseDirectory,fileType,filelist=None):
   if filelist is None:
       filelist=[]
   file=os.listdir(BaseDirectory)
   for i in file:
      x=BaseDirectory+'\\'+i
      if os.path.isdir(x):
         Search_File(x,fileType,filelist)
      elif os.path.isfile(x):
         if os.path.splitext(x)[1]==fileType:
            filelist.append(x)
   return filelist

#gdal庫讀取栅格資訊
def Readinfo(RasterFile):
    ds = gdal.Open(RasterFile,GA_ReadOnly)
    if ds is None:
        print 'Cannot open ',RasterFile
        sys.exit(1)
    cols = ds.RasterXSize
    rows = ds.RasterYSize
    band = ds.GetRasterBand(1)
    noDataValue = band.GetNoDataValue()
    projection=ds.GetProjection()
    geotransform = ds.GetGeoTransform()
    return rows,cols,noDataValue,geotransform,projection

#gdal庫儲存栅格影像
def WriteGTiffFile(filename, nRows, nCols, data,geotrans,proj, noDataValue, gdalType):
    format = "GTiff"
    driver = gdal.GetDriverByName(format)
    ds = driver.Create(filename, nCols, nRows, 1, gdalType)
    ds.SetGeoTransform(geotrans)
    ds.SetProjection(proj)
    ds.GetRasterBand(1).SetNoDataValue(noDataValue)
    ds.GetRasterBand(1).WriteArray(data)
    ds = None

#Transform raster to 2d array,栅格轉數組
def ras_to_array(ras_list):
    arcpy.AddMessage(u"Transforming raster to 2d array......")
    array_list=[]
    for ras in ras_list:
        nodata=-1
        array=arcpy.RasterToNumPyArray(ras,'','','',nodata)
        array_list.append(array)
    num_array=np.array(array_list,dtype='int8')

    shape=num_array.shape
    res_array=np.full((shape[1],shape[2]),-1,dtype='int8')

    arcpy.AddMessage(u"Calculating ModeNumber of big matrix......")
    #calculate every single array,計算衆數
    for i in range(shape[1]):
        for j in range(shape[2]):
            if np.min(num_array[:, i, j]) < 0:
                continue
            counts = np.bincount(num_array[:,i,j])

            res_array[i,j]=np.argmax(counts)
            print res_array[i, j]
    # np.save('F:\Arcgis_process\Test\modenumber.npy',res_array)
    # np.savetxt('F:\Arcgis_process\Test\modenumber.txt',res_array)
    arcpy.AddMessage(u"Value Calculated!")
    return res_array,ras_list[0]


#numpy to raster,數組轉栅格,arcpy内置方法,對行列數較多的栅格影像來說,容易報記憶體錯誤
def array_to_ras(res_array,ras_info):
    arcpy.AddMessage(u"Converting array to raster......")
    myRaster = arcpy.Raster(ras_info)
    #lower left coordinate
    x=myRaster.extent.XMin
    y=myRaster.extent.YMin
    print myRaster.meanCellWidth,myRaster.meanCellHeight
    myRaster_result=arcpy.NumPyArrayToRaster(res_array,arcpy.Point(x,y),myRaster.meanCellWidth,myRaster.meanCellHeight,-1)
    arcpy.AddMessage(u"Converted over!")
    return myRaster_result

#用gdal庫中的方法實作數組轉栅格
def gdal_array_to_ras(res_array,ras_info,out_name):
    rows, cols, noDataValue, geotransform, projection=Readinfo(ras_info)
    WriteGTiffFile(out_name, rows, cols, res_array, geotransform, projection, -1, GDT_Int16)


#save result結果儲存
def Mode_cal(ras_array,ras_info,out_name):

    result=array_to_ras(ras_array, ras_info)
    result.save(out_name)
    arcpy.AddMessage(u"Exported the image!")


arcpy.env.overwriteOutput = True
#工具箱中傳入的兩個參數
raster_workspace=arcpy.GetParameterAsText(0)
out_name=arcpy.GetParameterAsText(1)

raslist=Search_File(raster_workspace,'.tif')
res=ras_to_array(raslist)
gdal_array_to_ras(res[0],res[1],out_name)
           

工具腳本建立

代碼實作好以後,就可以着手建立工具條了,鑒于腳本工具建立步驟比較簡單我就不做過多贅述了,建立步驟可參照arcgis官方幫助文檔:如何添加腳本工具?,建立腳本工具中需要注意的主要有以下三點:

  1. python腳本中盡量不要出現中文字元,不論是注釋還是檔案名,否則很容易報錯,血淚的教訓;
  2. 有可能的話不要使用自建的包,最好完全使用arcpy中自帶的類和函數,不然會報子產品不存在的錯誤(這點我不清楚為什麼,希望有知道的朋友能解答一下)
  3. 工具界面中輸入項的direction屬性是input,輸出項的屬性是output,千萬不能忘記選擇,并且還要明确自己輸入輸出資料的類型,是檔案還是檔案夾。

以上就是今天實作利用python建立腳本工具的過程與心得,與大家共勉!