You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Python代码实现QGIS v.kernel.rast多嵌套文件夹批量处理

问题

我使用QGIS 3.40.8,需要实现跨嵌套文件夹结构的核密度计算自动化。我不懂Python,现有代码是基于GUI手动运行v.kernel.rast的QGIS日志由大语言模型生成的单文件夹运行代码。

现有可运行的单文件夹代码

import processing
import os
from qgis.core import QgsRasterLayer

# === Inputs ===
point_layer = 'main_folder/manchester/2018/01/poi.shp'
reference_raster = 'main_folder/manchester/2018/01/lc.tif'
output_dir = 'main_folder/manchester/2018/01/'

# === Bandwidths to test ===
bandwidths = [50, 100, 150, 200]

# === Extract parameters from reference raster ===
print("Extracting parameters from reference raster...")
ref_layer = QgsRasterLayer(reference_raster, "reference")

if not ref_layer.isValid():
    print(f"ERROR: Could not load reference raster: {reference_raster}")
    exit()

# Get extent
extent = ref_layer.extent()
region_extent = f"{extent.xMinimum()},{extent.xMaximum()},{extent.yMinimum()},{extent.yMaximum()} [EPSG:{ref_layer.crs().postgisSrid()}]"

# Get pixel size
pixel_size = ref_layer.rasterUnitsPerPixelX()

print(f"Extracted region extent: {region_extent}")
print(f"Extracted pixel size: {pixel_size}")

# === Kernel density loop ===
for radius in bandwidths:
    output_path = os.path.join(output_dir, f'kernel_bw_{radius}.tif')
    print(f"Processing bandwidth: {radius}...")
    processing.run("grass7:v.kernel.rast", {
        'input': point_layer,
        'radius': radius,
        'kernel': 5,  # Gaussian
        'multiplier': 1,
        'output': output_path,
        'GRASS_REGION_PARAMETER': region_extent,
        'GRASS_REGION_CELLSIZE_PARAMETER': pixel_size,
        'GRASS_RASTER_FORMAT_OPT': 'TFW=YES,COMPRESS=LZW',
        'GRASS_RASTER_FORMAT_META': ''
    })

print("All kernel rasters created.")

文件夹结构

main_folder/
├── city (e.g., rome)/
│   ├── year (e.g., 2018)/
│   │   ├── month (e.g., 11)/
│   │   │   ├── poi.shp
│   │   │   └── lc.tif
│   │   └── 04/
│   │       ├── poi.shp
│   │       └── lc.tif
│   └── 2019/
│       └── 11/
│           ├── poi.shp
│           └── lc.tif
└── london/
    └── 2021/
        └── 03/
            ├── poi.shp
            └── lc.tif

需求

  • 遍历所有符合main_folder/city/year/month/模式的月度文件夹
  • 跳过不包含poi.shp的文件夹
  • 为每个有效月度文件夹运行核密度分析
  • 将输出栅格保存到poi.shp所在的月度文件夹中
  • 文件命名固定为poi.shp(点图层)和lc.tif(参考栅格)

解决方案

修改后的代码会自动遍历嵌套文件夹,处理符合要求的月度目录:

import processing
import os
from qgis.core import QgsRasterLayer

# === 全局设置 ===
main_folder = 'main_folder'  # 根文件夹路径
bandwidths = [50, 100, 150, 200]  # 要测试的带宽值

# === 遍历嵌套文件夹 ===
# 遍历根文件夹下的所有城市目录
for city_name in os.listdir(main_folder):
    city_path = os.path.join(main_folder, city_name)
    if not os.path.isdir(city_path):
        continue  # 跳过非目录文件
    
    # 遍历城市目录下的所有年份目录
    for year_name in os.listdir(city_path):
        year_path = os.path.join(city_path, year_name)
        if not os.path.isdir(year_path):
            continue
        
        # 遍历年份目录下的所有月份目录
        for month_name in os.listdir(year_path):
            month_path = os.path.join(year_path, month_name)
            if not os.path.isdir(month_path):
                continue
            
            # 检查当前月份目录是否包含必要文件
            poi_path = os.path.join(month_path, 'poi.shp')
            lc_path = os.path.join(month_path, 'lc.tif')
            
            if not os.path.exists(poi_path):
                print(f"跳过目录:{month_path} - 未找到poi.shp")
                continue
            
            if not os.path.exists(lc_path):
                print(f"跳过目录:{month_path} - 未找到lc.tif")
                continue
            
            # === 提取参考栅格参数 ===
            print(f"正在处理目录:{month_path}")
            ref_layer = QgsRasterLayer(lc_path, "reference")
            
            if not ref_layer.isValid():
                print(f"错误:无法加载参考栅格 {lc_path}")
                continue
            
            extent = ref_layer.extent()
            region_extent = f"{extent.xMinimum()},{extent.xMaximum()},{extent.yMinimum()},{extent.yMaximum()} [EPSG:{ref_layer.crs().postgisSrid()}]"
            pixel_size = ref_layer.rasterUnitsPerPixelX()
            
            print(f"提取的范围:{region_extent}")
            print(f"提取的像素大小:{pixel_size}")
            
            # === 运行核密度分析 ===
            for radius in bandwidths:
                output_path = os.path.join(month_path, f'kernel_bw_{radius}.tif')
                print(f"处理带宽:{radius}...")
                processing.run("grass7:v.kernel.rast", {
                    'input': poi_path,
                    'radius': radius,
                    'kernel': 5,  # 高斯核
                    'multiplier': 1,
                    'output': output_path,
                    'GRASS_REGION_PARAMETER': region_extent,
                    'GRASS_REGION_CELLSIZE_PARAMETER': pixel_size,
                    'GRASS_RASTER_FORMAT_OPT': 'TFW=YES,COMPRESS=LZW',
                    'GRASS_RASTER_FORMAT_META': ''
                })
            
            print(f"{month_path} 处理完成\n")

print("所有核密度栅格生成完成。")

关键修改说明

  • 嵌套遍历逻辑:使用三层循环依次遍历城市、年份、月份目录,确保覆盖所有符合main_folder/city/year/month结构的文件夹
  • 有效性检查:进入每个月份目录后,先检查poi.shp和lc.tif是否存在,不存在则直接跳过该目录
  • 动态路径生成:所有文件路径(点图层、参考栅格、输出文件)都基于当前月份目录动态生成,无需手动指定单个路径
  • 错误处理增强:对参考栅格加载失败的情况增加跳过逻辑,避免单个目录出错导致整个程序终止

内容的提问来源于stack exchange,提问作者Nikos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:05:55