摘要:雲上遙感影像文件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級。隨着衛星傳感器精度增加,單個影像文件越來越大。
大,帶來的問題就是不容易保存,本地數據中心存不下,就得上雲。但是大量的遙感數據上雲后,面臨不少挑戰:
- 大量的既有軟件,無法遠程讀取雲上的(特別是對象存儲,如S3)影像文件。必須先Download到本地,然后才能打開分析。
- 即使為軟件增加S3驅動。遠程分析一個文件,也不得不全量讀取文件內容(因為它是鏈表式的文件)。注意這個是通過網絡進行的,所以很影響效率。
- 單獨取影像文件中的部分區域(瓦片,或者縮略圖),也不得不全量下載or訪問整個文件。即使瓦片僅占全影像的1/N。
所以,能不能在訪問雲上的遙感影像數據的時候,只訪問部分(盡可能小的)內容呢?
2.1 GeoTIFF適合雲的優化
要達成這個目的,需要有以下能力:
- 雲存儲協議上支持以 Range方式讀取雲上的文件。
- 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/
介紹文章可以參考:https://medium.com/planet-stories/cloud-native-geospatial-part-2-the-cloud-optimized-geotiff-6b3f15c696ed
目前該標准得到了業界很多公司的認可:
重要的是,一個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命令:
gdal_translate input.tiff output.tiff \
-co TILED=YES -co COPY_SRC_OVERVIEWS=YES -co COMPRESS=LZW
rio命令:
rio cogeo create input.tif output.tif
如果你僅有gdal,也可以通過以下命令:
gdal_translate input.tif output.tif \ -co TILED=YES -co COMPRESS=LZW -co COPY_SRC_OVERVIEWS=YES \ -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 \ --config GDAL_TIFF_OVR_BLOCKSIZE 256
來控制瓦片大小。
gdal命令,可以通過docker直接獲得:
docker pull osgeo/gdal
啟動gdal容器的時候,只需要使用 -v 將主機目錄,掛載到容器內就行。例如我的:
docker run -it -v /home/tsjsdbd/cog/:/tmp/cog/ osgeo/gdal /bin/bash
這樣容器里面的/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