宇宙からクルマを数えてみたら、“日常”という名の風景が見えてきた

40度に迫る猛暑が続く中・・・街はアスファルトから陽炎が立ちのぼり、車のボンネットも触れないほどの熱さ。
そんな現実をよそに、写真の中では、整列した車たちがまるで海辺でひとときのバカンスを楽しんでいるようにも見えました。
「車にも、こんな夢があってもいいよね」——そう思えるような、静かでどこか詩的な1枚から、今回の実験は始まりました。

今、衛星データとAIの融合がどんどん進化しています。特に「地上にある小さな物体を、宇宙からどう認識するか?」というテーマは、インフラ監視や防災、都市計画など多くの分野で注目されています。

ということで今回は、AIを使って衛星写真から“自動車”を検出する実験を行ってみました!使用したのは、ディープラーニングベースの物体検出アルゴリズム「YOLOv8 OBB」。実際の衛星画像を使った検出結果や、そこで分かった意外な課題も紹介していきます。

 

 なぜ衛星写真で車を検出するのか?

一見すると「そんな細かいもの見えるの?」と思うかもしれませんが、今の高解像度な衛星写真なら50cm未満の分解能で地上を観測することが可能です。

たとえば、施設などの駐車場に停まっている車や道路を走行中の車をカウントすることで、「混雑状況」「車両の傾向」など、さまざまなインサイトが得られます。

ただし、人の目で数えるのは限界があります。 そこで登場するのがAI。大量の衛星画像を自動で解析し、必要な物体だけを検出できれば、業務の効率化や新たな価値創出につながります。

 

 まずは物体検出の基本から

物体検出アルゴリズムで有名なのが、YOLO(You Only Look Once)という画像中の物体を高速かつ正確に検出するアルゴリズムがある。
これは、機械学習モデルの一種で、ディープラーニングに基づいていて以下のような特徴がある。

  • 処理速度:画像を一度スキャンすると検出と識別の処理を同時に行うため、高速で動作可能
  • 検出精度:複数のアンカーボックスを使用することで、異なる形状の物体に対しても適切に反応
  • 応用範囲:自動運転、セキュリティ対策、医療分野の画像診断など、様々な分野で活用

You Only Look Once: Unified, Real-Time Object Detectionより引用

 

このアルゴリズムは、自動運転車の物体検知、監視カメラの人検知などにも応用されているので、見たことあるのではないかと思う。
今回は「YOLOv8 OBB」、「DOTAデータセット」を使って、衛星画像からクルマを数えていきます。

 

 YOLOv8 OBBとDOTAデータセットって何?

物体検出「YOLO(You Only Look Once)」ですが、今回使用するのはUltralytics社が開発したYOLOv8 OBB版です。
OBB(Oriented Bounding Box)は、検出した物体の角度が検出可能な回転ボックスに対応したモデルで、航空・衛星写真のように、物体が真上から綺麗に並んでいない画像でも、物体の向きを考慮して正確に検出できるのが特徴です。

https://docs.ultralytics.com/ja/tasks/obb/

 

学習モデルは、DOTA(Dataset for Object deTection in Aerial images)という衛星画像向けのオープンデータをベースにしたモデルを活用しました。これにより、「衛星画像に写った車」を効率よく検出できます。

https://docs.ultralytics.com/ja/datasets/obb/dota-v2/

 

 今回もM3 Macでスクリプトを実行

Ultralytics の YOLOv8 OBB モデルにより物体検出後に以下の出力を実施、YOLOv8-OBBモデルを使用。M3 Mac (Apple Silicon) でGPU処理を行った。

 

DOTA学習済みYOLOv5モデルを使う手順(Mac M1/M2/M3対応)

 

  • Python 3.8〜3.10(3.11以上だとTorchで不具合が出やすい)
  • torch と opencv-python は既にインストール済みと仮定

 

ステップ1:YOLOv5のリポジトリをクローン

git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt

ステップ2:Ultralytics YOLOv8 OBB モデルの使用方法

Ultralytics パッケージのインストール

pip install ultralytics

ステップ3:実行コマンド

python detect_vehicle_obb.py <画像ファイル>

※モデルファイルは、スクリプト内の YOLO(‘yolov8x-obb.pt’) にて自動的にダウンロードされます。

 

スクリプトコード(detect_vehicle_obb.py)

  • 検出結果のポリゴン情報,IDを元画像に描画してイメージ出力
  • 検出結果をJSON形式で出力
  • 検出結果をGeoJSON形式(緯度経度は画像の相対値)に変換出力
import sys
import os
import json
from PIL import Image, ImageDraw, ImageFont
from ultralytics import YOLO
from pathlib import Path

def save_json(boxes, base_filename):
    results = []
    for i in range(len(boxes)):
        polygon = boxes.xyxyxyxy[i].tolist()
        results.append({
            "id": i + 1,
            "class": int(boxes.cls[i]),
            "confidence": float(boxes.conf[i]),
            "polygon": polygon
        })
    with open(f"{base_filename}_result.json", "w") as f:
    json.dump(results, f, indent=2)

def save_geojson(boxes, base_filename):
    features = []
    for i in range(len(boxes)):
        polygon = boxes.xyxyxyxy[i].tolist()
        coords = polygon + [polygon[0]] # 閉じるために始点を追加
        feature = {
            "type": "Feature",
            "properties": {
            "id": i + 1,
            "class": int(boxes.cls[i]),
            "confidence": float(boxes.conf[i])
        },
        "geometry": {
            "type": "Polygon",
            "coordinates": [[ [x, y] for x, y in coords ]]
        }
    }
    features.append(feature)

    geojson = {
        "type": "FeatureCollection",
        "features": features
    }

    with open(f"{base_filename}_result.geojson", "w") as f:
        json.dump(geojson, f, indent=2)

