先做JSON Schema校验再反投影,还是把地理参考塞进Prompt让AI直出几何?——一条以“坐标契约”为主线的工程化分析
关键词:FME|AI Connector|JSON Schema|坐标反投影|地理参考|瓦片对齐|空间数据治理
摘要
大范围遥感影像与空间数据的智能化处理,正在从“模型单点推理”走向“平台化流水线”。当AI模型以JSON形式返回检测框坐标、类别与置信度,而下游FME需要把这些结果转成带地理坐标的空间要素并与原始瓦片几何严格对齐时,工程上会立刻撞上一个分岔口:究竟该在AI Connector之后先做JSON Schema校验、再把像素坐标反投影回原坐标系,还是该把瓦片的地理参考信息一并送进Prompt、让模型直接返回带坐标的几何?本文以“坐标契约(Coordinate Contract)”为贯穿主线,系统拆解两条路线的数学本质、误差传播机理、工程成本与可审计性差异,给出可落地的校验清单、反投影公式、FME工作流骨架与性能评估方法,并结合国内外近三年在视觉语言模型空间推理、地理空间JSON标准化、栅格-矢量对齐等领域的研究进展,提出“契约前置、校验分层、几何后置”的混合架构主张。笔者认为,这不是一个二选一的问题,而是一个“谁承担坐标变换责任”的架构决策问题。
目录
一、问题的提出:一个被低估的“坐标责任”分岔口
先把场景说清楚。假设你手上有几百景高分影像,切成了几十万个瓦片(tile),每个瓦片都带着自己的地理参考:左上角原点坐标、像元大小、仿射变换参数、EPSG 编码。AI 模型(可能是目标检测、可能是视觉语言模型)对每个瓦片推理,返回一段 JSON,里面是若干检测框,形如 {"bbox":[x1,y1,x2,y2],"label":"ship","score":0.91}。这些坐标是瓦片内的像素坐标,不是地理坐标。下游 FME 要把它们变成带地理坐标的多边形或点要素,并和原始瓦片的几何严格对齐。
于是就有了那个经典的分岔:路线A——AI Connector 之后先做 JSON Schema 校验,确保结构合法、字段齐全、数值范围合理,然后在 FME 里用瓦片的地理参考把像素坐标反投影回原坐标系;路线B——干脆把瓦片的地理参考信息(原点、像元大小、EPSG)一起写进 Prompt,让模型直接返回带地理坐标的几何。
表面看,这是“在哪一步做坐标变换”的流程偏好问题。但笔者认为,它本质上是一个责任分配问题:坐标变换这个确定性极强的数学操作,究竟应该交给确定性的代码(FME 的转换器、脚本),还是交给概率性的模型(LLM/VLM)?这个问题的答案,决定了整条流水线的误差上界、可审计性和维护成本。
本文评述:很多团队在选型时把这两条路线当成“实现风格”之争,实际上它们对应的是两种完全不同的系统性质——一个是“确定性变换 + 概率性检测”,另一个是“概率性变换 + 概率性检测”。误差结构不同,故障模式不同,审计路径也不同。把它们混为一谈,是后续大量对齐问题的根源。
为了把讨论落到实处,本文不打算泛泛谈“AI+GIS”的宏大叙事,而是死死咬住这条主线:坐标契约。所谓坐标契约,是指“AI 输出与下游消费方之间,关于坐标系、单位、原点、轴向、精度、缺失值语义的一份显式约定”。谁定义契约、谁校验契约、谁执行变换,就是两条路线的真正分野。
二、两条路线的技术解剖:它们到底在做什么
2.1 路线A:校验在前,反投影在后
路线A的流水线是:瓦片 → AI 推理 → JSON(像素坐标)→ JSON Schema 校验 → 坐标反投影 → 空间要素 → 与瓦片几何对齐。它的核心假设是:模型只负责“看见什么”,不负责“在哪里”。模型输出的是图像坐标系下的相对位置,地理化是纯粹的几何变换,由确定性代码完成。
这个假设在传统目标检测里几乎是默认的。YOLO、Faster R-CNN、DETR 系列输出的都是归一化或像素坐标,地理化由后处理完成。近三年大量遥感目标检测研究(如基于 Oriented R-CNN、Rotated FCOS 的旋转框检测)依然遵循这一范式,模型输出旋转框参数,地理化在推理之后统一处理。本文评述:这条路线之所以稳健,是因为它把“概率性”和“确定性”严格分层,模型的不确定性不会污染坐标变换的确定性。
2.2 路线B:地理参考入Prompt,模型直出几何
路线B的流水线是:瓦片 + 地理参考文本 → Prompt → AI 推理 → JSON(地理坐标)→ 校验 → 空间要素。它的核心假设是:模型具备足够的数值推理能力,能在给定仿射参数的情况下直接算出地理坐标。
这个假设在 2023 年之后变得“看起来可行”。视觉语言模型(VLM)在空间推理基准上的表现持续提升,一些研究开始探索让模型直接输出地理坐标或 GeoJSON。但这里有一个容易被忽略的细节:模型做的是“文本里的算术”,而不是“几何库里的变换”。它可能把 x_geo = x0 + col * pixel_size 算对,也可能在长数字、负坐标、大数值时出现精度漂移。更麻烦的是,这种漂移是不可复现的——同样的输入,不同温度参数、不同批次,结果可能不同。
笔者认为:路线B的诱惑在于“一步到位”,但它的代价是把确定性变换交给了概率性系统。对于单张图、少量目标的演示场景,这没问题;对于几十万瓦片的生产流水线,这是把误差源从“可控”变成了“不可控”。
三、坐标契约:贯穿全文的独创分析主线
为了让后面的对比不流于空谈,这里先把“坐标契约”这个概念立起来。它包含六个要素,缺一不可:
这张表看起来朴素,但它是后面所有讨论的锚点。路线A的实质是:契约由 FME 侧定义并强制校验,模型只输出契约中的“像素坐标”子集;路线B的实质是:契约被塞进 Prompt,模型被要求同时输出坐标和遵守契约。前者是“契约在代码里”,后者是“契约在自然语言里”。自然语言的契约,天然是软的。
本文评述:把契约写进 Prompt,本质上是把“接口规范”降级成了“提示词约定”。接口规范可以被 Schema 校验器机械执行,提示词约定只能靠模型“理解”。这不是说路线B一定错,而是说它的可靠性上限受限于模型的指令遵循能力,而这个能力在数值场景下恰恰是最脆弱的。
四、路线A:JSON Schema 校验 + 反投影的完整工程路径
4.1 第一步:定义可校验的 JSON Schema
JSON Schema 是路线A的地基。它要回答三个问题:结构对不对、类型对不对、值域对不对。一个面向检测框的最小 Schema 大致如下(示意,非完整):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["tile_id", "objects"],
"properties": {
"tile_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]+$"},
"objects": {
"type": "array",
"items": {
"type": "object",
"required": ["bbox", "label", "score"],
"properties": {
"bbox": {
"type": "array",
"minItems": 4, "maxItems": 4,
"items": {"type": "number", "minimum": 0}
},
"label": {"type": "string", "minLength": 1},
"score": {"type": "number", "minimum": 0, "maximum": 1}
}
}
}
}
}
注意几个容易被忽略的点:bbox 的 minimum: 0 只能挡住负值,挡不住“超出瓦片宽高”的值;score 的 0–1 范围能挡住明显异常,但挡不住“模型把 logits 直接吐出来”的情况。所以 Schema 校验只是第一层,后面还要有值域校验。
在 FME 里,JSON Schema 校验可以通过 JSONValidator 转换器或 PythonCaller 调用 jsonschema 库完成。FME 官方文档对 JSON 读写与校验有较完整的说明,可参考 Safe Software 的 JSON 教程页面(https://docs.safe.com/fme/html/FME_Desktop_Documentation/FME_ReadersWriters/json/json.htm)。
4.2 第二步:像素坐标到地理坐标的反投影
反投影的数学本身不复杂。对于常见的北向上栅格,若瓦片左上角地理坐标为 (X0, Y0),像元大小为 (dx, dy),像素坐标 (col, row) 对应的地理坐标为:
X = X0 + col * dx
Y = Y0 - row * dy # 注意 Y 轴方向,北向上时行号向下增大、Y 减小
如果瓦片带旋转或更一般的仿射变换(GDAL 的 GeoTransform 六参数),则要用完整的仿射矩阵:
X = gt0 + col * gt1 + row * gt2
Y = gt3 + col * gt4 + row * gt5
这里的 gt0..gt5 就是 GDAL 的仿射参数。FME 的 RasterGeoreferencer、Affiner、CoordinateSystemSetter 等转换器可以完成类似工作,但更稳妥的做法是用 PythonCaller 直接调用 osgeo.gdal 或 pyproj,把变换逻辑显式写出来,便于审计。
本文评述:反投影这一步,最怕的不是公式错,而是“坐标系混用”。比如瓦片是 UTM 50N,但 AI 返回的 bbox 被某个中间环节当成了 WGS84 经纬度;或者瓦片原点用了左下角,代码按左上角算。这类错误不会报错,只会让要素整体偏移,而且偏移量看起来“像那么回事”,极难排查。所以反投影必须和坐标系断言绑在一起。
4.3 第三步:与原始瓦片几何对齐
反投影之后,要素已经在地理空间里了,但“对齐”还没完。对齐要检查三件事:要素是否落在瓦片范围内(裁剪或标记越界)、要素的几何类型是否与下游预期一致(点/线/面)、要素的属性是否带上了瓦片 ID 和时间戳以便追溯。
在 FME 里,可以用 SpatialFilter 做范围过滤,用 Clipper 做裁剪,用 AttributeCreator 补溯源字段。一个常见的坑是:模型返回的 bbox 可能部分越界(比如目标被瓦片边缘截断),这时直接 Clipper 会把目标切成两半,影响后续统计。更合理的做法是保留原始 bbox,另加一个 is_clipped 标志,把“是否越界”作为质量字段传给下游。
五、路线B:地理参考入Prompt直出几何的可行性与边界
5.1 Prompt 里到底能塞多少地理信息
路线B的 Prompt 通常长这样:“这是一张瓦片,左上角地理坐标为 (X0, Y0),像元大小 0.5m,EPSG:32650。请检测船只,并直接返回地理坐标的 bbox。”看起来信息齐全,但模型实际要完成的是:识别目标 → 定位像素 → 读取 Prompt 中的参数 → 做乘加运算 → 输出地理坐标。这是一条四步链,任何一步出错都会传导到最终坐标。
近三年关于 VLM 空间推理的研究(如 SpatialVLM、SpatialRGPT 等工作)表明,模型在“相对空间关系”判断上进步明显,但在“精确数值计算”上仍然薄弱。这不是模型“笨”,而是自回归生成数字的机制决定了它对长数字、进位、负号的稳定性不如专用计算模块。本文评述:让模型做坐标变换,相当于让一个擅长描述的人去做精密测量,方向对,但精度不对。
5.2 路线B真正适用的场景
这不意味着路线B一无是处。它在三类场景里反而有优势:一是交互式探索,用户想快速看“大概在哪”,精度要求不高;二是语义级定位,比如“找出图中靠近码头北侧的区域”,模型输出的是语义描述而非精确坐标;三是小样本、低并发的验证性任务,人工复核成本低于搭建完整反投影流水线。
换句话说,路线B的合理定位是“快速原型”和“语义辅助”,而不是“生产级坐标生产”。把它用在几十万瓦片的批量任务上,等于把最不该交给模型的确定性计算交了出去。
六、误差传播与对齐精度:两条路线的量化对比
为了把“谁更准”说清楚,这里做一个误差结构的拆解。假设瓦片像元大小为 0.5m,模型检测框的像素定位误差为 ±2 像素(这是目标检测里比较典型的量级,具体依模型和场景而定,此处为示意性假设,非实测数据)。
这张表的关键不在第一行(两条路线都有检测误差),而在第二、三、四行。路线A的坐标变换误差是浮点级,且完全可复现;路线B的坐标变换误差来自模型的数值生成,量级不定、不可复现、难以定位。本文评述:在误差分析里,“可复现的误差”和“不可复现的误差”是两种性质完全不同的东西。前者可以校准,后者只能兜底。
关于栅格-矢量对齐的精度评估,OGC 的 GeoJSON 标准(RFC 7946)和 Simple Features 规范提供了几何表达的基础约定,可参考 https://datatracker.ietf.org/doc/html/rfc7946 与 https://www.ogc.org/standards/sfa。这些标准本身不规定精度,但规定了坐标顺序(经度在前)等易错细节——路线B如果让模型“自由发挥”,很容易在这些细节上翻车。
七、FME工作流骨架:从Connector到空间要素的落地实现
7.1 工作流总体结构
一个可落地的 FME 工作流大致分五段:瓦片读取与地理参考提取 → AI 推理调用 → JSON 校验 → 反投影与几何构造 → 对齐与质量标记。下面给出关键节点的实现思路。
Reader(Raster)
→ RasterGeoreferencer / PythonCaller(提取 GeoTransform)
→ HTTPCaller / AI Connector(调用模型,返回 JSON)
→ JSONValidator(Schema 校验)
→ PythonCaller(值域校验 + 反投影)
→ VertexCreator / GeometryReplacer(构造几何)
→ SpatialFilter / Clipper(对齐与裁剪)
→ AttributeCreator(质量标记)
→ Writer(GeoPackage / PostGIS)
FME 的 HTTPCaller 与 JSON 处理是这条链路的核心,官方教程与社区示例较多,可参考 https://community.safe.com/ 中的 JSON 与 AI 集成案例。对于批量瓦片,建议用 FeatureReader 或 WorkspaceRunner 做分块调度,避免单次内存爆掉。
7.2 反投影的 PythonCaller 实现要点
在 PythonCaller 里,建议把“坐标系断言”和“反投影”写在一起,任何一步不满足就抛异常并记录 tile_id。核心逻辑示意:
def process_feature(feature):
gt = feature.getAttribute('geotransform') # [gt0..gt5]
epsg = feature.getAttribute('epsg')
assert epsg == 32650, f"unexpected EPSG: {epsg}"
for obj in feature.getAttribute('objects'):
x1, y1, x2, y2 = obj['bbox']
# 像素 → 地理(完整仿射)
gx1 = gt[0] + x1*gt[1] + y1*gt[2]
gy1 = gt[3] + x1*gt[4] + y1*gt[5]
gx2 = gt[0] + x2*gt[1] + y2*gt[2]
gy2 = gt[3] + x2*gt[4] + y2*gt[5]
feature.setAttribute('geom_wkt', build_polygon(gx1,gy1,gx2,gy2))
这段代码的价值不在于“能跑”,而在于“出错时能说清楚错在哪”。断言 EPSG、记录 tile_id、保留原始 bbox,都是为了让后续审计有据可查。
八、性能、成本与可审计性的三角权衡
选型不能只看精度,还要看性能、成本和可审计性。路线A多了一次 Schema 校验和一次反投影,计算开销很小(毫秒级),但需要维护 Schema 和变换代码;路线B省掉了反投影代码,但 Prompt 变长、Token 成本上升,且模型输出不稳定带来的重试和人工复核成本往往更高。
可审计性上,路线A的每个环节都有中间产物(原始 JSON、校验结果、反投影前后坐标),可以逐段回放;路线B是端到端黑箱,出了问题只能“重跑看看”。本文评述:在生产环境里,可审计性不是锦上添花,而是故障定位的成本函数。一个不可审计的流水线,故障一次可能就要花几天去猜。
延伸阅读:关于地理空间数据质量与对齐的工程实践,可参考 GDAL 官方文档 https://gdal.org/ 与 FME 社区教程 https://community.safe.com/;关于 JSON Schema 规范,见 https://json-schema.org/。
九、前沿研究扫描与学术预判
近三年,三个方向的研究与这个问题直接相关。第一是遥感目标检测的旋转框与地理化,大量工作聚焦于如何让模型输出更贴合地物的几何表示,但地理化仍普遍放在后处理。第二是VLM 的空间推理与工具调用,一些研究让模型调用外部计算工具(如计算器、几何库)来完成精确计算,这实际上是在“路线B的壳里装路线A的芯”。第三是地理空间 JSON 的标准化,GeoJSON、JSON-FG 等规范在推动几何表达的互操作性。
本文评述:工具调用(tool use)的兴起,恰恰印证了本文的主线判断——模型不该自己做坐标变换,而该把变换委托给确定性工具。所谓“路线B”,在工程上更合理的形态是“模型输出结构化参数 + 外部工具执行变换”,而不是“模型直接吐出地理坐标”。这与路线A在本质上是一致的,只是调用方式不同。
十、结论:混合架构与落地检查清单
回到最初的问题:先校验再反投影,还是地理参考入 Prompt 直出几何?笔者的结论是:以路线A为主体,路线B仅用于探索与语义辅助,二者通过“坐标契约”统一。具体落地建议如下:
- 契约前置:在 AI 调用之前就定义好 JSON Schema 和坐标契约,写入接口文档。
- 校验分层:Schema 校验管结构,值域校验管范围,坐标系断言管基准,三层缺一不可。
- 几何后置:坐标变换一律由确定性代码完成,模型只输出像素坐标和语义标签。
- 溯源留痕:每个要素带 tile_id、模型版本、Prompt 版本、变换参数哈希。
- 质量标记:越界、低置信度、坐标异常单独打标,不静默丢弃。
- 探索分流:交互式场景可用路线B快速出结果,但结果需标注“未校准”。
这套架构不追求“一步到位”的炫技,而是追求“出错可查、误差可控、责任可追”。在大范围影像处理这种长链路、高并发的场景里,这三点比任何单点精度都重要。
十一、主要参考文献
[1] OGC. OGC GeoJSON / JSON-FG 相关规范与讨论文档, 2022–2024.
[2] IETF. RFC 7946: The GeoJSON Format, 2016(作为基础标准持续被引用).
[3] GDAL Development Team. GDAL Documentation: Geotransform and Raster Georeferencing, 2023–2025.
[4] Safe Software. FME Desktop Documentation: JSON Readers/Writers and JSONValidator, 2023–2025.
[5] 遥感旋转目标检测相关综述与代表性工作, 2022–2025(涉及 Oriented R-CNN、Rotated FCOS 等方向的公开文献).
[6] 视觉语言模型空间推理相关研究(SpatialVLM、SpatialRGPT 等公开工作), 2023–2025.
[7] JSON Schema 规范 Draft 2020-12, https://json-schema.org/.
[8] OGC Simple Feature Access 规范, https://www.ogc.org/standards/sfa.
[9] 本文涉及的模拟误差数值(±2 像素、0.5m 像元)为示意性假设,非实测数据,仅用于说明误差结构。
文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。
全文约 12800 字 | 参考文献 60 余篇(主要列出 9 篇)

