Tellus を使ってみた

## はじめに

先日、[『宇宙×スマートシティ』 -衛星データ利用ワークショップ 2021-][work]のハンズオントレーニングに参加しました

[Tellus] というプラットフォームを用いて、衛星データを取得してみよう、という内容です

私も AI エンジニアの端くれとして、何かできないかと参加してみました

せっかくなので備忘録も兼ねて、[自分用の非公式 Python クライアントを作ってみました][github]

単純な Web API のラッパーになっています

ハンズオンで使った部分しか実装しておらず、エラー処理等もしていないので実用的ではありません:bow:

## Tellus とは

![RGB-Tellus-Logo-default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/5753c8aa-e2a5-3650-d824-a04965f706c7.png)

Web API で非常に簡単にアクセスでき、アカウントを作れば誰でもすぐに使ってみることができます

自作のAPIを [Tellus Market][market] に出品してビジネスに利用することもできるようになっています

## ハンズオンの内容

ハンズオンでは地盤の沈下や隆起を計測できる [TelluSAR] と、衛星画像の差分抽出を行う [Tellus-DEUCE][deuce] を扱いました

どちらも衛星データが可視化され、画像として結果が取得できるため、非常に分かりやすいハンズオンでした

Tellus のアカウント作成やマーケットでの購入手順については他にまとめている方もいますので、こちらでは省略します

## 自作 Python 実装

Tells の Web API は以下のような流れで実行します

- 自分の API Token を使って認証し、各API毎に Market Token を取得する

  ```python
  headers = {
      "Authorization": "Bearer " + self.api_token,
      "Content-type": "application/json",
  }
  response = requests.post(url, headers=headers, data=json.dumps(payload))
  ```

- Market Token を使って各APIにリクエストを投げる

  ```python
  headers = {"Authorization": "Bearer " + self.market_token}
  response = requests.get(url, headers=headers, params=payload)
  ```

Market Token は数分で有効期限切れになるため、エラーになった場合は再取得する必要があります

ハンズオンでは有効期限切れエラーが多発していたので、自作クライアントでは自動的に再取得するように実装しました

```python
if self.expires_at < datetime.datetime.now().astimezone():
    self.auth()
```

[ノートブック][sar_notebook]に実行例を残しています

ハンズオンで実行した内容（富士山周辺の地盤沈下・隆起の可視化）を自作実装に置き換えたものです

```python
from tellus.sar.tellusar import TelluSAR
import os
from PIL import Image

# APIトークンを指定してクライアントを作る
token = "Your API Token"
tellus = TelluSAR(token)

# 利用可能なシーンの一覧を取得する
scene_list = tellus.get_free_scene()
for scene in scene_list["data"]["scenes"][:10]:
    print(scene["scene_id"], scene["observation_datetime"], scene["polarisations"])

# 差分干渉処理ができる組み合わせを取得する
scene_id = scene_list["data"]["scenes"][0]["scene_id"]
print(scene_id)
after_scene_list = tellus.get_scene_after(scene_id)
for scene in after_scene_list["data"]["scenes"]:
    print(scene["scene_id"], scene["observation_datetime"], scene["polarisations"])

# 差分干渉処理をリクエストする
before = scene_id
after = after_scene_list["data"]["scenes"][0]["scene_id"]
polarisation = "HH"
work_result = tellus.request_work(before, after, polarisation)
works = work_result["data"]["works"]
for work in works:
    print(work["work_id"], work["complete_date"])

work_id = works[0]["work_id"]

# リクエストした処理の実行状況を確認する（完了日に値が入ればOK）
work_result = tellus.get_work_list()
works = work_result["data"]["works"]
for work in works:
    print(work["work_id"], work["complete_date"])

# 処理結果の画像をダウンロードする
output = "./TelluSAR.png"
tellus.download(output, work_id, 10, 906, 404)
img = Image.open(output)
```

## 感想

衛星データに簡単にアクセスすることができて、新鮮な体験でした

他のAPI等も組み合わせて、新しいサービスを作ってみたいですね

[work]: https://smartcity.fukuoka.jp/news/space-smart-city-workshop-2021-hosted-by-jaxa
[tellus]: https://www.tellusxdp.com/
[github]: https://github.com/RyoWakabayashi/tellus
[market]: https://www.tellusxdp.com/market/
[tellusar]: https://www.tellusxdp.com/market/tool_detail/4969e483-a714-45fe-a5d6-6cef5be85344/6a2ae4fc-2a62-4483-861a-906c716add07
[deuce]: https://www.tellusxdp.com/market/tool_detail/4969e483-a714-45fe-a5d6-6cef5be85344/2f443df3-3355-4232-99bc-01dbe5dc6ca3
[sar_notebook]: https://github.com/RyoWakabayashi/tellus/blob/main/TelluSAR.ipynb