はじめに
本連載記事は、地理空間情報のAI-ReadyなDataLoaderである『SpatialArrow』を設計し、実装し、検証した内容を3部作として執筆したものです。今回は、その第1回目の記事となります。
第1回【SpatialArrow概念編】GeoAI学習で「画像分割によって地物が途切れる問題」をどう解決するか?(固定タイル方式の課題とSpatialArrowの設計思想)
第2回【SpatialArrow実装編】GeoAI学習で地物を切り刻まずに学習へ渡す(ROI単位で画像とBBを生成する、AI-ReadyなDataLoaderの実装)
第3回【SpatialArrow検証編】GeoAI学習で地物を分割せずに学習させたら精度は上がるか?(屋根上PV検出の比較検証で見逃しが16.5%減少)
空中写真や衛星画像を使って、建物や道路、屋根上のソーラーパネルを抽出する。こうしたGeoAIの開発では、地理空間データを用意しただけでは学習を始められません。
GeoTIFFから画像を切り出し、地図上のポリゴンを画像内の座標へ変換し、COCOなどの形式でアノテーションを保存する。その後で、ようやくモデルに渡せるデータセットになります。
ここで考えたいのは、「モデルへ入力できるデータ」と「地理空間情報を一貫して扱えるデータ」は、同じではないという点です。
画像上で建物を検出できても、その建物は地図上のどこにあるのでしょうか。隣の画像に写っている建物と同じものなのでしょうか。学習に使った形状は、どの元データを、どの条件で切り出したものなのでしょうか。
本記事では、COCO形式を中心とした画像単位のデータセットで生じやすい課題を出発点に、オービタルネットで研究開発しているSpatialArrowの設計思想を説明します。
SpatialArrowは、地理空間データの正本を保ち、モデルに必要な画像・教師データ・座標変換情報を実行時に構成するためのデータ仕様とPyTorch DataLoaderの提案です。[1]
本記事は設計の解説編です。具体的なRF-DETRへの接続方法と、屋根上ソーラーパネルのBoundingBox(以下、BB)検出による比較実験は、別の実装記事で扱います。
1. COCO形式で表現できること
COCOは、物体検出やインスタンスセグメンテーションで利用されるデータセット・アノテーション形式です。基本的には、画像と、その画像内にある物体の注釈を対応付けます。[2][3]
画像はimages、注釈はannotations、クラスはcategoriesで管理します。BBは、画像内の位置と大きさを[x, y, width, height]で表します。セグメンテーションにはポリゴンやRLEによるマスク表現があります。
以下は、BBの対応関係を説明するための簡略例です。完全なデータセット定義ではありません。
{
"images": [
{"id": 1, "file_name": "tile_001.png", "width": 1024, "height": 1024}
],
"annotations": [
{
"id": 101,
"image_id": 1,
"category_id": 1,
"bbox": [100, 200, 80, 60],
"area": 4800,
"iscrowd": 0
}
],
"categories": [
{"id": 1, "name": "building"}
]
}
これにより、「画像1の中の、左上が座標(100, 200)、幅80、高さ60の範囲に建物がある」と伝えられます。
一方、その座標だけから、地図上の位置を求めることはできません。
2. 地理空間データをCOCOへ変換するときに、別途必要になる情報
GeoAIでは、画像内の位置に加えて、次の情報が重要です。[1]
| 情報 | 必要になる理由 | COCOの標準的な注釈だけで十分か |
|---|---|---|
| CRS(座標参照系) | 座標の意味と他データとの位置関係を決める | 別途管理が必要 |
| 元画像のアフィン変換 | 画素座標と地理座標を対応付ける | 別途管理が必要 |
| 元画像の参照先・切り出し範囲 | 元のどの範囲を使ったか追跡する | 地理空間用途の追加情報が必要 |
| 地上解像度・使用バンド | 同じ画素数でも異なる観測条件を区別する | 別途管理が必要 |
| 永続的な地物ID | 別タイル・別時点の同じ地物を結び付ける | 注釈IDとの対応を別途定義する |
| 変換・リサイズの条件 | 同じ入力を再生成し、座標を戻す | 別途管理が必要 |
| 地物間の関係や形状構造 | 隣接、外周・内周、辺の接続を扱う | 目的に応じた追加設計が必要 |
COCOのidやimage_idが存在しないわけではありません。しかし、画像ごとの注釈IDは、そのままでタイルをまたぐ永続的な地物IDになるわけではありません。
また、COCOには画像の取得日時などを記述する項目もあります。それでも、地理空間データの正本、画像の空間参照、変換条件を結び付ける仕組みは別途必要です。
COCOへ変換すると必ず地理情報が失われる、ということではありません。 GeoTIFFやワールドファイルを残したり、JSONを拡張したり、外部の対応表を持たせたりすれば、情報を維持できます。
課題は、その対応をプロジェクトごとの独自処理として持ちやすく、画像・注釈・座標変換の整合性を継続して管理しなければならないことです。
3. 固定タイル化によって生じる、地物の断片化
もう1つの問題は、モデル入力のために画像を固定サイズへ切り出すことです。
地図上では1つの建物でも、画像のタイル境界をまたぐと、複数のチップに分かれます。ポリゴンやBBを各タイル内へクリップすれば、その地物の一部分が教師データになります。
地物の形状を $G$、タイルの範囲を $T_i$ とすると、各タイルで扱う部分形状は次のように表せます。
G_i = G \cap T_i
この処理は、タイル内の正解を作る方法として成立します。ただし、断片だけを保存し、元の地物IDや形状への対応を残さないと、次の区別が難しくなります。
- その輪郭は、実際の地物の境界なのか、タイルによる切断線なのか
- 隣接する画像の断片は、同じ地物なのか、別の地物なのか
- 地物全体のうち、どの程度が画像に写っているのか
- 部分的な地物を、学習や評価でどのように扱ったのか
建物ポリゴンや辺の接続を学習する場合には、切断によって人工的にできた境界が、実在する境界と区別されないことも課題になります。[1]
なお、固定タイル化はCOCO形式そのものの必須要件ではありません。 ここで問題にしているのは、大きな地理空間画像を固定チップへ加工し、その画像内注釈だけを中心に管理するワークフローです。
図1:地物全体とタイル内の断片
図1:元の地物は1つでも、固定タイル上では複数の断片になる。断片を使う場合にも、元の地物との対応と部分性を保持することが重要になる。
4. SpatialArrowの基本思想:正本とモデル用ビューを分ける
SpatialArrowでは、保存する地理空間データと、モデルへ渡す表現を分けます。[1]
**正本(canonical data)**は、地物の元の形状、ID、属性、画像の参照先、空間参照などを保持する基準データです。
**ビュー(runtime view)**は、その正本から、ある入力条件に応じて生成する一時的な画像・教師データです。
例えば、同じ建物ポリゴンから、次のような入力を作ることを考えます。
| 用途 | 正本から生成するモデル用表現 |
|---|---|
| 物体検出 | BB |
| セグメンテーション | 画素単位のマスク |
| ポリゴン予測 | 画像座標の頂点列 |
| 辺を扱うモデル | 辺・端点・接続関係 |
モデルに応じて表現が変わっても、基準となる地物は同じです。
ただし、必要な情報が元データに存在することが前提です。BBしかないデータから、詳細な建物形状やパネルのマスクが自動的に復元できるわけではありません。
ここで維持したいのは、「1024ピクセルの画像に合わせて保存した注釈」だけではなく、その注釈の元になった地物と、入力を生成した条件の対応です。
5. ファイル形式を増やすのではなく、情報の関係を定義する
SpatialArrowは、すべてを1つの独自バイナリファイルへ詰め込む提案ではありません。既存形式を役割ごとに利用し、その間の関係をデータ契約(data contract)として定義します。[1]
データ契約とは、「何を保存し、どのIDで関連付け、どの座標系と変換条件で解釈するか」という取り決めです。
| 技術 | SpatialArrowの設計における主な役割 |
|---|---|
| COG/GeoTIFF | 空間参照付き画像の保持と、必要範囲の読出し |
| Parquet | 参照情報や関係テーブルなどの永続的な列指向保存 |
| GeoParquet | 地物のジオメトリ、属性、CRS情報の永続化 |
| Apache Arrow | メモリ上の列指向データ、RecordBatchでの受渡し |
| GeoArrow | Arrow上でのジオメトリ表現と関連メタデータ |
| PyTorch DataLoader | 学習用サンプルの取得とバッチへの受渡し |
GeoParquetは保存、GeoArrowは主にメモリ上の表現という役割で整理すると理解しやすくなります。GeoArrow自体はArrow互換の構造・形式も対象とする仕様です。[4][5]
SpatialArrowは、Apache ArrowやGeoArrowそのものの名称でも、これらを置き換える標準でもありません。地理空間データとAI入力の関係を、これらの技術の上で定義する研究開発です。
COGの内部タイルと、モデル専用に書き出す固定チップも区別します。元のラスタが内部でタイル化されていても、モデルごとの画像ファイルを大量に事前生成することとは別です。
6. 何を管理するのか:v0.1の論理スキーマ
資料では、次の情報を論理的に分けて管理します。[1]
| 要素 | 保持する内容 | 役割 |
|---|---|---|
raster |
画像参照、CRS、source affine、幅・高さ、バンド等 | 元画像の位置と読出し条件を知る |
objects |
地物ID、クラス、属性、正本のジオメトリ | 地物をモデル入力に依存せず保持する |
roi |
空間範囲やsource window、画像との対応、split等 | どの領域を選ぶかを表す |
roi_object_index |
ROIと地物の対応、部分性、可視割合、扱いの方針 | ビュー内での地物の状態を明示する |
view_profile |
解像度、バンド、入力サイズ、再サンプリング、正規化等 | モデルへの見せ方を指定する |
canonical_edge_primitives |
元の辺、リング、接続関係など | 辺を扱うモデル向けの任意要素 |
これは論理構成であり、必ず6つの独立ファイルが必要という意味ではありません。
ROIは保存済みの画像チップではない
ROI(Region of Interest)は、対象範囲を表す情報です。元画像のどのwindowを読むか、あるいはどの地理的範囲を選ぶかを示します。
その範囲に対応するPNGが、あらかじめ保存されている必要はありません。
正本の座標系を明確にする
地物は、モデル画像の画素座標ではなく、正本として定めた共通CRSのジオメトリとして保持します。異なるCRSのベクターデータは、取込み時に正本のCRSへそろえる設計です。
CRSは原則としてGeoParquetのジオメトリ列またはテーブルのメタデータで宣言し、行ごとに異なるCRSを持つことを基本形にはしません。
7. 部分的に見える地物を、どう扱うか
SpatialArrowは、どのビューでも地物を絶対に切らないことを要求する仕組みではありません。 保存する正本を維持したまま、ビュー上で部分地物をどう扱うかを明示する設計です。[1]
| 情報・方針 | 意味 |
|---|---|
object_id |
どの元地物に由来するか |
visible_fraction |
定義した基準に対し、どの程度がビュー内に含まれるか |
is_partial |
地物の一部分だけを扱うか |
clip_policy |
ビュー境界で形状をどのように切り抜くか |
loss_policy |
その教師を損失計算にどう使うか |
ポリゴンの面積を基準にする場合、可視割合は概念的には次のように表せます。
f_{\mathrm{visible}} = \frac{\operatorname{Area}(G\cap R)}{\operatorname{Area}(G)}
ここで $R$ はビューの範囲です。これは幾何学的に範囲内に入る割合であり、雲や影によって実際に見える割合を直接表すものではありません。計算する座標系や面積の定義もそろえる必要があります。線など、面積で扱えない地物には別の基準が必要です。
タスクに応じて、全体が入る範囲を選ぶ、部分形状を教師にする、部分地物を損失から除外する、といった扱いを設計できます。ただし、除外する場合には、画像内に残った対象を背景として誤って学習させないためのモデル側の対応も必要です。
同じ地物を別物として保存してしまうことと、一時的な入力上で一部だけを使うことを分ける。 これが断片化への基本的な対応です。
8. 座標変換を入力の一部として管理する
地理空間のポリゴンをモデルへ渡すには、地理座標を画像内の座標へ変換します。この処理は、単純に画像のアフィン変換を逆にするだけとは限りません。[1]
必要になる変換は、次の順序です。
- 地物の正本CRSから、ラスタのCRSへ変換する。
- ラスタの地理座標を、元画像の画素座標へ変換する。
- 切り出しwindowの左上を原点とする座標へ移す。
- モデルの入力サイズに合わせて拡大・縮小する。
地物の正本座標を $q_c$、CRS変換を $P_{c\to r}$、元画像の画素座標からラスタの地理座標へのアフィン変換を $A$、window左上を $(x_0,y_0)$ とすると、概念的には次のようになります。
\begin{bmatrix}u\\v\\1\end{bmatrix}
=
S\left(\frac{W_m}{W_s},\frac{H_m}{H_s}\right)
T(-x_0,-y_0)
A^{-1}
\widetilde{P_{c\to r}(q_c)}
- $(u,v)$:モデル入力内の座標
- $(W_s,H_s)$:元画像から読み出すwindowの大きさ
- $(W_m,H_m)$:モデルの入力サイズ
- $T$:window位置に応じた平行移動
- $S$:入力サイズへの拡大・縮小
- チルダ:2次元座標を同次座標にした表記
この式は、windowを直接リサイズする場合のものです。余白追加や反転・回転などを行う場合は、その変換も管理対象に加える必要があります。
CRS変換は一般に非線形なので、変換列のすべてを常に1枚のアフィン行列だけで表せるわけではありません。行列で扱える部分と、CRS変換そのものの条件を区別して保持します。
また、画素の中心を座標の基準にするのか、画素の境界を基準にするのかも重要です。この違いを暗黙にすると、0.5ピクセルの系統的なずれにつながります。
9. ViewContext:入力がどこから来たかを残す
変換後の画像と教師だけを返すのではなく、生成条件をViewContextとして保持します。[1]
主に、次の情報です。
- 元画像のIDとROI/ビューのID
- CRSとsource affine
- 読み出したsource window
- モデル入力サイズ
- 順変換・逆変換に必要な情報
- 変換条件を識別するハッシュ
- 画素中心・画素境界の規約
これにより、学習で問題が起きた入力を元データへたどったり、同じ条件のビューを再生成したりするための情報を残せます。再現性のためには、参照する元画像・地物データの版も固定または識別できる必要があります。
推論結果の座標をGISへ戻す際にも、この変換情報を利用できます。ただし、逆変換で戻せるのは予測された座標です。切り抜きで失った形状や、モデルが見逃した部分を復元するものではありません。タイル間の重複統合や、予測ジオメトリの妥当性確認も別途必要です。
10. PyTorchへ何を渡すのか
資料では、DataLoaderが扱うバッチを、概念的に次の3要素で表しています。[1]
# データ構成の概念例。実行用APIではありません。
batch = {
"images": Tensor[B, C, H, W],
"targets": List[Dict],
"view_contexts": List[ViewContext],
}
画像は同じ入力サイズへそろえてバッチ化できます。一方、地物数、ポリゴンの頂点数、リング数、辺の数は画像ごとに異なります。そのため、汎用部分では教師データを可変長のリストとして受け渡します。
その後、モデル別アダプターがBB、マスク、ポリゴン、辺などへ変換します。必要なpaddingやtokenization、ラベル形式の変換も、モデル固有の要件に応じて行います。
モデルに合わせる処理をなくすのではなく、地理空間データの保存から分離するという設計です。
11. 「前処理なし」「トポロジー保持」の意味
前処理が消えるわけではない
SpatialArrowでいう「事前固定タイルを保存しない」は、座標変換やリサイズが不要になるという意味ではありません。
画像の読出し、展開、バンド選択、座標変換、クリップ、正規化などは、実行時にも必要です。モデル専用の派生ファイルを繰り返し作成・保存する負担を減らすことが目的です。[1]
トポロジー保持は、予測の正しさの保証ではない
資料におけるトポロジー保持は、保存層で地物の同一性、外周・内周リング、明示的な隣接・辺の接続関係を保つことを指します。
任意のクリップ後の形状や、モデルの予測結果が、必ず完全なトポロジーを持つという保証ではありません。また、単にポリゴンをGeoParquetに保存するだけで、隣接関係が自動的に定義されるわけでもありません。
12. COCOとSpatialArrowは併用できる
両者を「どちらか一方しか使えない形式」と捉える必要はありません。
| 比較点 | 画像単位のCOCOデータセット | SpatialArrowの設計 |
|---|---|---|
| 中心となる単位 | 画像と画像内注釈 | 地理空間の正本と実行時ビュー |
| 空間参照 | 外部情報・拡張で補う | データ契約の構成要素として管理 |
| 地物の識別 | 画像・注釈IDを中心に扱う | 永続的な地物IDとビューの関係を保持 |
| 入力条件の変更 | 固定チップ中心の運用では再生成が生じやすい | 正本を再利用してビュー条件を変更 |
| モデルへの接続 | 対応する既存ツールを利用しやすい | モデル別アダプターを整備する |
例えば、正本をSpatialArrowの構成で管理し、特定モデルや評価器に渡す段階でCOCO互換の注釈を生成する構成が考えられます。
COCOが担う学習・評価の互換性を利用しながら、元の地物、画像、座標変換の対応を別の層で維持できます。
13. AI-Readyを、テンソル化だけで終わらせない
SpatialArrowが目指すAI-Readyは、「配列に変換できる」という意味だけではありません。[1]
- 正本を保持する:元画像、地物、座標系、ID、メタデータを対応付ける。
- 入力条件を解決する:範囲、解像度、バンド、入力サイズからビューを構成する。
- 画像と教師を一致させる:同じ範囲・同じ変換条件から両者を生成する。
- 由来を追跡できる:モデル入力から元データと生成条件をたどれる。
この構成でも、元データの位置ずれやアノテーションの誤りは自動的には解消されません。画像・ベクターの重ね合わせ確認、座標変換の往復試験、更新時の版管理が必要です。
また、実行時にビューを作る場合も、trainとvalidの重複や同じ地物の混入を防ぐ分割方針が必要です。生成方法が動的であること自体は、データ漏洩の防止を保証しません。
14. 設計の適用範囲と今後の検証
添付のv0.1資料では、メモリ内リポジトリ、window読出し、座標変換、view edge、custom collateなどの最小参照実装を示しています。一方、実運用規模のストレージ連携や性能評価は、段階的に整備・検証する位置付けです。[1]
実行時生成には処理コストがあるため、事前チップ方式より常に高速とは限りません。Arrowでコピーを減らせる部分があっても、画像の展開、CRS変換、形状処理、正規化まで含めた処理全体がゼロコピーになるわけではありません。
基本仕様はアフィン参照を対象とし、RPCやGCPなどによる非アフィン参照は対象外です。固定したモデルと小規模なデータだけを扱う場合には、事前チップ方式の方が簡便なこともあります。
今後は、精度だけでなく、次の観点から有効範囲を確認する必要があります。
- DataLoader待機時間、処理量、メモリ・ストレージ使用量
- 座標変換と画素規約の整合性
- モデル変更時の再利用性
- 部分地物を含む学習・評価の方針
- データ更新時の追跡可能性
将来的には、画像と形状に加えて、建物用途や時系列情報などを対応付ける構想もあります。その際も、登録情報が示す状態と、画像などで観測した状態を区別し、何を根拠にモデルが判断するのかを管理する必要があります。これは資料で示された今後の展開であり、すべてが接続済みという意味ではありません。
おわりに
COCO形式は、画像と物体の注釈を学習・評価へ渡すうえで有用です。しかし、GeoAIでは、その外側にある座標系、元画像、地物ID、部分性、変換履歴まで管理する必要があります。
SpatialArrowは、この対応関係をデータ契約として定義し、地理空間データの正本から、モデルが必要とする入力を実行時に構成するための提案です。
画像のために地物を作り直し続けるのではなく、地物と空間参照を保ちながら、モデルへの渡し方を変える。 この考え方を、次の実装記事では屋根上ソーラーパネルのBB検出に適用し、データローダの構成と検証結果を紹介します。
第1回【SpatialArrow概念編】GeoAI学習で「画像分割によって地物が途切れる問題」をどう解決するか?(固定タイル方式の課題とSpatialArrowの設計思想)
第2回【SpatialArrow実装編】GeoAI学習で地物を切り刻まずに学習へ渡す(ROI単位で画像とBBを生成する、AI-ReadyなDataLoaderの実装)
第3回【SpatialArrow検証編】GeoAI学習で地物を分割せずに学習させたら精度は上がるか?(屋根上PV検出の比較検証で見逃しが16.5%減少)
参考資料
[1] SpatialArrow|株式会社オービタルネット
[2] COCO — Data Format
[3] COCO API — pycocotools
[4] GeoArrow Specification
[5] GeoParquet
