112 lines
4.4 KiB
Python
112 lines
4.4 KiB
Python
import geopandas as gpd
|
||
import pandas as pd
|
||
import rasterio
|
||
from rasterio.features import rasterize
|
||
import numpy as np
|
||
from shapely.geometry import mapping
|
||
|
||
|
||
def merge_and_rasterize_vectors_two_categories(file_paths, output_vector_path, output_raster_path,
|
||
raster_resolution=30):
|
||
"""
|
||
合并2个矢量图层(forest, water),转为栅格并显示2个类别,保留0值作为背景
|
||
|
||
参数:
|
||
file_paths: 包含2个矢量文件路径的列表 (按顺序: forest, water)
|
||
output_vector_path: 输出合并后的矢量文件路径
|
||
output_raster_path: 输出栅格文件路径
|
||
raster_resolution: 输出栅格的分辨率(默认30米)
|
||
"""
|
||
try:
|
||
# 检查输入文件数量
|
||
if len(file_paths) != 2:
|
||
raise ValueError("请提供正好2个矢量文件路径")
|
||
|
||
# 定义类别映射,按照指定顺序
|
||
categories = ['forest', 'water']
|
||
category_values = {'forest': 1, 'water': 2} # forest=1, water=2
|
||
|
||
# 读取所有矢量文件并添加分类
|
||
gdfs = []
|
||
for i, (path, category) in enumerate(zip(file_paths, categories), 1):
|
||
print(f"正在读取第{i}个矢量文件: {path}")
|
||
gdf = gpd.read_file(path)
|
||
gdf['category'] = category # 添加类别字段
|
||
gdf['value'] = category_values[category] # 添加数值字段用于栅格化
|
||
gdfs.append(gdf)
|
||
|
||
# 检查和统一坐标系(以第一个图层为基准)
|
||
base_crs = gdfs[0].crs
|
||
for i, gdf in enumerate(gdfs[1:], 2):
|
||
if gdf.crs != base_crs:
|
||
print(f"第{i}个图层坐标系不同,正在转换为第一个图层的坐标系...")
|
||
gdfs[i - 1] = gdf.to_crs(base_crs)
|
||
|
||
# 合并所有GeoDataFrame
|
||
print("正在合并图层...")
|
||
merged_gdf = gpd.GeoDataFrame(pd.concat(gdfs, ignore_index=True))
|
||
merged_gdf = merged_gdf.set_geometry('geometry')
|
||
|
||
# 保存合并后的矢量文件
|
||
print(f"正在保存合并矢量结果到: {output_vector_path}")
|
||
merged_gdf.to_file(output_vector_path)
|
||
|
||
# 计算栅格化的范围
|
||
bounds = merged_gdf.total_bounds # [minx, miny, maxx, maxy]
|
||
width = int((bounds[2] - bounds[0]) / raster_resolution)
|
||
height = int((bounds[3] - bounds[1]) / raster_resolution)
|
||
|
||
# 创建栅格化变换
|
||
transform = rasterio.transform.from_bounds(
|
||
bounds[0], bounds[1], bounds[2], bounds[3], width, height
|
||
)
|
||
|
||
# 栅格化:将几何对象转为栅格,使用'value'字段作为像素值
|
||
print("正在将矢量转为栅格...")
|
||
shapes = ((mapping(geom), value) for geom, value in zip(merged_gdf.geometry, merged_gdf['value']))
|
||
raster = rasterize(
|
||
shapes=shapes,
|
||
out_shape=(height, width),
|
||
transform=transform,
|
||
fill=0, # 背景值为0
|
||
dtype=rasterio.uint8
|
||
)
|
||
|
||
# 保存栅格文件
|
||
with rasterio.open(
|
||
output_raster_path,
|
||
'w',
|
||
driver='GTiff',
|
||
height=height,
|
||
width=width,
|
||
count=1,
|
||
dtype=rasterio.uint8,
|
||
crs=base_crs,
|
||
transform=transform,
|
||
nodata=0 # 设置nodata值为0,表示背景
|
||
) as dst:
|
||
dst.write(raster, 1)
|
||
|
||
print("处理完成!")
|
||
print(f"合并矢量保存为: {output_vector_path}")
|
||
print(f"栅格保存为: {output_raster_path}")
|
||
print(f"栅格中类别值: 0=背景, 1=forest, 2=water")
|
||
|
||
except Exception as e:
|
||
print(f"发生错误: {str(e)}")
|
||
|
||
|
||
# 使用示例
|
||
if __name__ == "__main__":
|
||
# 输入2个矢量文件路径(按顺序: forest, water)
|
||
input_files = [
|
||
r"E:\Data\z18\sd\Total_sd\shandonghebingshp\sdshp\forest\sdforest.shp",
|
||
r"E:\Data\z18\sd\Total_sd\shandonghebingshp\sdshp\water\true\shandongsuiyu3.shp"
|
||
]
|
||
output_vector_file = r"E:\njds\shenyang\shengyangshp\kejianshe\merged_vector_forest_water.shp"
|
||
output_raster_file = r"E:\njds\shenyang\shengyangshp\kejianshe\merged_raster_forest_water.tif"
|
||
|
||
# 执行合并和栅格化
|
||
merge_and_rasterize_vectors_two_categories(input_files, output_vector_file, output_raster_file,
|
||
raster_resolution=10)
|