前回は、rio-tilerを利用してモノクロの1レイヤーのCOGをQGIで表示するところまでしました。今回はバンド合成したカラー画像を表示するところまでやっていきます。
前回
COGをソースにしてタイルサーバをホストする(1) - たぶん動く...
単バンドグレー表示
前回は表示できてもグレーで濃淡のない表示になってしまいました。これはCOGがFloat型で持っているのに対し、出力するPNGがInt型(0〜255)に無理に変換しようとした結果、グレー一色になっているようです。
ヒストグラムを確認すると、0.2以下に山があるので、値を1000倍してそのままInt型に変換すれば良さそうです。
適切に濃淡が表示されるようにapp.pyを修正します。
タイルのレスポンスを以下に変更しました。 19行目でCOGから切り出した値を0.255より大きい値は0.255とし、その状態が1000倍にすることで、全ピクセルを255以下の値にします。
その後PNGを返します。
@app.get( r"/{z}/{x}/{y}.png", responses={ 200: { "content": {"image/png": {}}, "description": "Return an image.", } }, response_class=Response, description="Read COG and return a tile", ) def tile( z: int, x: int, y: int, url: str = Query(..., description="Cloud Optimized GeoTIFF URL."), ): """Handle tile requests.""" with Reader(url) as cog: img = cog.tile(x, y, z,256) img.data=np.where(img.data>0.255,0.255,img.data)*1000 img.data=img.data.astype('uint8') content = img.render(img_format="PNG", **img_profiles.get("png")) return Response(content, media_type="image/png")
では実行してみます。
uvicorn app:app --reload --host 0.0.0.0
砂漠地域なので、赤色に対応するバンドだとほとんど白くなりますが、単バンドで濃淡が表現されるタイルになりました。
カラーバンドを表示する
まず、RGBバンドを持つGeoTIFFを作成してから、COGファイル化します。
rio-tilerは、コードを読んだところ複数バンドを持つCOGを読み取ることができるようです。 必要なバンドを指定し、カラーになる順番で抽出します。
9行目に引数を追加しました。
def tile( z: int, x: int, y: int, url: str = Query(..., description="Cloud Optimized GeoTIFF URL."), ): """Handle tile requests.""" with Reader(url) as cog: img = cog.tile(x, y, z,256,[1,2,3]) img.data=np.where(img.data>0.255,0.255,img.data)*1000 img.data=img.data.astype('uint8') content = img.render(img_format="PNG", **img_profiles.get("png")) return Response(content, media_type="image/png")
では実行してみます。
uvicorn app:app --reload --host 0.0.0.0
表示できました。 湖水域がNodataなので黒く表示されています。
参考文献
GitHub - cogeotiff/rio-tiler: User friendly Rasterio plugin to read raster datasets.