Tôi đã có cùng một vấn đề một vài năm trước đây. Tôi có một giải pháp không yêu cầu dữ liệu LAS được lọc hoặc dữ liệu phụ trợ khác. Nếu bạn có quyền truy cập vào dữ liệu LiDAR và có thể tạo DEM / DSM / DHM (DEM sau đây, tôi không tranh luận về ngữ nghĩa của danh pháp mô hình bề mặt) từ các trả về khác nhau, tập lệnh sau có thể hữu ích.
Kịch bản Arcpy ăn vào 3 DEM và phun ra một hình đa giác rừng và các hình dạng điểm cây. 3 DEM phải có cùng độ phân giải không gian (nghĩa là 1 mét) và phạm vi, và đại diện cho lợi nhuận đầu tiên, lợi nhuận cuối cùng và đất trống. Tôi đã có các thông số rất cụ thể để trích xuất rau, nhưng các thông số có thể được thay đổi để phù hợp với các nhu cầu khác. Tôi chắc chắn rằng quá trình này có thể được cải thiện, vì đây là nỗ lực nghiêm túc đầu tiên của tôi đối với kịch bản python.
# Name: Veg_Extractor.py
# Date: 2013-07-16
# Usage: ArcMap 10.0; Spatial Analyst
# Input: 1 meter DEMs for first returns (DEM1), last returns (DEM2), and bare earth (BE)
# Output: forest polygon (veg with height > 4m) shapefile with holes > 500m removed;
# tree point (veg with height > 4m, crown radius of 9 cells) shapefile
# Notes: Raises error if input raster cell sizes differ
import arcpy, os
from arcpy import env
from arcpy.sa import *
# Check out any necessary licenses
arcpy.CheckOutExtension("spatial")
# Script arguments
dem1 = arcpy.GetParameterAsText(0) #input Raster Layer, First Return DEM
dem2 = arcpy.GetParameterAsText(1) #input Raster Layer, Last Return DEM
bare_earth = arcpy.GetParameterAsText(2) #input Raster Layer, Bare Earth DEM
outForest = arcpy.GetParameterAsText(3) #shapefile
outTree = arcpy.GetParameterAsText(4) #shapefile
# Make sure cell size of input rasters are same
arcpy.AddMessage("Checking cell sizes...")
dem1Xresult = arcpy.GetRasterProperties_management(dem1, "CELLSIZEX")
dem1Yresult = arcpy.GetRasterProperties_management(dem1, "CELLSIZEY")
dem2Xresult = arcpy.GetRasterProperties_management(dem2, "CELLSIZEX")
dem2Yresult = arcpy.GetRasterProperties_management(dem2, "CELLSIZEY")
beXresult = arcpy.GetRasterProperties_management(bare_earth, "CELLSIZEX")
beYresult = arcpy.GetRasterProperties_management(bare_earth, "CELLSIZEY")
dem1X = round(float(dem1Xresult.getOutput(0)),4)
dem1Y = round(float(dem1Yresult.getOutput(0)),4)
dem2X = round(float(dem2Xresult.getOutput(0)),4)
dem2Y = round(float(dem2Yresult.getOutput(0)),4)
beX = round(float(beXresult.getOutput(0)),4)
beY = round(float(beYresult.getOutput(0)),4)
if (dem1X == dem1Y == dem2X == dem2Y == beX == beY) == True:
arcpy.AddMessage("Cell sizes match.")
else:
arcpy.AddMessage("Input Raster Cell Sizes:")
arcpy.AddMessage("DEM1: (" + str(dem1X) + "," + str(dem1Y) + ")")
arcpy.AddMessage("DEM2: (" + str(dem2X) + "," + str(dem2Y) + ")")
arcpy.AddMessage(" BE: (" + str(beX) + "," + str(beY) + ")")
raise Exception("Cell sizes do not match.")
# Check map units
dem1_spatial_ref = arcpy.Describe(dem1).spatialReference
dem1_units = dem1_spatial_ref.linearUnitName
dem2_spatial_ref = arcpy.Describe(dem2).spatialReference
dem2_units = dem2_spatial_ref.linearUnitName
bare_earth_spatial_ref = arcpy.Describe(bare_earth).spatialReference
bare_earth_units = bare_earth_spatial_ref.linearUnitName
if (dem1_units == dem2_units == bare_earth_units) == True:
if dem1_units == "Meter":
area = "500 SquareMeters" #Area variable for meter
unit = 1 #meter
elif (dem1_units == "Foot_US") or (dem1_units == "Foot"):
area = "5382 SquareFeet" #Area variable for feet
unit = 3.28084 #feet in meter
else:
raise Exception("Units are not 'Meter', 'Foot_US', or 'Foot'.")
else:
raise Exception("Linear units do not match. Check spatial reference.")
# Local variables:
(workspace, filename) = os.path.split(outForest)
arcpy.env.workspace = workspace
arcpy.env.overwriteOutput = True
dem1 = Raster(dem1)
dem2 = Raster(dem2)
bare_earth = Raster(bare_earth)
nbr1 = NbrRectangle(3, 3, "CELL")
nbr2 = NbrRectangle(5, 5, "CELL")
nbr3 = NbrCircle(5, "CELL")
# Give units and multiplier
arcpy.AddMessage("Linear units are " + dem1_units + ". Using multiplier of " + str(unit) + "...")
arcpy.AddMessage("Processing DEMs...")
# Process: Raster Calculator (DEM1 - BE)
ndsm_dem1 = dem1 - bare_earth
# Process: Raster Calculator (DEM1 - DEM2)
d1_d2 = dem1 - dem2
# Process: Raster Calculator
threshold_d1d2 = (d1_d2 > (0.1 * unit)) & (ndsm_dem1 >= (4.0 * unit))
# Process: Focal Statistics (max 3x3)
focal_max1 = FocalStatistics(threshold_d1d2, nbr1, "MAXIMUM", "DATA")
# Process: Focal Statistics (majority 5x5)
focal_majority = FocalStatistics(focal_max1, nbr2, "MAJORITY", "DATA")
# Process: Con
con_ndsm_dem1 = Con(ndsm_dem1 >= (4.0 * unit), focal_majority, focal_max1)
focal_majority = None
focal_max1 = None
# Process: Focal Statistics (min 3x3)
focal_min1 = FocalStatistics(con_ndsm_dem1, nbr1, "MINIMUM", "DATA")
con_ndsm_dem1 = None
# Process: Focal Statistics (min 3x3)
veg_mask = FocalStatistics(focal_min1, nbr1, "MINIMUM", "DATA")
# Process: Focal Statistics (max R5)
focal_max2 = FocalStatistics(ndsm_dem1, nbr3, "MAXIMUM", "DATA")
arcpy.AddMessage("Calculating tree points...")
# Process: Raster Calculator
tree_points = (veg_mask == 1) & (ndsm_dem1 == focal_max2) & (ndsm_dem1 >= (4.0 * unit))
ndsm_dem1 = None
focal_max2 = None
# Process: Raster Calculator
tree_pick = Pick(tree_points == 1, 1)
tree_points = None
# Process: Raster to Polygon
arcpy.RasterToPolygon_conversion(tree_pick, workspace + "\\tree_poly.shp", "SIMPLIFY", "Value")
tree_pick = None
# Process: Feature To Point
arcpy.AddMessage("Writing tree points...")
arcpy.env.workspace = workspace #reset workspace
arcpy.env.overwriteOutput = True #reset overwrite permission
arcpy.FeatureToPoint_management(workspace + "\\tree_poly.shp", outTree, "CENTROID")
arcpy.AddMessage("Calculating forest polygons...")
# Process: Focal Statistics (max 3x3)
forests = FocalStatistics(veg_mask, nbr1, "MAXIMUM", "DATA")
veg_mask = None
# Process: Raster Calculator
forest_pick = Pick(forests == 1, 1)
# Process: Raster to Polygon
arcpy.RasterToPolygon_conversion(forest_pick, workspace + "\\forest_poly.shp", "SIMPLIFY", "Value")
# Process: Eliminate Holes > 500 sq m (5382 sq ft)
arcpy.AddMessage("Writing forest polygons...")
arcpy.EliminatePolygonPart_management(workspace + "\\forest_poly.shp", outForest, "AREA", area, "0", "CONTAINED_ONLY")
# Clean up
arcpy.AddMessage("Cleaing up...")
arcpy.Delete_management(workspace + "\\tree_poly.shp")
arcpy.Delete_management(workspace + "\\forest_poly.shp")