def draw_polygons(image_path, boxes, output_path):
    image = Image.open(image_path).convert("RGB")
    draw = ImageDraw.Draw(image)
    try:
        font = ImageFont.truetype("arial.ttf", 16)
    except:
        font = ImageFont.load_default()

    for i in range(len(boxes)):
        polygon = boxes.xyxyxyxy[i].tolist()
        draw.polygon(polygon, outline="red", width=2)
        draw.text((polygon[0][0], polygon[0][1] - 10), str(i + 1), fill="red", font=font)

    image.save(output_path)

def main(image_path):
    base_filename = os.path.splitext(os.path.basename(image_path))[0]
    output_img_path = f"{base_filename}_result.png"

    print("モデルを読み込み中...")
    model = YOLO("yolov8x-obb.pt") # 高精度 OBB モデル

    print("推論を実行中...", image_path)
    results = model(image_path)
    boxes = results[0].obb

    if boxes is None or len(boxes) == 0:
    print("⚠️ 結果画像が保存されていません(検出なしの可能性あり)")
    print("✅ 検出オブジェクト数: 0")
    return

    print("✅ 検出オブジェクト数:", len(boxes))

    # 画像保存(ポリゴンで描画)
    draw_polygons(image_path, boxes, output_img_path)
    print("🖼️ 結果画像を保存しました:", output_img_path)

    # JSON保存
    save_json(boxes, base_filename)
    print("📝 JSONを保存しました:", f"{base_filename}_result.json")

    # GeoJSON保存
    save_geojson(boxes, base_filename)
    print("🌍 GeoJSONを保存しました:", f"{base_filename}_result.geojson")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("使い方: python detect_vehicle_obb.py <画像ファイル>")
    else:
        main(sys.argv[1])

 

 実際にやってみた!自動車検出テスト

今回は、使用可能な衛星データの関係上、航空写真を擬似的に分解能を落として、衛星データ程度の分解脳にしてクルマの検出を試してみました。

画像の分解能は、おおよそ50cm程度。では、検出実験スタート!

python detect_vehicle_obb.py car.png
モデルを読み込み中...
推論を実行中... car.png

image 1/1 /Users/habe/car/yolov5/car.png: 768x1024 1021.3ms
Speed: 3.7ms preprocess, 1021.3ms inference, 10.8ms postprocess per image at shape (1, 3, 768, 1024)
✅ 検出オブジェクト数: 133
🖼️ 結果画像を保存しました: car_result.png
📝 JSONを保存しました: car_result.json
🌍 GeoJSONを保存しました: car_result.geojson

検出されたクルマの台数は、133台…
意外と取りこぼしが多い感じですね。
現状の衛星データの分解能では、クルマの正確な検出は難しいのかもしれません。

 

試しに元の航空写真でクルマの検出を試してみました。

python detect_vehicle_obb.py car_original.png 
モデルを読み込み中...
推論を実行中... car_original.png

image 1/1 /Users/habe/car/yolov5/car_original.png: 768x1024 1029.7ms
Speed: 4.7ms preprocess, 1029.7ms inference, 55.1ms postprocess per image at shape (1, 3, 768, 1024)
✅ 検出オブジェクト数: 217
🖼️ 結果画像を保存しました: car_original_result.png
📝 JSONを保存しました: car_original_result.json
🌍 GeoJSONを保存しました: car_original_result.geojson

検出されたクルマの台数は、217台!
パッと見た感じ検出漏れもなく高精度に検出されてます。
分解能が4倍の15cm程度あれば問題なく検出することができそうです。

 

 検出率のカギは「高解像度化」にあり!

実験の中で印象的だったのは、解像度が低くてもYOLOモデルで検出ができるというところでした。
もちろん、低分解能の衛星写真ではクルマの台数監視など商用で活用するには精度がイマイチなところもあります。

今回の実験では、高解像度の航空写真の解像度を下げて衛星データ程度の分解能にしましたが、逆に分解能が低い衛星データをAIで高解像度化することで検出精度が上がる可能性があるのではないかと感じました。

 

 自動車検出のこれからの可能性

今回のような「静止画像ベースの車検出」は、以下のようなユースケースにもつながります:

  • 駐車場の混雑モニタリング

  • 不法駐車や長期駐車の可視化

  • 災害時の避難状況チェック

  • 高速道路の交通量把握

  • 街の賑わいを見える化(イベント・観光地など)

特に、自治体やインフラ事業者にとっては“省人化”や“リアルタイム性”が大きな武器になります。

 

 まとめ:衛星から地上の「今」を読み取る時代へ

今回紹介したように、AIと衛星データを組み合わせれば、地上の様子を自動で把握することが可能になります。

そして、私たちデジオンでは、さらにその先へ。

現在進めているSpaceVision事業では、独自生成AIモデルによって高精細にする超解像化技術により、低分解能の衛星写真でも細部まで詳細に観察できる画像に変換することができます。

https://www.digion.com/business/space/

 

この事業では、人工衛星を活用したデータ解析や、AIを用いた画像解析技術を駆使し、地球観測やインフラ管理、環境モニタリングなどの分野に貢献しています。特に、生成AIを活用したデータ解析により、従来の手法では難しかったパターン認識や異常検知を、より精度高く・高速に行うことが可能になっています。

ということで、衛星とAIの力で“地球を見守る”取り組みは、今まさに進化の真っ只中!次回は、もう一歩先の技術についても掘り下げていきたいと思います。

お楽しみに!

Hiroshi Abe
Published on Jul, 2025

記事一覧へ

おすすめ記事