ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

QGIS模型构建器教程:用迭代器实现批量处理自动化

QGIS模型构建器教程:用迭代器实现批量处理自动化 做GIS这行谁没被重复劳动折磨过我印象特别深的是有一年接到一个任务把全市十几个县的DEM统一裁剪到行政边界范围内每个县还要求输出一份坡度统计表。那时候我用的还是最笨的办法一个图层拖进来设好输出路径点一次运行再换下一个连续点了几百次鼠标大半天时间就耗在这上面了。后来我在QGIS里把模型构建器彻底摸熟之后才后知后觉——这种批量活真的不该靠手点应该靠连线。模型构建器Model Designer是QGIS处理框架里自带的可视化建模工具它最大的价值就一句话让你不用写代码也能把一串重复操作打包成交互界面可控的自动化流程。尤其适合那些每天跟矢量、栅格打交道的测绘、规划、地质和科研朋友数据量不大不小写代码又嫌麻烦手工处理又实在浪费时间。这篇文章我会从模型构建器的基础逻辑讲起重点拆解三种迭代器的批量处理玩法最后用一个“批量裁剪DEM并输出坡度统计”的完整案例收尾过程中附带我踩过的坑和排查经验。1. 为什么我要用模型构建器处理批量任务1.1 批量处理的几条常见路线对比QGIS里想批量做事其实不只模型构建器一条路。我先把我自己试过的几种方式摆在一起大家对照着看就知道哪种场景该选哪个。第一是纯手工逐个处理。数据少的时候没什么问题超过二十个文件就开始考验耐心了而且中间一旦换参数前面的活全得重来。第二是处理工具箱里的批量运行界面Batch Process在“处理”面板里右键任意算法选择“批量处理”就能打开一个表格式的运行面板一行一个任务可以手动填参数或者从文件列表加载。这个方式比纯手工好很多但问题也明显参数一多横向拉得很长而且它只能循环同一个算法没法把“裁剪 坡度 统计”这一串动作串成一个流程。第三是写Python脚本。处理工具箱的日志里能看到每个算法对应的PyQGIS代码有基础的话可以把流程写成脚本用for循环控制输入路径。它的上限最高灵活度也最大但对没有编程习惯的朋友来说学习成本不是一天两天能解决的。当初项目催得紧的时候我根本不可能现学Python去写脚本。模型构建器刚好卡在这两者中间。它把算法当成积木块拖进画布用连线把数据流串起来批量处理则是靠“迭代器”实现的相当于在可视化的流程里嵌入了循环逻辑既不写代码又能做到一串操作跑遍所有文件。用熟了以后还能一键导出成Python脚本为将来转脚本开发做过渡。1.2 模型构建器真正解决的是什么问题我理解模型构建器的核心价值不只是“能批量”而是“可复用、可参数化、能共享”。拿我之前做的一批分乡镇土地调查数据来说原始图层几十个处理步骤都是同一套唯一变化的是乡镇名称和对应边界。如果一个个做三天也干不完写成模型之后同事拿过去数据路径换掉参数改一改半小时就能跑完。它能做到这一点是因为模型构建器把几个关键要素整合在了一起。一是封装流水线多个算法串在一起连中间产物都不用管模型会替你管理临时数据。二是变量化每次运行可以弹窗让用户输入参数而不是把路径和阈值写死。三是有迭代器这是批量处理的核心开关模型里不只有一个“文件路径”而是会自动遍历文件夹里的所有文件逐个往下游传。在QGIS 3.x版本里模型构建器默认随QGIS安装不需要额外插件入口在“处理”菜单下的“模型构建器”。我用过的QGIS 3.16、3.28和3.34版本界面细节有点差异但核心逻辑一致下面讲的思路可以通用于这些版本。2. 先弄懂模型构建器的基础逻辑2.1 打开模型构建器认识四个主要区域QGIS菜单栏找到“处理 → 模型构建器”点击后会弹出一个新的模型编辑窗口。第一次打开可能有点懵其实核心区域就四个左侧是算法列表按分类排列可以搜索中间是画布用来摆放算法模块和连线右侧是模型属性面板顶部是菜单和工具栏运行按钮、保存按钮都在那。我习惯先把“处理工具箱”面板和模型构建器窗口并排摆放这样拖算法的时候可以直接从工具箱面板里拖进模型画布不过新版QGIS模型窗口自带算法列表单独操作也够用。画布里最关键的是蓝色的输入框、黄色的算法块、绿色的输出元素。这个配色很直观蓝色代表数据从哪进来黄色代表对数据做了什么绿色代表最终产出什么。2.2 模型的三大要素输入、算法、输出做一个最简单的模型只需要三步。第一步在算法列表里找到一个算法双击或者直接拖进画布。比喻一下算法块就像一台加工机器它需要原料输入也会吐出成品输出。第二步把输入框拖进来。比如你想处理一个属性字段那就添加“矢量图层”输入想手动填一个阈值那就添加“数字”输入。第三步用鼠标从输入框的右侧连线到算法块的左侧接口再从算法块的右侧接口连到输出或下一个算法。这一步看似简单但很多人会卡在“连不上”这个问题上。原因通常是类型不匹配你拖进去的输入是栅格类型而算法接口期望的却是矢量图层。解决办法是在添加输入元素时就把“数据类型”选准确算法接口需要什么你就添加什么类型的输入而不是随便加一个再说。2.3 先拿一个小模型热热身矢量筛选 缓冲光讲概念容易飘我带大家搭一个最基础的小模型把一栋建筑矢量数据里用地类型等于“住宅”的要素挑出来然后再按50米做缓冲区。步骤如下在模型构建器左侧搜索“按属性提取”拖进画布添加一个“矢量图层”输入连接到“按属性提取”的输入接口。双击“按属性提取”的算法块在弹出的参数设置里选择用于过滤的字段和表达式比如用地类型 住宅再搜索“缓冲区”算法拖进画布把“按属性提取”的输出连接到缓冲区输入。最后把缓冲区的输出连接到一个“矢量图层”输出元素。保存模型点运行弹窗会问你要输入哪个图层选好之后点运行结果就加载到QGIS地图里了。这个模型虽然简单但完整走了一遍“输入—处理—输出”的通路。熟悉了这个基础流程接下来加迭代器就顺理成章了。3. 批量处理的核心三种迭代器用法详解3.1 迭代文件批量读入同类型的栅格或文本文件模型构建器里最常用的迭代器叫“迭代文件”(Iterate Files)它在算法列表的“批量处理”分类下。它做的事情很简单遍历某个文件夹里的文件把文件路径逐个传给下游算法。拿批量裁剪DEM来举例。假设D:/DEM目录下放着全省30个县的DEM栅格我想把这30个tif全部裁剪到某个研究区边界范围内。模型的结构就是迭代文件输入目录给出*.tif。然后后面接“按掩膜提取”Clip raster by mask layer算法把迭代出来的文件路径连接到栅格输入接口把固定边界图层连接到掩膜输入接口。这里有一个关键的细节迭代文件输出的不是图层本身而是文件的完整路径字符串。大部分栅格算法能直接接受文件路径作为输入所以连线能够成功。但如果你想在同一个模型里对每个文件做多步处理路径字符串就要一级一级地往下传不能断开。3.2 迭代要素类与迭代图层批量处理矢量数据除了迭代文件还有两个常用的迭代工具迭代要素类Iterate Feature Classes和迭代图层Iterate Layers。它们之间的区别我理解成“读文件”和“读内存”。迭代要素类适合遍历某文件夹里的SHP、GeoPackage等矢量文件它输出的也是文件路径。迭代图层则适合遍历当前QGIS工程中已经加载的图层包括临时图层、数据库图层。你这边打开了一个包含多个分县边界的GeoPackage想对里面每一层的要素做面积计算用迭代图层就比迭代要素类方便得多因为不需要去设置文件夹路径。实际项目中我经常把“迭代要素类”和“合并/追加”算法组合使用。比如几十个行政村界SHP每个文件里有一套属性表结构我可以用迭代要素类把每个文件读入再连到“合并图层”算法一次性把所有村界拼成一个完整图层。如果不用迭代器这个活就只能手动一个个往“合并图层”里加入极易漏文件。3.3 迭代按要素分组拆分后再批量处理第三种迭代器是“迭代要素分组”Iterate Feature Parts我个人管它叫“按字段拆分循环器”。它不讲文件夹也不讲图层列表而是针对一个大的矢量图层按某个属性字段的不同值把要素拆成多个部分逐个送入下游处理。举个例子你有一份全国重点文物保护单位的点位数据属性里有“省份”字段。你希望按省份拆分后再分别以每个省的点位做最小凸多边形。如果手工来先得分省拆图层拆完几十个省级图层再重复几十次凸包运算。用模型构建器就不一样添加一个矢量图层输入连到“迭代要素分组”设置分组字段为“省份”迭代器的输出再连到“凸包”算法。模型运行时它会自动把每个省的点位作为一个子集合分别计算凸包。这个迭代器在处理“先分组、再批量”的场景时非常犀利。但使用中要特别留意迭代输出的名称和顺序因为如果你后续想用“省份”字段给输出文件命名就必须通过表达式把字段值提取出来再接字符串拼接。3.4 三种迭代器的适用场景速查为了让大家一眼看清差异我把三种迭代器的选择建议整理成一个表。迭代器循环对象典型使用场景输出类型迭代文件文件夹内特定类型的文件批量裁剪多个tif影像、批量转换CSV、批量读取LAS点云文件路径字符串迭代要素类文件夹或数据库内的矢量文件批量拼接SHP、统一调整投影、批量统计各图层字段文件路径字符串或带属性迭代图层当前工程已加载的图层多个已打开图层统一处理比如批量导出图斑图层对象迭代要素分组单个矢量图层按字段拆分后的子集按省/县/分类拆分后分别做缓冲区、统计分析、专题制图子集要素这个表我放在手边已经很久了每次拿不准用哪个就照着看一眼基本不会错。4. 完整实操批量裁剪DEM并输出坡度统计结果4.1 案例需求与工具选型为了把前面这些概念串起来我拆一个自己实际做过的案例一批分县DEM栅格共12个tif分别对应12个县城区域。我的任务有两步第一步用各县域范围矢量边界去裁剪DEM只保留县域内的地形第二步对裁剪后的每个DEM计算坡度并统计每个县域内的坡度平均值输出一张汇总表。工具选型上我建议按这个组合裁剪用“按掩膜提取”坡度用“坡度算法”分区统计用“分区统计”Zonal Statistics。为什么不用“裁剪栅格”Clip raster by polygon因为“按掩膜提取”能更好地控制像元大小、对齐方式在批量处理中结果更稳。4.2 建模过程迭代文件 裁剪 坡度 分区统计打开模型构建器我逐步操作一次。第一步在左侧搜索“迭代文件”拖进画布设置迭代目录为D:/DEM文件名模式填*.tif。这里提醒一句如果目录下既有tif还有其它格式一定要用通配符过滤否则迭代器会把文件夹里每个非隐藏文件都传给下游算法必报错。第二步搜索“按掩膜提取”拖进算法画布。双击打开参数设置输入栅格选择迭代器的输出文件路径遮罩图层我们设为模型输入参数稍后运行时选择。提取范围默认是“遮罩层范围”也可以选“输入图层范围”或“交集范围”我习惯用遮罩层范围这样裁剪后的影像刚好贴合矢量边界。第三步在被裁剪的结果后面接“坡度”算法。在模型构建器里按掩膜提取的输出会自动成为坡度算法的栅格输入不需要二次选择。坡度格式一般选“度”或“百分数”这里选度。第四步接“分区统计”算法。分区统计需要一个统计区域矢量图层和一个数值栅格。栅格输入就是坡度结果矢量统计区域我直接复用第二步的遮罩图层。在参数面板里把统计内容选为一次性统计所有波段统计量勾选“均值和范围”输出表格设为D:/DEM_Result/stats.csv。这一步的关键是为了让每个县的结果分开理论上需要对每个县的边界作为单独区域统计这里我假设分县的DEM已经和分县边界一一对应实际运行时我们选择对应的边界图层。4.3 输入文件名变量与输出路径的设置技巧模型搭建到一半最容易懵的地方是怎么让每个迭代出来的文件输出成不同名字的文件而不是所有结果都写进同一个文件QGIS模型构建器里如果你在输出路径里直接填一个固定路径比如D:/DEM_Result/clip.tif那么迭代第二次时就会覆盖第一次的结果。正确做法是把输入文件路径中的文件名部分提取出来再做拼接。我试过两种稳定的方法。第一种是直接在下游算法的输出参数编辑器里点开“表达式”或“值”后面的下拉箭头选择“文件路径基础名称”这个预定义函数。它能从完整路径里把不带扩展名的文件名提取出来。然后你在输出路径里写成类似这样的表达式concat(D:/DEM_Result/, filename_base, _clip.tif)第二种更灵活就是在上游先加一个“根据路径提取基础名称”的算法把迭代文件的路经转换成纯文件名再把这个文件名作为变量传入后续输出参数。这两者的本质都是“提取变量 → 拼接路径”区别只是前者在参数面板里完成后者在流水线里显式建模。这个环节我一开始没重视导致第一次跑模型时只剩最后一个县的裁剪结果前面的全被覆盖了。所以想批量处理名字拼接必须在一开始就想好。4.4 运行模型与查看日志模型搭完之后先别急着全量跑。我用个人习惯做了一次“单文件试探”在运行参数界面里把测试目录临时指向一个只含单个tif的小文件夹先看看流程通不通、字段对不对、结果有没有生成。确认无误后再切回完整目录。点运行按钮后QGIS会弹出运行日志里面会显示每个迭代步骤对应的文件路径和处理结果。如果中间某个文件处理失败日志会用红字标出错误信息。这一步特别有用因为批量处理最怕的是“一次跑到头最后发现半数文件都失败了”。看日志能帮你快速定位是哪个文件、哪个环节出的问题。我这次运行中第一次就报了错分区统计的矢量图层字段名称在裁剪前后不一致。原因是我疏忽了遮罩图层有两个一个是模型参数的输入一个是统计时复用的图层理论上应该同一个但我连的时候连错了分支。日志里反复提示Could not compute之后我才意识到是图层连接乱了。4.5 把模型做成参数化工具分享给同事模型跑通后不要直接关掉窗口。我强烈建议你把输入参数设置为“模型参数”这样保存后的模型在使用时会有更友好的表单界面而不是一堆傻乎乎的变量名。在模型构建器画布里右键每个蓝色输入框选择“模型参数”它就会出现在运行对话框里。你还可以在模型属性里给每个参数写上描述比如“请选择县域边界图层”“请填写DEM目录”。这样哪怕是不懂建模的同事拿到模型也能顺利跑通。保存模型时QGIS有两种做法一是存成.model3文件可以随意拷贝二是在模型构建器中保存到“收藏模型”之后会在处理工具箱的“模型”分类里直接出现随时调用。我一般会把模型文件和配套的示例数据一起压缩存档并在文件名里标注QGIS版本号因为模型格式在不同版本之间偶尔会有兼容性问题。4.6 把模型导出成Python脚本还有一个很多人不知道的功能模型可以直接导出为Python脚本。在模型构建器窗口点击“导出 → 导出为Python脚本”QGIS会把你搭的模型转成一段可执行的PyQGIS脚本。这样做的好处是你可以在外部环境里调参、循环、加判断也可以在更大范围的自动化工作流里复用。我拿这个功能做过一次比较“偷懒”的升级从模型导出的脚本作为底子再把数据路径改成命令行参数配合Windows计划任务每周自动处理一次新到的DEM数据。整个过程没有手写核心算法全靠模型构建器搭出来的流程做骨架。5. 常见问题与实测避坑5.1 迭代器的输出总是连不上后续算法这是模型构建器新手问得最多的问题。原因通常有两个一是迭代器类型与算法接口不匹配二是没有给算法块“就绪”状态。解决办法是双击后续算法块检查被禁用的输入接口或者在算法块右键选择“评估失败时调试”QGIS会帮你标出哪条链路断了。我在实际中还遇到过一个隐蔽问题迭代文件输出的是文件路径而导致后续算法无法识别文件类型比如把LAS文件路径传给DEM算法。就像我听人说“迭代文件管所有文件”其实它本身不管文件类型全依赖你设置的过滤模式和后面驱动它的算法。5.2 中文路径、空格和非法字符引发的报错国内项目里数据路径带中文太常见了。我用QGIS模型构建器处理中文路径的文件有时候能跑通有时候莫名报错翻日志发现是GDAL算法在读写时没有正确处理编码。这跟QGIS版本和操作系统Locale有关不同机器行为还不一致。规避方案一句话项目目录尽量用英文和数字文件夹层级不要太深。如果实在避免不了中文路径建议在数据处理之前写一个Alter Files操作或直接用浏览器把文件批量重命名一遍。另外文件名不要有空格不要有括号和百分号因为这些字符在表达式拼接时可能引发解析问题。5.3 模型第二次运行报“输出已经存在”默认情况下QGIS模型构建器遇到输出文件已经存在可能会直接跳过或弹窗询问在批量循环里弹窗就很麻烦。我遇到过第二次运行时全部跳过的怪现象解决方案在“处理 → 选项 → 常规”里勾选“允许覆盖现有文件”或者在建模时将中间输出设置为临时图层最终输出单独保存。如果是栅格中间文件强烈建议把输出类型设置为“临时文件”。这样每次运行时中间数据自生自灭既省磁盘空间又避免文件名冲突而且整体速度会提升。唯一的风险是如果模型跑挂了中间数据可能没法保留下来排查。5.4 模型运行很慢如何定位瓶颈模型构建器本身不会让算法变慢它会按顺序执行每个步骤。如果你觉得批量处理时间长得离谱先看处理日志里每步的耗时。方法很简单在运行对话框里打开日志面板QGIS会打印每个算法块的实际执行时间。我遇到过几次典型情况一次是迭代文件目录里混进了几万个缩略图文件我被过滤模式坑了以为只处理tif结果某个分支还是把所有文件跑了一遍。另一次是分区统计用了一个几十万面的高精度边界图层每个县的栅格都要和全图求交性能自然差。后来我先用“按范围提取”把统计区域裁剪到栅格外扩范围速度立刻从四十分钟降到五分钟。5.5 可复用的排查清单我把日常排查模型构建器问题的方法整理成清单方便大家在现场排查时对照。现象排查思路解决办法迭代结果全部一样输出路径被固定写死用文件名变量或表达式拼接输出路径批量运行到一半弹窗存在覆盖询问或属性类型不匹配开启允许覆盖检查输入变量类型中文路径报错GDAL编码问题统一用英文路径文件重命名算法块变灰色无法执行上一个输出未成功或类型不匹配查看调用顺序双击算法检查参数状态模型保存后打开找不到版本不同或依赖路径失效重新设置输入路径保存为.model3文件输出CRS漂移对齐选项未设置在栅格算法中统一设定参考系和对齐5.6 安装和版本方面的小提醒有些朋友第一次接触QGIS连软件都装不好。安装这个环节我简单提一句QGIS安装包下载和安装都比较傻瓜但有两个坑值得注意安装路径尽量不要选带中文的目录安装完成后如果打不开先检查显卡驱动再把“设置 → 选项 → 渲染 → 渲染器”切到“软件”模式能解决大部分闪退或黑屏问题。模型构建器和这些底层渲染器关系不大但环境稳定了后面处理才不会莫名奇妙出问题。还有一个使用习惯上的建议如果你在QGIS里加载的在线底图比如常用OSM或天地图服务经常显示不出多半是网络或投影问题不要怀疑是模型构建器挂掉了。模型构建器处理的是本地数据和在线底图没有直接关系。6. 最后再分享一个实用小技巧这是我用模型构建器快三年的一个习惯性操作每次搭完模型我都会保留一个“极简测试版”里面只放一个输入文件、两个核心算法用来快速验证新数据是否符合预期。正式模型跑大批量之前先拿测试版跑一份数据看输出结果、文件命名、字段值有没有问题然后再上全量。这个习惯帮我挡掉过至少五次大规模返工。另外模型构建器其实并不排斥代码。你在画布里搭好的模型导出成Python脚本后还可以顺手加上自动扫描文件列表、断点续跑、写执行日志等逻辑。很多你以为只有程序员才能搞定的自动化用QGIS模型构建器起步一点都不晚。现在每次有朋友跟我说数据处理慢我第一反应还是那句先想想能不能把流程变成模型。
返回列表