基于栅格掩膜用Python程序化检测屋顶是否倾斜的方法
基于Python检测建筑屋顶平坦/倾斜状态的方案
核心思路
利用LiDAR栅格的高程离散程度判断屋顶类型:平坦屋顶的高程值波动极小(标准差低),倾斜屋顶的高程变化明显(标准差高)。同时通过预处理过滤烟囱、水箱等小范围凸起的干扰。
实现步骤及代码
1. 依赖库安装(若未安装)
pip install rasterio fiona numpy scikit-image
2. 完整代码实现
import fiona import rasterio import rasterio.mask import numpy as np from skimage.morphology import opening, square # 配置参数 SHP_PATH = "MyShapefile.shp" RASTER_PATH = "RasterFile.tif" OUTPUT_SHP_PATH = "RoofType_Result.shp" # 标准差阈值:根据实际数据精度调整,值越小判断越严格 STD_THRESHOLD = 0.5 # 形态学操作核大小:用于去除烟囱等小凸起,单位为栅格像素 KERNEL_SIZE = 3 # 读取原shapefile元数据与特征 with fiona.open(SHP_PATH, "r") as src_shp: schema = src_shp.schema.copy() # 添加屋顶类型字段 schema['properties']['roof_type'] = 'str:10' crs = src_shp.crs # 打开LiDAR栅格文件 with rasterio.open(RASTER_PATH) as src_raster: # 写入结果shapefile with fiona.open(OUTPUT_SHP_PATH, "w", driver=src_shp.driver, schema=schema, crs=crs) as dest_shp: # 逐个处理每个建筑多边形 for feature in src_shp: geom = feature["geometry"] # 对单个建筑区域进行掩膜 out_image, _ = rasterio.mask.mask(src_raster, [geom], crop=True, nodata=np.nan) # 过滤无效的空值高程数据 elevation_data = out_image[0][~np.isnan(out_image[0])] if len(elevation_data) == 0: # 无有效高程数据,标记为未知 feature['properties']['roof_type'] = "unknown" else: # 可选:用形态学开运算去除小凸起(烟囱、水箱等) temp_data = out_image[0].copy() temp_data[np.isnan(temp_data)] = 0 cleaned_data = opening(temp_data, square(KERNEL_SIZE)) cleaned_elevation = cleaned_data[cleaned_data != 0] # 计算高程标准差 std_dev = np.std(cleaned_elevation) # 根据阈值判断屋顶类型 feature['properties']['roof_type'] = "flat" if std_dev < STD_THRESHOLD else "sloped" # 将标记结果写入新shapefile dest_shp.write(feature)
关键说明
- 阈值调整:
STD_THRESHOLD需匹配你的LiDAR数据精度,比如数据精度为0.1米时,平坦屋顶的标准差通常在0.3以内,倾斜屋顶会远高于该值。 - 形态学预处理:如果数据中存在大量烟囱、水箱等小结构,开启形态学开运算可有效过滤干扰,避免误判。
- 逐个处理逻辑:相比一次性掩膜所有建筑,逐个处理能精准对应每个多边形的屋顶类型,结果直接写入原shapefile的新字段,方便后续GIS分析。
内容的提问来源于stack exchange,提问作者furbaw
相关产品推荐
相关产品推荐

