COG 云原生优化遥感影像,瓦片切分的最佳实践
摘要:云上遥感影像文件 Cloud optimized GeoTIFF(COG)格式的详细介绍,大量数据上云面临的挑战,并分享了获得云原生影像最佳性能的实践经验。
本文分享自华为云社区《COG云原生优化遥感影像,瓦片切分的最佳实践》,作者: tsjsdbd 。
1、遥感影像文件格式
遥感影像就是地球自拍照,一般文件很大,一张文件 5GB 左右。
这些影像文件大多数都保存为 TIFF 格式(而不是 JPEG),因为 TIFF 格式记录的内容是比较原始的多个波段的信息,也不会因为压缩丢失信息。
1.1 TIFF 格式
这里分享一下 TIFF 文件的格式:
TIFF 是一个灵活适应性强的文件格式,能够在一个文件中保存多幅图像。然后每幅影像带一个标签目录(多个标签),记录它的像素深度、每像素波段信息,RGB 编码等详细信息。
注意:上图属性之间没有顺序要求,都通过 offset 查找。实际上是链表的形式:
因此,TIFF 文件内部各 Block 块之间的顺序可以很灵活自由。
1.2 TIFF 标签目录格式
每幅影像,带有一组标签目录,记录该图形的各种属性。
标签目录的格式如下:
每个标签(属性),由于信息内容不一样,其值大小有区别。有些信息小,它的标签值(Value)直接在标签里面。有些信息量比较大的,它的标签值(Value),在标签里放不下,需要记录在文件的其他位置上,通过 offset 便宜对应。
1.3 TIFF 单标签格式
1 个标签,就是记录图片的一个属性。主要是:属性名+属性值。
具体格式如下:
一般一幅图片,大概 10 几个属性。
可以看到,整个 TIFF 文件,是分块分散的记录图像数据的。所有信息之间都是通过 offset 偏移量关联。
ps:这里我先给“分块分散”标个粗。 这是它灵活性的优势,也是后续主题要讨论的。
关于 TIFF 详细格式,可参考:https://www.jianshu.com/p/ff32eb09ed3d
1.4 GeoTIFF 格式
正是因为 TIFF 这种标签化的格式,非常的好扩展,为图片添加地理信息也很方便。 所以 GeoTIFF 就在 TIFF 的标签规范里面,增加一系列(地理信息相关的)扩展标签,用来记录一幅影像的地理坐标信息。
可以看到,一个 GeoTIFF,也是正常的 TIFF 文件。所以它的内容,也是分散分块在文件内保存的。只是多了一系列的地理信息标签。
所有标签解释,见:https://www.loc.gov/preservation/digital/formats/content/tiff_tags.shtml
1.5 TIFF 格式灵活
由于 TIFF 文件内部都是链表的形式,所以文件标准中并没有要求各 Block 块之间彼此的顺序。
有时候它是这样的:
更常见的则是这样的:
少数还有可能是这样的:
无论哪种组织形式,都是符合标准的 TIFF 文件。
1.6 TIFF 文件调试
由于我个人的编程语言是 GO 语言,所以这里我选用了https://github.com/google/tiff
这个包(谷歌开源的 TIFF 文件解析包),函数调用使用 tiff.Parse() 就行。
解析完打个断点,就可以看到 TIFF 文件的各种属性啦:
上图可以看到,当前分析的这个 TIFF 文件里面,有 5 幅图片。
如上图,第一幅图片,有 21 个属性。这是原始图片,带有地理信息属性(标签 ID 值大于 3000),各属性如下:
其余的 4 幅,都只有 15 个属性。是 overview,没有地理信息,单纯的图片(不带 Geo 地理属性,标签 ID 都是 2xx~3xx 的),如下:
我们打开其中一个标签,看它的值:
这里看到这个属性 ID 是 256,查询规范:
得知这个表示图片的宽度,然后大小端属性,我们算出:第 2 个字节是 28,第 1 个字节是 174,实际值等于:28 * 256 + 174 = 7342 像素的宽度。
可以查看实际图片的像素,就是 7342。
其余属性,都可以按照这个方式一一查看。
2、遥感影像上云面临的问题
遥感影像的特点,主要是大。一般一张图片在 5~10GB,单卫星每天增加 TB 级,全球每天增加 PB 级。随着卫星传感器精度增加,单个影像文件越来越大。
大,带来的问题就是不容易保存,本地数据中心存不下,就得上云。但是大量的遥感数据上云后,面临不少挑战:
1. 大量的既有软件,无法远程读取云上的(特别是对象存储,如 S3)影像文件。必须先 Download 到本地,然后才能打开分析。
2. 即使为软件增加 S3 驱动。远程分析一个文件,也不得不全量读取文件内容(因为它是链表式的文件)。注意这个是通过网络进行的,所以很影响效率。
3. 单独取影像文件中的部分区域(瓦片,或者缩略图),也不得不全量下载 or 访问整个文件。即使瓦片仅占全影像的 1/N。
所以,能不能在访问云上的遥感影像数据的时候,只访问部分(尽可能小的)内容呢?
2.1 GeoTIFF 适合云的优化
要达成这个目的,需要有以下能力:
1. 云存储协议上支持以 Range 方式读取云上的文件。
2. GeoTIFF 影像文件,支持先读取“所有标签数据”,然后以 Offset 偏移读取目标数据。
这 2 个条件里面的第 1 个,目前各大云厂商的对象存储(如 S3)都已经支持。
关键是第 2 个条件。首先,能不能把 GeoTIFF 的“元数据”,全部放到文件头部,把实际 Data 数据放到文件尾部。
即:
这样的话,访问一个超大的 GeoTIFF 遥感影像,只需先发送 HTTP GET 获取文件头部 16K 字节,然后文件中剩余内容位置就都知道了。接下来想要访问什么,再根据偏移,发送 HTTP GET 访问目标 XX 字节的影像数据,就够了。
然后,将图像切成小片,可以根据“瓦片”的方式访问目标区域。因为已经有了头部的标签信息,所以再访问具体区域,只需要根据 Offset,直接读取云上文件的指定偏移就行。
即:
在这种模式下,该遥感影像文件,还是一个标准的 GeoTIFF 格式,只是它更适应云化访问。
2.2 COG 格式(Cloud optimized GeoTIFF)
为了让云优化的 GeoTIFF 格式更加的普及,专门成立了 COG(Cloud optimized GeoTIFF)标准。规范可以参考:https://www.cogeo.org/
介绍文章可以参考:
目前该标准得到了业界很多公司的认可:
重要的是,一个 COG 影像文件,也是一个标准的 GeoTIFF 文件,可以兼容已有的各种软件生态。
TIFF 和 GeoTIFF 和 COG 这三种文件格式之间的关系。
3、COG 文件最佳实践
有了 COG 文件格式的背景介绍,接下里我们详细分析一下一个 COG 文件,怎么样才能做到云化性能最优?
3.1 取文件头字节数
一幅影像文件,目前远程读取的最常用的底层库就是 gdal 了。它在第一次访问文件的时候,默认是先取 16KB 的内容。大多数的 GeoTIFF 文件头,取 16KB 肯定是够了的,如下(取 1 次头就可以 Open):
但是也有些 GeoTIFF 文件信息太多,使得文件头很大。gdal 就会不得不再次取一次文件头,如下图(取了 2 次头才能 Open):
2 次 HTTP 请求,才能获得完整的 TIFF 文件头,显然访问效率大打折扣。
这个时候,就得通过底层 gdal 库的配置,来控制首次获取文件头的字节数了。
环境变量:GDAL_INGESTED_BYTES_AT_OPEN=2000
可以使得首次请求的时候,获取更大的文件头,如下图:
但是如果影像文件的实际头都很小,你首次取太大肯定也浪费。
所以请根据自己的影像规格,以及影像的属性,恰当的选择首次取文件头的字节数。避免每次都额外发送一次 HTTP 请求,浪费效率。
3.2 瓦片大小的影响
一图影像,举个例子,原始像素是 512*512 的图片。
如果我们按照 256*256 的 Tile(瓦片)进行保存,那么就会有 4 个瓦片。
如果按照 512*512 的 Tile(瓦片)保存,那么只有 1 个瓦片。
这 2 种保存方式,会导致文件头需要记录的“信息量”不一样。4 个瓦片,就得记录 4 个偏移量。1 个瓦片则只需要记 1 个偏移量。
这里以一个 5GB 左右大小的 GeoTIFF 文件举例,按照 128*128 像素进行瓦片,那么所有的瓦片偏移值如下:
(标签 ID=324,代表 TileOffsets,值为 8 字节的整型。)
所以为了记录所有瓦片信息:65905(瓦片数) * 8(字节) = 527240,就要 520KB。
如果按照 256*256 的瓦片保存,则可以直接减少到 1/4,记录所有瓦片的偏移信息只需要 520KB / 4 = 130KB。可见适当加大瓦片面积,可以缩小 TIFF 文件头大小。
但是瓦片又不能太大,因为这会影响取局部区域的像素效率问题。
如下图举例:
如果目标区域在一个小瓦片范围内,则瓦片大小为 256*256 的话,取回的文件内容,就很小。 而 512*512 的话,一次取回就得整个大瓦片。显然网络传输效率会降低很多。
4、瓦片大小性能分析
下面我们详细分析性能 vs 瓦片大小的影响,分别以:
gdal 默认 tile 大小 256*256。
rio 默认 tile 大小 512*512。见:https://github.com/cogeotiff/rio-cogeo
gdal 命令:
rio 命令:
如果你仅有 gdal,也可以通过以下命令:
来控制瓦片大小。
gdal 命令,可以通过 docker 直接获得:
启动 gdal 容器的时候,只需要使用 -v 将主机目录,挂载到容器内就行。例如我的:
这样容器里面的/tmp/cog 目录下,就可以看到主机/home/tsjsdbd 里的 tiff 文件了。
下面来对 2 种做对比,详细操作如下:
4.1 取一个像素
512*512 瓦片:
第 2 次通过 HTTP 响应取回来:105119744-105840639 = 720,895 字节
256*256 瓦片:
可以看到,第 2 次请求的内容,小很多:139476992-139722751 = 245,759 字节
对比发现,256 的瓦片,第 2 次 HTTP 响应只有 1/3,延时也是优势明显。
4.2 取一块区域
512*512 瓦片:
第 2 次通过 HTTP 响应取回来:32522240-33095679 = 573,439 字节
256*256 瓦片:
同样的,第 2 次取的内容,小很多:41402368-41533439 = 131,071 字节
同样,256 的瓦片,第 2 次 HTTP 响应大小只有 1/3,延时也是优势明显。
4.3 512 瓦片性能
官方测试报告里面(见:https://trac.osgeo.org/gdal/wiki/CloudOptimizedGeoTIFF )
显示 512*512 的瓦片大小,性能更优,是因为
256*256 的小瓦片,导致 TIFF 文件头太大了。第 1 次 16KB 取不完,又取了 1 次导致的。
Ps:首次取的字节数,是可以通过配置控制的。
所以实际业务场景下,具体以多大的瓦片划分,要根据项目影像图片特征适当的调整。
4.4 性能小结
性能对比看,256*256 的小瓦片,在做局部在线 Web 预览加载时,性能更优异。
但是 256*256 的瓦片,意味着瓦片数量更多,TIFF 文件头更大,因此需要适当控制“首次取文件头字节”配置。
上述 GDAL 操作步骤可以参考:
https://trac.osgeo.org/gdal/wiki/CloudOptimizedGeoTIFF
其他 GADL 配置调优可参考:
https://developmentseed.org/titiler/advanced/performance_tuning/
5、COG 的未来
分享了 GeoTIFF 影像文件上云后的一系列最佳实践后,我们探讨一下,未来在 COG 性能方面,有没有云厂商提供更加深度优化方式呢?
可以想到的有:快速的获得 COG 文件头大小,使得首次 HTTP 请求,精确取想要的数据,不浪费额外的网络报文。不过这种就需要对象存储提供一些定制能力了。
COG 已经是业界普遍认可的云原生的遥感影像数据格式,未来一定可以更加的普及,并且发挥更大的价值。其他有好的想法,也欢迎探讨分享。
华为云地理遥感平台 GeoGenius,经过多年的技术项目积累,采用了业界最佳的云原生的遥感影像管理实践,并且提供端到端最优的性能体验,欢迎领域同行了解使用。
详见:https://www.huaweicloud.com/product/geogenius.html
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/bb8a08a624262aa215999c37f】。文章转载请联系作者。
评论