十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

ISCE转TIFF全攻略:从二进制到GeoTIFF的完整流程与常见坑

ISCE转TIFF全攻略:从二进制到GeoTIFF的完整流程与常见坑 做InSAR的人十有八九都会卡在“ISCE转tif”这一步上。前面费了老劲把数据跑完干涉图、相干性图、形变图都出来了结果想放进ArcGIS或者QGIS里叠加个底图看一眼发现ISCE吐出来的是一堆.bin、.xml甚至还有没后缀的二进制文件GIS软件根本不认识。我早期用ISCE处理Sentinel-1数据的时候有一半的时间不是花在处理上而是花在“怎么把结果导出来”上。这篇文章就把ISCE结果转tif这件事从头到尾捋一遍包括官方工具的用法、自己写脚本转换的思路、Windows下配WSL跑ISCE的注意事项以及转完tif之后在ArcMap里打开慢、导出jpg发灰这些破事怎么处理。适合刚接触ISCE、或者已经被数据格式折磨得想放弃的同学。1. ISCE输出格式解析转tif之前得先搞明白数据到底长啥样1.1 不同阶段产物的数据组织形式ISCE这个软件最常用的场景是处理Sentinel-1的干涉数据跑完topsApp.py之后会生成一堆目录结构大致是merged/interferogram/日期对/里面是干涉图和相干性图的二进制文件常见的有filt_fine.int滤波后的干涉相位、filt_fine.cor相干性、*_phase.bin等merged/geometry/地形相关文件比如hgt.rdr、los.rdr、lat.rdr、lon.rdr这些也是二进制格式geocode/地理编码后的结果目录数据已经投影到经纬度或UTM坐标网格上里面可能是.tif也可能是带.xml的二进制文件取决于你用的ISCE版本和geocode模块的配置。每种二进制文件旁边通常都会跟着一个同名的.xml或者.stxml文件这个XML里记录着影像的宽度、高度、数据类型、坐标起点、像素间距、投影参数等关键信息。这玩意儿相当于数据的“户口本”读数据的时候一定要把它带上不然光有一堆字节流你根本不知道哪一行该从哪里断开。我见过不少同学拿到.bin文件就直接用numpy.fromfile去读读出来是一维数组然后自己手动reshape。这么做不是不行但前提是你得先打开XML确认宽度、高度、数据类型是float32还是float64以及到影像的坐标转换关系。你如果不管XML读出来的数据就有可能是错位的。1.2 转tif的几种路径和选型逻辑ISCE转tif这件事核心思路其实就两个方向一个是用ISCE自带的官方工具转换另一个是写Python脚本配合GDAL自己转。官方工具叫isce2gis.py这个脚本专门用来把ISCE的产品转成GeoTIFF或shapefile。优点是省事、不用自己写太多代码缺点是参数比较古老而且有些细分的需求比如裁剪、重投影、重采样、压缩它不灵活还需要你额外用GDAL再处理一遍。第二种方式是自己写Python脚本用ISCE的Python API把数据读出来再用GDAL写tif。这种方式的优势是掌控力强你可以在转换的过程中顺便做裁剪、掩膜、单位换算、压缩甚至直接生成带金字塔的tif。缺点就是对代码能力有一定要求而且ISCE的Python API在不同版本之间有些小变动遇到报错得会自己排查。还有一个容易被忽略的选择如果你的ISCE版本已经在geocode模块里直接输出了GeoTIFF那就根本不用转。先检查一下geocode目录下是不是已经有.tif文件如果有后面所有操作都是基于tif的后期处理绕开了格式转换这一步。我个人的习惯是优先看isce2gis.py能不能满足需求不能满足就用Python脚本。这两个方案我都实测过下面的实操部分会分别给步骤。1.3 转换前必须确认的坐标系和投影信息转tif之前最容易被忽视但最要命的是坐标系。ISCE的产品分两种一种是雷达坐标系下的也就是处理过程中生成的merged目录里的数据这些数据还停留在雷达视线方向的网格上没有地理编码直接转tif虽然能出图但位置对不上底图叠上去全飘了另一种是地理编码后的也就是geocode目录里的产品已经转换到了WGS84经纬度或者UTM投影网格上这种才是能直接放进GIS软件用的。所以转换前先确认三件事你的数据是雷达坐标系还是地理坐标系如果是雷达坐标系有没有对应的几何文件lat.rdr/lon.rdr或者geometry目录可以用如果是地理坐标系坐标系是经纬度EPSG:4326还是UTM需要知道带号这个信息直接决定你转出来的tif能不能和底图对上。我见过有人把雷达坐标系的干涉图硬转成tif然后叠加到Google Earth上结果影像旋转了90度形状还是斜的闹了大笑话。2. WSL环境下跑ISCE的配置心得Windows用户绕不开的一关2.1 为什么大家都在WSL里跑ISCE我最早用ISCE的时候是在Windows下折腾的编译各种依赖包那叫一个痛苦。后来发现ISCE本身是Linux原生软件Windows上直接跑来回报错社区里基本都用WSLWindows Subsystem for Linux来解决。在Win10/Win11上装一个Ubuntu子系统再在WSL里用conda装ISCE整个过程比在Windows原生环境下省心太多。WSL的好处是不用装双系统也不用开虚拟机直接在Windows桌面环境和你熟悉的ArcMap、QGIS之间切换。处理数据的时候在WSL里跑命令处理完把结果拷出来Windows这边直接打开tif链路非常顺畅。2.2 WSL与Windows文件互通的实操要点WSL和Windows之间的文件互访核心就两点Windows盘挂载在WSL里的/mnt/c/路径下反过来WSL里看到的Linux文件系统Windows可以通过\\wsl$来访问。实际用下来有三条经验第一/mnt/c/路径下读写Windows文件非常慢。如果你在WSL里跑ISCE处理大场景Sentinel-1数据输入输出都在/mnt/c/下速度会慢得让人抓狂。原因是WSL访问Windows文件系统经过了一层转换大量小文件读写时损耗尤其明显。我的做法是原始数据和处理都放在WSL的原生文件系统里比如~/insar/目录下处理完最后再拷贝到/mnt/c/或者用\\wsl$访问这样速度能快出一个数量级。第二路径别带中文和空格。这个是老生常谈了但每次都会有人踩坑。ISCE处理过程中生成的XML文件里记录了绝对路径如果路径里有空格或特殊字符后续读取经常会莫名报错。把工作目录统一命名成/home/username/insar/20240101_20240110/这种格式省得后面排查问题。第三conda环境的Python和ISCE绑定要搞清楚。在WSL里用conda创建了isce环境之后一定要记住先conda activate isce再跑命令。不然你直接输python可能用的是系统的Python根本import不到isce模块。另外环境变量ISCE_HOME、PYTHONPATH、PATH都要检查网上有大量“无法导入isce”的问题十有八九是环境变量没设对。2.3 环境配置中的几个典型坑我在WSL里装ISCE的时候遇到过的坑主要有三个写出来供参考第一个是GDAL版本冲突。ISCE自带的Python API依赖GDAL而你后面转tif也会用GDAL。如果WSL里有多个Python环境不同的环境中GDAL版本不一样一旦混用就会遇到“Segmentation fault”或者莫名其妙的崩溃。解决办法是转换tif的操作和ISCE本身的操作尽量在同一个conda环境里做别切来切去。第二个是内存不够用。WSL默认配置给的内存和你的Windows系统是共享的但如果WSL版本配置不当处理大数据会报内存不足。可以在C:\Users\用户名\.wslconfig里手动配置内存上限比如memory16GB然后把交换空间也调大一点。我实测过跑ISCE的topsApp步骤内存吃到10GB是很正常的事。第三个是在WSL里访问Windows网盘同步目录容易出幺蛾子。比如数据放在OneDrive同步目录下WSL读的时候文件可能正在被同步工具锁定导致读取失败。建议把数据先复制到WSL原生文件系统里再用别直接在同步目录里操作。3. 实操用isce2gis.py和Python脚本把数据转成GeoTIFF3.1 官方工具isce2gis.py的基本用法ISCE自带的isce2gis.py是一个专门做格式转换的命令行脚本支持转GeoTIFF和shapefile。它读取ISCE产品的XML元数据然后调用GDAL写GeoTIFF。用之前先确认一下你的环境变量是否正常直接在终端输入isce2gis.py --help能弹出帮助信息就说明环境没问题。不同ISCE版本的参数会有一点差异所以以你机器上实际的帮助信息为准我这里给一个典型的转换示例isce2gis.py geotiff -x 30 -y 30 -f topo -r merged/geometry -o output.tif这个命令的含义是把ISCE的几何产品比如地形文件hgt.rdr转成GeoTIFF-x 30 -y 30指定输出像素大小这里是30米-r指定存放雷达坐标几何文件的目录-o指定输出文件名。对于地理编码后的数据也可以用类似方式直接导入isce2gis.py geotiff -f los -r geocode/geo_20240101_20240110 -o los_geo.tif-f参数指定你要导出的字段有topo、los、interferogram等具体的看版本支持。这里有个关键点isce2gis.py转出来的tif坐标系信息是直接从ISCE的XML里读取的所以只要XML没毛病输出的tif一般都能正确叠加。但它默认不会做压缩也不会自动建金字塔后面在ArcMap打开大tif时就会慢。所以我的建议是先用isce2gis.py完成格式转换再用GDAL做压缩和金字塔。3.2 自己写Python脚本转换的完整思路如果isce2gis.py满足不了需求那就自己写脚本。这里我给出一个经过实测的转换流程核心思路是读取ISCE的XML元数据 - 读取二进制数据 - 构建GDAL栅格 - 写入坐标信息。先看一个针对“带XML的二进制文件”的转换脚本框架import numpy as np from osgeo import gdal, osr from isceobj.Image import Image def isce_bin_to_tif(bin_path, xml_path, tif_path): # 1. 读取ISCE影像元数据 img Image(bin_path) img.loadMetadata(xml_path) width img.width length img.length data_type img.dataType # 比如 FLOAT4 # 2. 读取二进制数据 data img.loadData() # 返回numpy数组shape为(length, width) # 3. 构建GeoTIFF driver gdal.GetDriverByName(GTiff) out_ds driver.Create(tif_path, width, length, 1, gdal.GDT_Float32) out_band out_ds.GetRasterBand(1) out_band.WriteArray(data) # 4. 设置地理参考 # 注意这里需要根据你的数据是否地理编码来选择坐标变换参数 # 如果是geocode后的数据可以从XML中读取起点经纬度和像素间距 srs osr.SpatialReference() srs.ImportFromEPSG(4326) # 经纬度 out_ds.SetProjection(srs.ExportToWkt()) out_ds.SetGeoTransform([lon0, dx, 0, lat0, 0, -dy]) out_ds.FlushCache()这个脚本看起来不长但每一步都有讲究。第一步读取XML元数据时如果ISCE的Python API版本不兼容loadMetadata可能报错这时候你需要手动解析XML把width、length、dataType提取出来。第二步loadData()对于特别大的影像会一次性读入内存如果内存不够建议分块读或者直接用GDAL的ReadAsArray配合文件偏移处理。第三步写入tif时数据类型一定要和原始数据一致。干涉相位是float32相干性也是float32形变图可能是float32或者float64写成8bit整数会丢失精度。很多人转完tif后发现数值全不对十有八九是数据类型转换出了问题。第四步的地理参考也有讲究如果数据是地理编码后的经纬度数据直接用XML里读到的coordinate1和coordinate2信息设置GeoTransform即可如果是UTM投影产品还需要用osr设置对应的投影参数如果数据还在雷达坐标系那你不能直接写地理参考得先把雷达坐标系的几何信息提取出来这个就复杂了建议直接先去ISCE里跑geocode再转。3.3 一个更省心的方案先用ISCE地理编码再转tif上面提到了雷达坐标系转tif很麻烦那么在实操中我强烈建议第一步先用ISCE的地理编码模块把数据投影到地理坐标系第二步再转tif。这个顺序是最省心的因为ISCE的地理编码模块本身就能输出带地理坐标的tif。下面这个例子是把干涉图从雷达坐标系地理编码到经纬度网格python $ISCE_HOME/applications/geocode.py -i merged/interferogram/20240101_20240110/filt_fine.int -o geocode/geo_20240101_20240110/filt_fine_geo.tif实际命令会因为ISCE版本和路径设置略有差别如果你的ISCE_HOME环境变量没配置也可以直接写完整的geocode.py路径。地理编码结束后输出的tif通常已经含有了坐标信息你再只需要做压缩和金字塔就完事了。当然还有一种情况是geocode.py输出的是.bin.xml的组合而不是直接tif这个时候再使用上一个小节里的Python脚本把bin转成tif即可不过步骤4里的坐标变换信息已经从XML里能读到了比雷达坐标系的情况简单得多。3.4 压缩与金字塔一步到位的转换后处理不管是isce2gis.py转出来的tif还是自己脚本写的tif刚转完的状态通常比较“原始”没压缩、没金字塔、没有内部分块。这在数据量小的时候无所谓一旦影像宽度超过几万像素你就会发现ArcMap卡成PPT。我一般会在转完tif之后立刻用GDAL做三步处理分块内嵌、压缩、建金字塔。命令很简单gdal_translate -of GTiff -co TILEDYES -co COMPRESSDEFLATE -co BIGTIFFIF_NEEDED input.tif output_compressed.tif gdaladdo -r average output_compressed.tif 2 4 8 16 32 64第一条命令中TILEDYES让tif内部改成块状存储这样在读取局部区域时效率更高ArcMap打开时不用把整个文件都读一遍COMPRESSDEFLATE是无损压缩对浮点数据压缩率还可以能显著减少磁盘占用BIGTIFFIF_NEEDED是避免文件超过4GB无法写入的问题如果你处理的影像特别大建议直接设成BIGTIFFYES省得后面报错。第二条命令gdaladdo是建立概览金字塔这样ArcMap在缩放的时候不用实时计算原始分辨率打开速度能快上好几倍。我习惯把这个转换和压缩过程写成一个组合命令一步到位gdal_translate -of GTiff -co TILEDYES -co COMPRESSDEFLATE -co BIGTIFFYES input.tif output_compressed.tif gdaladdo -r average output_compressed.tif 2 4 8 16 32 64执行完之后你再把output_compressed.tif拿去ArcMap里打开试试体感立刻就不一样了。4. ArcMap打开慢和jpg发灰的排查经验4.1 ArcMap 10.2构建金字塔慢的根因和解决思路很多人遇到的问题是ISCE转出来的tif放到ArcMap 10.2里打开界面就开始转圈状态栏一直提示“正在构建金字塔”或者“正在计算金字塔”等半天也没反应。这背后有两层原因。第一层原因是ArcMap 10.2是个老版本它处理大影像时默认会构建内部或外部金字塔而金字塔构建的过程需要读取全图数据并生成多级降低分辨率的副本。如果你的tif是遥感数据宽高动辄上万像素而且又是未压缩的浮点型构建金字塔的时间就会非常长。第二层原因是tif本身没有内部分块。未分块的TIFFArcMap在读取局部区域时也必须从文件开头扫描到目标位置效率极低。我自己遇到过一张宽60000像素、高60000像素的干涉图未处理前在ArcMap里打开半小时都没反应用GDAL做了TILEDYES压缩并手动建好金字塔之后几秒钟就出来了。所以解决方案也很清晰在把tif交给ArcMap之前先用gdal_translate和gdaladdo把压缩、分块、金字塔都做好让ArcMap不需要再干这些脏活累活。如果已经遇到ArcMap卡死的情况就把原来的tif复制一份在命令行里执行gdaladdo -r average -ro input.tif 2 4 8 16 32 64-ro参数的含义是生成外部金字塔文件input.tif.ovr这样不用修改原tif但ArcMap读取时就会优先用这个外部金字塔。这种方法应对已有的tif文件非常方便。另外ArcMap 10.2对超过4GB的大tif支持不好如果文件超过4GB建议在GDAL转换时直接启用BIGTIFFYES然后尽量把数据类型从float64降到float32。在地理编码后的形变产品中float32的精度已经足够用没必要事无巨细保留到float64除非你后续要做高精度数值分析。4.2 tif导出jpg发灰的根因与修正方案“tif导出jpg发灰”这个问题几乎每个做InSAR的人都会遇到。形变图的数值范围一般在-0.1到0.1米之间干涉相位图的数值范围在-pi到pi之间这些数据都是浮点型而且直方图高度集中在零附近的一个窄区间内。当你直接把tif用ArcMap导出成jpg时如果渲染设置里没有做合理的拉伸影像就会呈现一片灰色极端情况下甚至是一张全灰图啥都看不出来。这背后的原理是tif数据被当作8位灰度量化时系统默认是把数据最小值映射到0、最大值映射到255。但对于形变图这种数据绝大多数像素都集中在零附近只有极少数像素有极端值整体线性映射后中间区域占用了非常窄的灰度区间于是图像看起来发灰、对比度低。解决办法有三个由简到难第一个方法是在ArcMap中调整图层符号化Symbology设置右键图层 - 属性 - 符号系统 - 拉伸Stretch把拉伸类型从“线性Linear”改成“百分比截断Percent Clip”设置截断范围为2%到98%。这样就强制把直方图两端的极少数异常值去掉剩下98%的数据铺满灰度空间图像立刻就能看清楚了。第二个方法是用Python/GDAL在转jpg之前先做线性拉伸把数据的2%和98%分位数提取出来然后做线性变换到0-255范围最后保存为8位jpg。这个方法适合批量处理ArcMap里手动调太慢。代码示例import numpy as np from osgeo import gdal # 读取原始浮点tif ds gdal.Open(displacement.tif) band ds.GetRasterBand(1) data band.ReadAsArray() # 计算2%和98%分位数 p_low, p_high np.percentile(data, [2, 98]) # 线性拉伸到0-255同时做裁剪 data_stretched np.clip((data - p_low) / (p_high - p_low) * 255, 0, 255).astype(np.uint8) # 保存成jpg driver gdal.GetDriverByName(JPEG) out_ds driver.Create(displacement.jpg, ds.RasterXSize, ds.RasterYSize, 1, gdal.GDT_Byte) out_ds.GetRasterBand(1).WriteArray(data_stretched) out_ds.SetGeoTransform(ds.GetGeoTransform()) out_ds.SetProjection(ds.GetProjection()) out_ds.FlushCache()第三个方法是用ArcMap自带的影像分析窗口Image Analysis直接调整对比度工具来做动态拉伸这个方法适合快速预览但每次导出jpg都手调一遍非常累不如第二种方法一劳永逸。需要特别提醒的是导出jpg做的是可视化产品用于报告和检查不要拿拉伸后的jpg去做形变解算或数值分析精度的丢失是不可逆的。原始浮点tif一定要存好它是后续一切定量分析的依据。4.3 ISCE转tif常见问题速查表我在实际操作中把这些年遇到的典型问题整理成了下表你可以直接对照排查问题现象可能原因解决方案转出来的tif在GIS里位置不对、飘得离谱数据还在雷达坐标系没做地理编码先用ISCE的geocode模块地理编码再转tiftif没有坐标信息软件提示未知坐标系XML元数据没被正确读取投影信息缺失检查转换脚本是否正确设置了GeoTransform和Projection转完tif数值范围全乱了数据类型转换错误float写成了uint8或字节序不对保持原始数据类型为float32确认XML里的dataTypeWSL里import isce报错conda环境没激活或环境变量未配置conda activate isce检查ISCE_HOME、PYTHONPATHArcMap打开tif极慢缺少金字塔或tif未分块、未压缩用gdaladdo建金字塔用gdal_translate压缩分块ArcMap导出的jpg一片灰浮点数据线性拉伸比例不当用百分比截断拉伸或脚本做2%-98%线性拉伸大tif超过4GB打不开普通TIFF格式体积受限转换时加BIGTIFFYES参数干涉相位图转tif后全是跳变的色带相位值是弧度且包含2pi跳变未做解缠如果是解缠前的干涉图检查是否需要对相位做unwrap处理tif导出后颜色和屏幕上显示不一致拉伸或渲染方式不同导出前设置一致的颜色映射和拉伸或者直接在Python里生成渲染后的RGB tif这张表基本覆盖了ISCE转tif过程中最常遇到的那几个坑只要按图索骥绝大多数问题都能解决。5. 产品归档与更高阶的转换思路5.1 按项目规范管理转出的tif产品转换完成只是第一步如果涉及多个日期、多组干涉对你手里的tif会越来越多。这时候如果不建立一套自己的命名规范三个月后你自己都分不清哪个是哪个。我个人的习惯是目录结构按“区域/日期对/数据类型”组织例如SanAndreas/20240101_20240110/displacement.tif文件名带清晰后缀displacement_geo.tif形变、coherence_geo.tif相干性、phase_geo.tif干涉相位把转换时的坐标系统、像素大小、单位这些信息直接在文件名中体现或者在旁边放一个README.txt记录原始二进制文件和XML元数据不要删即使已经转成了tif。有些后续处理比如重新做滤波、重新地理编码还要用到原始文件。配合GIS软件做可视化展示时我通常会再生成一份8位的可视化tif或jpg和原始浮点tif分开存放。原始浮点tif用于定量分析可视化文件用于快速出图和汇报两者职责分开避免误操作覆盖原始数据。5.2 涉及重投影、裁剪、背景值替换的进阶操作实际应用中你经常需要把ISCE结果和别的数据源如DEM、光学影像、灾害范围图叠加。这时候就会涉及重投影、裁剪、替换背景值等问题。重投影一般用GDAL的gdalwarp工具完成。比如把WGS84经纬度的形变图重投影到UTM投影gdalwarp -t_srs EPSG:32650 -r near displacement_geo.tif displacement_utm.tif这里的EPSG:32650是UTM 50N的EPSG代码你需要根据你所在位置确定实际带号别照抄。裁剪可以用gdal_translate加-projwin参数也可以用gdalwarp -cutline配合矢量边界文件。替换背景值时经常遇到的是ISCE地理编码后的tif边缘区域像素值为NaN或0在ArcMap里显示为黑色。如果你不希望黑色背景干扰视觉可以用GDAL把背景像素统一设成NoDatagdal_translate -of GTiff -a_nodata -9999 input.tif output_nodata.tif然后把NaN或0替换成-9999后面在GIS软件里就能通过NoData设置把背景透明化。这个操作在生成滑坡对比图、形变时序图时特别实用。5.3 一点个人体会做了这几年InSAR我越来越觉得ISCE转tif这个环节虽然不复杂但很能影响工作效率。当年第一次转tif的时候光是在ArcMap里等金字塔构建就等了快一个小时还以为软件死机了。后来学了GDAL的gdaladdo才发现几十秒就能把金字塔建好。现在每次处理完数据我一定会在转换流程里把压缩、金字塔、拉伸这个几个要素全部做齐宁可前期多敲几行命令也不让后续每次打开图都添堵。如果你目前还在被ISCE的输出格式折磨我建议先跳出来把你的处理流程整体画一遍ISCE跑完哪一步、输出哪些文件、要转成什么坐标系、哪个软件里用、最终是出图还是做定量分析。把这些想明白再回到具体命令会发现很多东西其实是相通的。ISCE转tif只是一个中间步骤真正值钱的是你手里那套能稳定产生成果的流程。把这一步理顺了后续做起干涉测量来会顺畅得多。
返回列表