ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

基于LLM智能体的城市遥感图像变化分析系统设计与实现

基于LLM智能体的城市遥感图像变化分析系统设计与实现 城市遥感变化检测这几年几乎是所有测绘院、规划院和卫星应用公司的刚需。但凡是做过实际项目的人都清楚传统流程是把两期影像丢进模型里出一张差分图再人工看一遍写报告过程又慢又费人。我这两年一直在琢磨一件事能不能把“变化在哪”和“为什么变、影响多大、该不该管”这一整条链路交给一个智能体去组织把那些固定套路的事自动化让人只做判断和决策。于是就有了这个基于LLM智能体框架的城市遥感图像变化分析系统。这篇文章把我从架构设计到落地实现的过程、踩过的坑、调过的参都整理出来给想做这个方向的同行一个参考。1. 先想清楚LLM智能体到底解决了遥感变化检测的什么问题1.1 传统变化检测流程的五个真实痛点先说传统流程。以前做一个城市变化监测项目大概是这个节奏拿两期影像做辐射归一化、几何配准然后跑一个变化检测网络输出二值图或者差异图再人工目视解译圈出变化斑块核实属性最后整理成报告。听起来不复杂但实际做起来至少有五个痛点非常要命。第一语义碎片化。像素级的检测结果往往是一片一片的噪声同一个真实变化被切成好几块或者不同性质的微小变化混在一起。每次都要靠人去合并、去分类规则写着写着就成了一堆没人敢动的补丁逻辑。第二后处理链条太长。栅格转矢量、小斑块过滤、形态学运算、边界平滑、属性赋值每一步都有参数参数之间还互相耦合。项目换了数据源整套参数就得重新调一遍。第三阈值选择靠拍脑袋。变化检测模型输出的概率图定多少算变化不同传感器、不同季节、不同城市都不一样。很多项目直接取0.5结果不是漏检就是误报。第四结果不可解释。深度学习模型的输出就是一张图领导问“这个地方为什么算变化”你只能说“模型这么判断的”这在业务上没法落地的。第五报告写作费人力。图斑统计表、位置描述、面积汇总、合规性初判这些工作看起来简单批量起来极其消耗人天。一个城市级项目全手工整理报告大概要占掉三分之一的人力。这些痛点其实指向同一个方向变化检测这个事真正值钱的不是“找出变化”而是“理解变化”。而理解变化恰好是LLM智能体最擅长的事。1.2 LLM智能体切入的三个核心环节LLM智能体不是来替代变化检测模型的它是来接管“组织、理解、输出”这三个环节的。第一个环节叫工具编排。智能体可以根据用户的一句话需求自己决定调哪个数据预处理工具、跑哪个检测模型、做什么后处理而不是像传统pipeline那样写死流程。比如用户说“看看东片区近两年有多少新增建筑”智能体就会规划先按行政区划裁剪影像调用建筑变化模型再做矢量化和面积统计最后结合规划数据判断合规性。第二个环节是语义解读。变化检测模型输出的是栅格和矢量这些几何数据本身没有语义。智能体能结合地理知识、城规知识甚至网络公开信息把“这里有个图斑”翻译成“该地块存在疑似新增工业厂房面积约1.2公顷位于生态控制线内需进一步核实”。第三个环节是报告生成与交互。智能体可以把表格、图例、文字描述、风险提示组织成一份结构化报告并且允许用户追问比如“这个变化区域周边的路网情况怎么样”智能体可以继续调工具查数据而不是重新跑一整套流程。1.3 适用边界别指望它什么都干我必须先泼一盆冷水。LLM智能体不是万能的有些场景它真不适合。适合的场景包括变化检测结果的后处理与语义化、点对点的问答式查询、多源数据的汇总研判、报告草稿生成、阈值的自适应解释等等。不适合的场景也有高精度的像素级定位、实时视频流变化检测、对模型推理速度有硬性要求的在线系统。这些事还是乖乖用传统CV和专用深度学习模型。我现在的产品定位就是“面向分析研判的半自动系统”模型负责干活智能体负责组织干活并解释结果。这个定位切得越清楚落地越顺。2. 系统总体架构与技术选型2.1 核心架构规划—工具—记忆—反思四层我最终采用的智能体架构本质上是一个带工具调用能力的多轮对话系统分为四层。第一层是规划层。智能体接收用户意图后把任务拆解成若干子步骤。这里我初始用的就是ReAct模式的改写版让模型显式地输出“当前目标、下一步动作、调用参数”每一步都落在结构化的JSON里方便程序解析和校验。第二层是工具层。典型工具包括影像检索、栅格裁剪、变化检测推理、矢量后处理、面积统计、地类标签映射、图斑报告生成。每个工具都是独立服务通过统一的OpenAPI规范注册给LLM。实测下来工具命名和描述写得清不清楚直接决定智能体会不会调错工具这块后面细讲。第三层是记忆层。短期记忆用对话上下文长期记忆我引入了两块一块是业务知识库存城市规划控制线、地类分类标准、历史项目报告模板另一块是会话存档同一个地块的多次分析结果可以复用避免重复计算。第四层是反思层。每次工具调用的返回值会经过一个校验器。比如矢量数据面积明显不合理或者坐标系对不上就触发重新规划。这个反思机制在真实项目中救了我很多次。2.2 底层变化检测引擎选型智能体调用的是变化检测引擎引擎本身还是要选对的。我测试过好几条路线。最简单的是像素级差分法比如影像差值加阈值分割优点是快、无需标注缺点是对辐射差异极其敏感两期影像光照稍有不同整个城市都在“变化”。除非数据源高度一致否则不做首选。实用路线是孪生网络。两期影像经过共享权重的编码器提取特征再对特征做差异增强最后解码成变化概率图。代表性的结构有SiamCRNN、SiamU-Net这类。我在项目里用的基线是SiamU-Net的改进版在自建的城市变化数据集上mIoU大概能到0.71左右基本满足业务初筛要求。如果想追求精度更高可以换基于Transformer的ChangeFormer或者带注意力融合的模型对小目标变化敏感度会高一些但是计算量也上来了。一个1024×1024的影像patch在单张消费级显卡上可能要跑2-3秒全城推理要算好时间预算。我在真实项目里做了一个折中先用SiamU-Net出概率图再用一个轻量的地物分类模型给变化区域打标签比如区分建筑、道路、植被、水体。这样一个模型管“变没变”一个模型管“变成什么”配合起来效果好过单模型硬train。2.3 GIS工具层与数据格式中枢整个系统里最容易被低估的就是GIS工具层。很多做AI的人把精力放在模型上结果数据格式一塌糊涂最后分析结果根本导不进ArcGIS。我的建议是统一用GeoJSON作为矢量交换格式栅格统一用GeoTIFF投影信息在每一步都要保留。所有后端处理工具输入输出都走这两个格式。坐标系我内部统一用EPSG:4326的经纬度前端展示再动态转Web墨卡托。为什么不用投影坐标系因为影像原始数据五花八门有的地方是高斯投影有的是UTM统一转WGS84经纬度最保险虽然面积计算要重新换算但不会出大错。工具层还用到了PostGIS做空间查询。变化图斑入库后跟控制线、用地红线、生态保护区做空间叠加分析这一步交给空间数据库比让模型自己算靠谱得多。2.4 LLM选型与工具调用方式LLM选型我前前后后测了三种路线。第一是纯闭源大模型直接调API效果最好函数调用能力最稳但是数据出域很多政务客户不接受项目直接毙掉。第二是私有化部署开源模型数据不出域但函数调用能力弱稍微复杂一点的参数嵌套就漏参数比如让它调一个裁剪工具五个参数能漏俩。第三是混合模式本地部署一个小模型做意图识别和参数洗牌核心分析调用云端大模型。这个方案数据合规性可以解释效果也过得去我目前部署默认用这个。不管哪种模式工具调用的核心机制都差不多把每个工具的入参、出参、用途写成一个JSON Schema塞进上下文里让模型输出结构化的调用指令然后由程序去执行执行结果再回传给模型。这块比让模型直接生成Python代码要稳得多因为代码执行风险高还要多一道沙箱收益却不明显。3. 关键实现细节与代码级拆解3.1 数据准备裁剪、对齐、辐射归一化三步走影像预处理这个阶段80%的变化检测效果都取决于它。很多模型精度不够其实是数据没对齐。第一步裁剪。原始影像动不动就是上万像素宽直接丢进模型显存直接爆掉。要按512×512或者1024×1024的patch切patch之间保留50像素的重叠防止变化目标恰好被切在边界上。第二步对齐。两期影像要用同名点做二次配准我用的是基于特征匹配的自动配准再检查像元级对齐精度。如果配准误差超过一个像元后续像素级对比就基本没意义。第三步辐射归一化。这个坑太典型了。两期影像拍摄季节不同、传感器不同灰度分布差异巨大。我用的是直方图匹配加线性回归校正把参考影像的辐射特征调整到与基准期一致。做完这步识别出的“变化”才是真实变化而不是光照变化。代码上核心就是两段。一段做配准我是用rasterio读取影像、OpenCV提取特征、计算单应矩阵重采样这个流程不多说。一段做辐射校正我直接贴个简化版示意import numpy as np from skimage.exposure import match_histograms def radiation_normalize(base, target): # 将target影像的直方图匹配到base影像 matched match_histograms(target, base, channel_axis-1) return matched.astype(np.uint16)实际项目里我还会加一个掩膜把云、云影和水体区域先抠出来不参与校正不然这些地物的直方图会拖累全局统计。3.2 变化检测推理与后处理从概率图到干净图斑模型推理本身没什么特别就是把两期影像patch喂进去拿到变化概率图。真正的功夫在后处理。我后处理的顺序是概率图阈值分割→连通域分析→小斑块过滤→形态学平滑→栅格转矢量→边界简化。阈值这块我不用固定0.5而是用Otsu算法自适应确定或者根据类别频率动态调整。一个我总结的小经验城市区域建筑变化概率图的分布往往呈双峰Otsu的效果远好于固定阈值而道路变化概率图是单峰长尾需要人工指定一个较低的阈值比如0.35否则漏检严重。后处理核心代码示意import cv2 import numpy as np from shapely.geometry import shape from rasterio.features import shapes def postprocess(prob_map, threshold0.5, min_area_px200): binary (prob_map threshold).astype(np.uint8) # 形态学开运算去噪 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) binary cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations2) # 连通域过滤 num, labels, stats, _ cv2.connectedComponentsWithStats(binary) keep np.zeros_like(binary) for i in range(1, num): if stats[i, cv2.CC_STAT_AREA] min_area_px: keep[labels i] 1 return keep这一步之后我才把栅格转成矢量。转矢量用rasterio的shapes函数输出GeoJSON然后做坐标转换把像素坐标转换为地理坐标。这里要注意输出的多边形边界往往是锯齿形的我会用Douglas-Peucker做一次简化容差根据出图比例尺设一般设3到5米。3.3 智能体工具注册与分析链路实现工具注册是整个智能体框架能不能跑通的关键。在每个工具的定义里描述要写得像给实习生下指令一样清楚包括它做什么、输入输出是什么、常见误区是什么。比如裁剪工具的描述我这么写{ name: crop_raster_by_geojson, description: 用GeoJSON范围裁剪GeoTIFF影像返回裁剪后的GeoTIFF路径。注意GeoJSON必须为EPSG:4326坐标影像路径须来自影像检索工具。, parameters: { type: object, properties: { input_path: {type: string, description: 输入GeoTIFF路径}, aoi: {type: object, description: GeoJSON Polygon对象}, output_path: {type: string, description: 输出GeoTIFF路径} }, required: [input_path, aoi, output_path] } }画重点描述里一定要写“从哪里拿这个参数”比如“路径须来自影像检索工具”这样能显著减少LLM乱传路径的问题。这是我从一个真实bug里悟出来的当时模型把用户随口说的一句地名当成了文件路径分析直接跑飞加了这句约束后类似问题少了很多。智能体的主循环核心逻辑如下def agent_loop(user_query, available_tools, max_steps8): messages [{role: system, content: SYSTEM_PROMPT}] messages.append({role: user, content: user_query}) for step in range(max_steps): resp llm_chat(messages, toolsavailable_tools) if resp.tool_calls: for call in resp.tool_calls: result execute_tool(call.name, call.arguments) messages.append(tool_result_message(call.id, result)) else: return resp.content return 已达到最大步骤数中止。每一步工具结果回传后模型会决定是继续调用下一步工具还是直接生成最终回答。我在几个月度项目里观察平均一个完整的地块变化分析任务需要4到7次工具调用。3.4 提示词设计与多轮状态管理提示词设计这事容易被当成写作文其实它是工程。我的系统提示词固定分四块角色设定、工具使用规则、分析流程规范、输出格式规范。角色设定不要写“你是遥感专家”这种空话要写“你是城市遥感变化分析助手负责组织工具完成分析并解释结果”。工具使用规则里有一条很关键一次只调用一个工具等结果返回后再决定下一步。如果让它一次并行调多个工具参数混乱的概率会直线上升。输出格式规范也要明确。我对变化分析报告规定了固定的markdown结构摘要、变化区域列表、图斑明细表、风险研判、建议复核清单。模型如果自由发挥报告格式每次都不一样下游没法接。多轮状态管理我踩过一个坑用户意图变化后上一轮的工具结果还堆在上下文里模型容易串。解决方案是每轮对话前做一次历史压缩把已经完成的工具调用结果摘要化只保留关键数值比如“建筑新增总面积3.2公顷已提取图斑12个”而不是堆完整的GeoJSON。这样既省token也防止串数据。4. 实操过程一个城市地块的完整变化分析演示4.1 场景设定与数据情况拿一个我做过测试的模拟项目X来说。数据是某城市高新区一块约4平方公里的区域两期高分影像间隔两年。一期是六月份拍的二期是同年份另一天的不同时段包含云量很少地物有建筑新建、裸土翻整、道路拓宽等变化。我要求智能体完成以下任务识别新增建筑区域、评估对周边生态控制线的影响、生成变化分析简报。用户原始输入就一句话“高新区西北片区两年内新增了哪些建筑有没有越线的给我出一份简报。”4.2 智能体完整工作流演练整套工作流我一步步拆给你看。第一步意图解析。LLM把用户问题拆成子任务清单检索两期影像、裁剪AOI区域、执行变化检测、提取新增建筑类变化图斑、与生态控制线叠加分析、生成简报。这六步会被动态编排而不是全部执行。第二步影像检索。LLM调用imagery_search工具范围设置为高新区西北片区、获取时间为两个年份。影像检索返回两个GeoTIFF路径。这里注意LLM自己不会判断影像是否含云工具层在返回时自动带上云量检查结果。第三步裁剪与预处理。LLM调用crop工具和normalize工具。normalize返回的辐射统计信息显示两期影像直方图相关性0.92符合处理要求。第四步变化检测推理。LLM调用change_detect工具模型输出概率图后后处理模块自动生成图斑矢量。工具返回的信息不是完整GeoJSON而是摘要图斑数27个总面积3.8公顷置信度均值0.86。第五步地类分类。LLM发现用户关心“建筑”所以接着调用land_cover_classify工具给27个图斑打地类标签。结果显示新增建筑类图斑13个面积2.4公顷。第六步叠加分析。LLM调用spatial_overlay工具把这些图斑与生态控制线叠加。工具返回其中有2个图斑面积0.3公顷与生态控制线范围相交属于疑似越线。第七步生成简报。LLM整合所有结果输出一份带表格的markdown报告。这一步一步你可能会问是不是太慢了实测下来从提问到拿到完整简报耗时约1分20秒。其中变化检测推理占了大头大约50秒LLM规划加工具调用本身只占20多秒。和人工流程相比这个速度已经快了一个数量级。4.3 输出内容形式与人工复核闭环智能体最终生成的简报长这样开头一段摘要概述区域内新增建筑主要分布方向中间是变化图斑明细表每一行包含图斑编号、面积、地类、是否越线再往下是空间分析结论重点标出越线风险区域最后是一份建议人工复核清单列出需要现场拍照验证的3个图斑。这里我特别想强调人工复核闭环。智能体不是替代人做最终决策的它是把人的注意力引导到真正需要看的地方。我见过很多团队把目标定成“全自动检测、全自动报告”结果模型一出错没人发现最后领导问责。我的方案是所有智能体生成的结论都必须标注置信度低于阈值的图斑自动进入“待现场核实”列表。这样模型有错也只会漏在明面上不会被无声无息地掩盖。5. 常见问题与排查技巧实录5.1 LLM幻觉编造不存在的图斑或面积这个问题在最开始几乎天天碰到。模型在总结时会一本正经地写出“新增建筑面积5.6公顷”之类的数字但你回头对账所有图斑加起来只有2公顷。原因很简单模型不是在计算它是在“生成一个像样的数字”。我的解决办法是强约束工具结果的传递。所有统计数字不从LLM对话里提取而是工具结果里带一段machine-readable的JSON摘要显示给用户看的文本由模板生成。LLM只负责解释和分析不负责编数字。另外我在反思层加了一个校验器每次LLM生成最终回答前会检查它引用的数字是否与工具计算结果一致不一致就打回重写。5.2 坐标对不上图斑飞到十万八千里外这个坑我印象太深了。第一次联调时模型生成的图斑叠加在底图上竟然漂到了几万公里外的海上。排查后发现是工具返回GeoJSON时坐标没做转换一个环节输出的是投影坐标另一个环节按经纬度解析空间关系全部错乱。从此我立了一个铁律所有工具接口的GeoJSON一律EPSG:4326并且在工具描述里高亮强调。另外我在后处理服务的边界上加了个合理性检查输出坐标范围如果超出城市边界范围一定会弹告警。5.3 大影像处理显存不够和推理时间失控城市级影像动辄几十GB直接整景推理根本不现实。我测试过几种切patch的方式最优方案是按固定瓦片网格切而不是滑动窗口切。瓦片网格的好处是结果可缓存下次分析同一区域就不用重算。每个瓦片1024×1024检测模型推理一次2-3秒整个高新区大概400个瓦片并行8卡约15分钟出完整底图。这个速度对离线监测足够用了。实时性需求更强的场景可以降采样到512×512或者干脆只分析用户框选的重点区域不跑全城。5.4 漏检和误检阈值与样本的双重博弈漏检和误检是变化检测永恒的话题。智能体排错时我发现误检的图斑往往集中在影像配准误差大的边缘地区尤其是建筑物立面倾斜产生的鬼影。解决办法是分区设置阈值影像中心区域阈值0.45边缘区域阈值调到0.6。漏检问题更麻烦频繁发生在小目标变化上比如一栋小房子拆除。这类变化像素占比可能只有几十个像素后处理最小图斑面积参数设大了直接过滤掉。我的调试思路是把最小图斑面积参数做成可配置项由智能体根据任务类型自动选择做建筑监测时设300像素做细碎变化监测时设80像素。样本层面实在的办法是持续标注。每季度用智能体筛选出的低置信度图斑做一次人工标注回流微调。我见过很多项目忽略了这一步模型效果随着城市变化越来越差还不自知。5.5 长上下文与工具调用冲突对话一长上下文里堆了几轮工具结果后LLM开始出现“忘事”明明前面已经算过总面积后面又调一次工具重算或者干脆把历史图斑号张冠李戴。我做了三件事一是上文说过的历史摘要压缩二是限定工具调用步骤不超过8次超过就强制输出阶段性小结三是轮次结束时清理临时文件避免脏数据残留影响下一轮分析。这三板斧加上去长会话稳定性改善非常明显。至少在我现在的压力测试里连续10轮对话不串线、不重复计算已经能做到。最后分享一点个人体会做这个系统最大的体会是LLM智能体在遥感里的价值不是让模型变得更强而是让整个分析流程变得像人一样会思考和会沟通。以前做变化检测用户拿到的是一张图和一堆参数现在用户拿到的是能看懂、能追问、能直接辅助决策的结论。这套东西后续还能往两个方向延伸一个是把多源数据接入比如把夜间灯光、POI、路网数据一起喂给智能体做综合研判另一个是端到端微调一个小参数模型把工具调用和领域知识内化进去减少对外部大模型的依赖。如果你也在琢磨这个方向建议从一个小地块、一个明确的监测需求开始先把工具链跑通再去追求规模和智能感。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表