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官方幫助文檔:如何添加腳本工具?,建立腳本工具中需要注意的主要有以下三點:
- python腳本中盡量不要出現中文字元,不論是注釋還是檔案名,否則很容易報錯,血淚的教訓;
- 有可能的話不要使用自建的包,最好完全使用arcpy中自帶的類和函數,不然會報子產品不存在的錯誤(這點我不清楚為什麼,希望有知道的朋友能解答一下)
- 工具界面中輸入項的direction屬性是input,輸出項的屬性是output,千萬不能忘記選擇,并且還要明确自己輸入輸出資料的類型,是檔案還是檔案夾。
以上就是今天實作利用python建立腳本工具的過程與心得,與大家共勉!