遥感影像的坐标系问题,表面上是软件报错,实质上是“定义缺失”与“识别失败”两类完全不同的问题被混为一谈。本文把 FME 的坐标系解析链路拆开,逐层定位故障点,再给出三条技术路线的判据、操作步骤与边界条件。
📑 目录
一、摘要与问题定位
在 FME 中读取遥感影像(GeoTIFF、IMG、HFA、JP2、NITF 等)时,日志里出现 unrecognized spatial reference system 或 Unrecognized coordinate system,是空间数据工程里出现频率极高、但被误诊率同样极高的一类故障。常见的两种“直觉反应”是:其一,去 FME 安装目录下的 Reproject/Exceptions 文件夹里改映射文件;其二,直接上一个 CoordinateSystemSetter 转换器,把坐标系“按”上去。
这两种做法都可能奏效,也都可能埋雷。原因在于:这个报错背后至少对应四种性质完全不同的故障——定义缺失(数据里根本没有坐标系信息)、定义存在但 FME 不认识(WKT 方言不被解析)、定义存在且能识别但映射到错误基准(如把 CGCS2000 当成 WGS84)、以及定义本身错误(元数据写错)。四种故障的修复手段互不通用,用错路线轻则白忙,重则造成系统性坐标偏移而不自知。
本文以这条“先定位故障层、再选择修复层”的主线贯穿全篇:先拆解 FME 的坐标系解析链路,再给出四步诊断法,然后逐条评估三条技术路线的适用边界,最后落到工程化治理与前沿预判。全文面向已有一定 FME 与遥感基础、需要在生产环境中稳定处理多源影像的从业者。
二、背景:遥感影像坐标系信息的三种存在形态
要理解 FME 为什么“不认识”,先要理解坐标系信息在影像文件里到底以什么形态存在。遥感影像的坐标系描述大致有三种载体,它们的可靠性和可解析性差异很大。
2.1 GeoTIFF 标签:GeoKeyDirectory 与 EPSG 代码
GeoTIFF 规范(OGC 99-008r1 及其后续维护版本)通过一组 GeoKey 把坐标系信息写入 TIFF 标签。其中 ProjectedCSTypeGeoKey(键值 3072)或 GeographicTypeGeoKey(键值 2048)可以直接存一个 EPSG 代码,这是最“干净”的形态——FME 只要认得这个 EPSG 代码,就不会报错。
但 GeoTIFF 也允许另一种形态:不写 EPSG 代码,而是把完整的 WKT 或 ESRI PE String 塞进 PCSCitationGeoKey(3073)或私有标签。这时 FME 需要解析字符串,解析失败就报 unrecognized。国内不少国产卫星地面系统、以及部分老版本 ENVI/ERDAS 导出的影像,走的正是这条路径。
2.2 辅助文件:.prj、.aux.xml、.rpb
当主文件不带坐标系时,坐标系可能存在于同名辅助文件中。ESRI 生态的 .prj 存 WKT;GDAL/ESRI 的 .aux.xml 存 PAM 元数据;.rpb/.rpbm 存有理多项式系数,本身不含坐标系但常与投影信息配套。FME 在读取时会按格式优先级依次尝试,任何一个环节解析失败都可能触发报错。
2.3 完全缺失:只有像素坐标
最棘手的是第三种:影像只有行列号,没有任何地理参考。这在网络抓取的切片、截图、部分无人机原始输出、以及被“洗过”的成果图里非常常见。此时 FME 报 unrecognized 其实是“诚实”的——它确实无从识别。这类数据必须靠外部知识(采集参数、控制点、已知范围)反推定义,属于 CoordinateSystemSetter 或 LocalCoordSysDefs 的典型战场。
三、FME 坐标系识别机制拆解
FME 的坐标系处理建立在自有的坐标系字典之上,这套字典与 EPSG 数据集、ESRI 定义、以及若干历史定义保持同步,但并非完全等价。理解它的解析顺序,是定位故障的前提。
3.1 解析链路:从文件元数据到内部坐标系对象
一次读取大致经历四个环节:格式读取器提取原始坐标系字符串 → 字符串规范化(去空白、统一大小写、处理 ESRI 方言)→ 在坐标系字典中查找匹配项 → 生成内部坐标系对象并绑定到要素。任一环节失败,都会以 unrecognized 的形式抛出。实践中最常见的失败点是第二和第三环节。
# 用 GDAL 快速查看影像的坐标系原始描述(诊断第一步)
gdalinfo -json input.tif | python -c "
import json,sys
d=json.load(sys.stdin)
print('WKT:', d.get('coordinateSystem',{}).get('wkt','')[:200])
print('EPSG:', d.get('coordinateSystem',{}).get('epsg'))
print('Proj4:', d.get('coordinateSystem',{}).get('proj4'))
"
上面这段命令是笔者常用的“第一诊断动作”:它把文件里到底存了什么、能否被 GDAL 解析成 EPSG 代码,一次性暴露出来。如果 GDAL 能解析出 EPSG 而 FME 报错,问题多半在 FME 字典版本或字符串规范化;如果 GDAL 也解析不出,问题在文件本身。
3.2 坐标系字典与版本同步问题
FME 的坐标系字典随版本更新,新版本会纳入新的 EPSG 条目。这意味着一个在 FME 2021 里报错的定义,在 FME 2023 里可能已经能识别。反过来,某些历史定义(尤其是地方坐标系、城建坐标系)在较新版本中被调整或弃用,也可能引发新的识别问题。这一点在跨团队协作时尤其要注意——同一份工作空间在不同版本 FME 上行为可能不同。
Safe Software 官方文档中关于 coordinate system 的章节(见文末参考链接)明确指出,FME 支持 EPSG、ESRI、OGC WKT 等多种定义来源,并提供了 FME Coordinate System Gallery 供查询。本文建议把“查 Gallery 能否搜到目标 EPSG”作为诊断的固定动作。
3.3 Reproject/Exceptions 的真实作用域
这是最容易被误解的一环。Reproject/Exceptions 目录下的映射文件,其设计目的是在重投影计算时对特定坐标系对提供例外规则,例如某个基准转换需要特定的七参数、或某个投影对需要走特定的转换路径。它不是用来“让 FME 认识一个它不认识的坐标系”的。
四、故障诊断:四步定位法
下面这套四步法,是笔者在多源影像项目中反复验证过的诊断流程,目的是在动手修复之前,把故障层钉死。
4.1 第一步:确认文件里到底有没有坐标系
用 gdalinfo、exiftool 或 FME 的 Data Inspector 查看原始元数据。关键看两点:是否存在 EPSG 代码;若存在 WKT,其 AUTHORITY 节点是否完整。没有 EPSG 且 WKT 残缺,基本可判定为“定义缺失或残缺”,后续应走路线 B/C。
4.2 第二步:确认 FME 能否识别该定义
在 FME 里用 CoordinateSystemDescription 或直接在转换器参数里搜索该 EPSG 代码。搜得到,说明字典里有;搜不到,说明字典版本不覆盖,需要自定义定义。这一步能有效区分“FME 不认识”和“文件没写”。
4.3 第三步:确认识别结果是否正确
这是最容易被跳过、也最致命的一步。有些情况下 FME 不报错,但把 CGCS2000 识别成了 WGS84,或把某个地方坐标系识别成了相近的北京54。验证方法:用已知控制点或已知范围做一次反算,看坐标偏差是否在预期内。若偏差达到米级甚至十米级,说明识别结果错误,需要显式覆盖。
4.4 第四步:确认报错发生在哪个阶段
看日志时间戳与转换器执行顺序。若报错紧跟在读取器之后,属于读取阶段;若出现在 Reprojector 或 CSMapReprojector 执行时,属于重投影阶段。前者走 B/C,后者才考虑 A。
五、路线 A:修改 Reproject/Exceptions 映射文件
先把这条路线讲清楚,是因为它被误用得最多。Exceptions 机制的本质是“给重投影引擎打补丁”,而不是“给坐标系字典加词条”。
5.1 机制说明
FME 的重投影计算依赖底层 CS-MAP 库。Exceptions 文件允许你为特定的“源坐标系 → 目标坐标系”对指定转换方法、参数或优先级。它生效的前提是:源坐标系和目标坐标系都已被 FME 识别。也就是说,它解决的是“认识但转得不对”的问题,而不是“不认识”的问题。
5.2 适用条件与操作步骤
适用条件:源/目标坐标系均可识别;需要定制基准转换参数(如特定区域的七参数);或需要强制某个转换路径以匹配既有成果。操作上,一般是在 FME 安装目录的 Reproject 子目录下找到 Exceptions 相关文件,按官方格式追加条目。由于不同版本文件结构有差异,建议以本机版本的官方文档为准,不要照搬网络上的旧格式。
六、路线 B:CoordinateSystemSetter 显式赋值
CoordinateSystemSetter 是 FME 中把“已知但未写入”的坐标系显式绑定到要素上的标准手段。它的语义是“声明”,不是“转换”——这一点必须说清楚,否则极易被误用成“坐标纠正”。
6.1 语义边界:声明而非转换
CoordinateSystemSetter 只改变要素携带的坐标系标签,不改变坐标数值。如果影像的像素坐标本身是错的(比如地理参考偏移),Setter 只会让错误“看起来合法”。因此使用前必须确认:坐标数值本身是对的,只是标签缺失。这个确认动作,就是 4.3 步的验证。
6.2 操作步骤
典型工作流:读取器(此时坐标系为空或错误)→ CoordinateSystemSetter(填入正确 EPSG 或 WKT)→ 后续处理。若源数据坐标系为空,Setter 应放在读取之后、任何空间运算之前。若源数据坐标系错误,应先 Setter 成正确值,再做重投影。
# 伪代码:CoordinateSystemSetter 的典型放置位置
Reader(GeoTIFF) # 坐标系可能为空/错误
-> CoordinateSystemSetter # 填入 EPSG:4490 (CGCS2000 地理坐标)
-> Reprojector # 转到 EPSG:4547 (CGCS2000 / 3-degree GK CM 114E)
-> Writer(GeoTIFF)
6.3 批量场景下的参数化
当一批影像来自同一传感器、同一投影时,可以把 EPSG 代码抽成发布参数或从文件名/目录名解析,实现批量 Setter。这在处理按景分幅的国产卫星数据时非常实用——同一轨道的影像通常共享同一投影定义。
七、路线 C:LocalCoordSysDefs 自定义定义
当坐标系本身不在 FME 字典里(地方坐标系、城建坐标系、自定义投影),或者需要覆盖某个已有定义时,LocalCoordSysDefs 是正解。它允许你以 WKT 或 PROJ 字符串的形式,向 FME 注入自定义坐标系定义。
7.1 定义来源与格式
定义可以来自 EPSG 注册库、地方测绘主管部门发布的参数文件、或由已知控制点反算。格式上,FME 支持 OGC WKT 与 PROJ 字符串。实践中建议优先用 WKT,因为它对基准、椭球、投影参数的表达更完整,也更易被不同软件互认。
# 示例:以 WKT 形式注入一个自定义投影(示意,参数需按实际替换)
PROJCS["Local_GK_CM114",
GEOGCS["CGCS2000",
DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101]],
PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],
PROJECTION["Transverse_Mercator"],
PARAMETER["central_meridian",114],
PARAMETER["scale_factor",1],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1]]
7.2 操作步骤与注意事项
步骤上,一般是在 FME 的坐标系定义目录下维护自定义文件,或在工作空间层面引用。关键注意事项有三:其一,命名要唯一且可追溯,避免与 EPSG 官方名称冲突;其二,参数必须来自权威来源,不能凭经验填;其三,注入后要用已知点验证,确认反算误差在可接受范围。
7.3 与 CoordinateSystemSetter 的配合
实践中两者常配合使用:先用 LocalCoordSysDefs 把自定义定义“注册”进 FME,再用 CoordinateSystemSetter 把该定义绑定到要素。前者解决“字典里没有”,后者解决“要素上没写”。这个组合是处理地方坐标系影像的标准姿势。
八、三条路线的对比与选型矩阵
把三条路线放在同一张表里对照,选型逻辑就清晰了。核心判据是:故障发生在哪一层、修复是否需要跨机器复现、定义是否在字典内。
九、典型场景实战
9.1 国产卫星影像:CGCS2000 与地方投影
GF-1/GF-2 等国产卫星的标准产品通常带 CGCS2000 地理坐标或高斯-克吕格投影。问题多出在:部分地面系统导出的影像只写 WKT、不写 EPSG,且 WKT 中的 AUTHORITY 节点缺失,导致 FME 无法映射到 EPSG:4490。此时正解是 CoordinateSystemSetter 显式赋 EPSG:4490,而非改 Exceptions。
9.2 Sentinel-2:UTM 分带与 EPSG 映射
Sentinel-2 L1C/L2A 产品按 UTM 分带,EPSG 代码随瓦片变化(32601–32660 北半球,32701–32760 南半球)。批量处理时,EPSG 应从元数据或文件名解析,再用 Setter 绑定。这里的关键是“不要硬编码单个 EPSG”,否则跨带数据会出错。
9.3 无人机影像:无地理参考的原始输出
部分无人机原始影像只有 EXIF 中的 GPS 经纬度,没有投影信息。这类数据应先做空三与正射,得到带地理参考的成果后再进 FME。若必须在 FME 内处理,则需要用控制点反算定义,走 LocalCoordSysDefs。
9.4 历史影像:北京54、西安80 的基准转换
历史影像常带北京54或西安80。这类坐标系与 CGCS2000 之间存在基准转换问题,简单重投影会产生米级偏差。正确做法是:先用 Setter 明确源基准,再在重投影时指定七参数转换。此时若 FME 内置转换不满足精度要求,才轮到 Exceptions 定制转换参数。
十、工程化治理:把一次性修复变成可复用资产
单次修复解决的是单个文件,工程化治理解决的是“下次不再踩”。笔者建议从三个层面沉淀。
10.1 建立坐标系知识库
按数据源(传感器/地面系统/年份)记录其坐标系特征、常见故障与修复方式。这份知识库比任何单个工作空间都值钱,因为它把“领域知识”显性化了。
10.2 工作空间模板化
把 Setter、LocalDefs 引用、验证逻辑封装成模板或自定义转换器,新项目直接复用。模板里应内置“坐标系验证”环节——读取后立即检查坐标系是否为空、是否在预期集合内,不满足则报警而非静默通过。
10.3 自动化验证与回归
对关键数据流,建立基于已知控制点的回归测试:每次修改工作空间后,跑一遍验证点,确认坐标偏差在阈值内。这能有效防止“改了一处、坏了另一处”的隐性回归。
十一、前沿观察与预判
坐标系治理正在从“手工配置”走向“元数据驱动”。一方面,STAC(SpatioTemporal Asset Catalog)等元数据标准在遥感数据分发中普及,proj:epsg、proj:wkt2 等字段让坐标系信息更结构化,工具链可以据此自动绑定定义;另一方面,PROJ 库与 GDAL 的持续演进,使得跨软件的坐标系互认程度在提高。
但本文的判断是:短期内“定义缺失”问题不会消失。原因在于历史数据存量巨大、地方坐标系标准化程度参差、以及部分生产环节仍不重视元数据。这意味着 CoordinateSystemSetter 与 LocalCoordSysDefs 这类“显式声明”手段,在未来相当长时间内仍是主力。真正值得投入的,是把这些手段模板化、知识库化,而不是寄望于某个版本升级自动解决。
十二、结论
回到最初的问题:改 Reproject/Exceptions 映射文件是正路吗?答案是——只有在“定义可识别、但转换规则需要定制”时才是正路。对于绝大多数 unrecognized 报错,正路是先用 CoordinateSystemSetter 或 LocalCoordSysDefs 把定义喂进去,让 FME “认识”数据,再谈转换。
把这条主线记住:先定位故障层(定义缺失/识别失败/映射错误/规则缺失),再选择修复层(B/C 在前,A 在后)。这比记住任何单个转换器的用法都重要,因为它是可迁移的判断框架。
主要参考文献
- OGC. GeoTIFF Standard(OGC 19-008r4),2023. 说明 GeoKey 结构与 EPSG 代码写入方式。
- Safe Software. FME Coordinate Systems Documentation,2024. 官方坐标系支持与自定义定义说明。
- PROJ Contributors. PROJ Documentation,2024. 坐标系转换引擎与 WKT2 规范实现。
- GDAL/OGR Contributors. GDAL Documentation: GeoTIFF and PAM,2024. 元数据读取与辅助文件机制。
- ISO 19111:2019. Geographic information — Referencing by coordinates. 坐标参照系概念模型。
- EPSG Geodetic Parameter Dataset,2024 版本. 坐标系代码权威来源。
- STAC Specification,2024. 遥感元数据中 proj 字段的组织方式。
- 中国国家标准化管理委员会. GB/T 22021-2008《国家大地测量基本技术规定》及相关 CGCS2000 标准.
拓展阅读与教程链接(新窗口打开):

