オフラインAI×GIS

オフラインAI×GIS【現場で使えるローカル環境】

インターネットがない現場でも、AIとGISを活用できます。

この記事では、オフライン環境でのAI×GIS活用方法を解説します。

1. オフライン環境の必要性

オフラインが必要なケース

【通信環境がない】
・山間部の現場
・地下・トンネル内
・海上・離島
・災害時

【セキュリティ要件】
・機密データを扱う
・外部接続が禁止
・クローズド環境

オフラインのメリット

メリット 内容
セキュリティ データが外部に出ない
安定性 通信状況に依存しない
速度 ローカル処理で高速
コスト 通信費がかからない

従来の課題

【オフラインGISの課題】
・背景地図が表示されない
・オンライン機能が使えない
・データ更新ができない

【解決策】
・事前にデータを準備
・ローカル環境を整備
・オフライン対応ツールを使用

2. 必要な環境構築

ハードウェア要件

【最低構成】
・ノートPC
・CPU:Core i5以上
・メモリ:16GB
・ストレージ:SSD 256GB
・GPU:不要(CPU推論可能)

【推奨構成】
・ノートPC(GPU搭載)
・CPU:Core i7以上
・メモリ:32GB
・ストレージ:SSD 512GB
・GPU:RTX 3060以上

ソフトウェア構成

【GIS】
・QGIS(オフライン対応)
・オフラインタイル

【AI】
・Ollama
・軽量モデル(Phi-3、Qwen2.5など)

【連携】
・Python
・必要なライブラリ

構成図

┌─────────────────────────────────┐
│       オフラインノートPC         │
│                                 │
│  ┌─────────┐    ┌─────────┐    │
│  │  QGIS   │←→│  Python │    │
│  └─────────┘    └────┬────┘    │
│                      │         │
│                      ▼         │
│               ┌─────────┐      │
│               │  Ollama │      │
│               │  (LLM)  │      │
│               └─────────┘      │
│                                 │
│  ┌─────────────────────────┐   │
│  │    ローカルデータ        │   │
│  │  ・オフラインタイル      │   │
│  │  ・GISデータ            │   │
│  │  ・モデルファイル        │   │
│  └─────────────────────────┘   │
└─────────────────────────────────┘

3. オフラインGISの準備

背景地図の準備

【地理院タイルのダウンロード】
・事前に必要範囲をダウンロード
・MBTiles形式で保存
・QGISで表示可能

タイルダウンロードツール

Python
import os
import requests
from pathlib import Path

def download_tile(z, x, y, output_dir):
    """地理院タイルをダウンロード"""
    url = f"https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png"
    output_path = Path(output_dir) / f"{z}/{x}/{y}.png"

    output_path.parent.mkdir(parents=True, exist_ok=True)

    response = requests.get(url)
    if response.status_code == 200:
        with open(output_path, 'wb') as f:
            f.write(response.content)
        return True
    return False

def download_area(min_lon, min_lat, max_lon, max_lat,
                  min_zoom, max_zoom, output_dir):
    """指定範囲のタイルをダウンロード"""
    for z in range(min_zoom, max_zoom + 1):
        # 座標をタイル番号に変換
        min_x, max_y = lonlat_to_tile(min_lon, min_lat, z)
        max_x, min_y = lonlat_to_tile(max_lon, max_lat, z)

        for x in range(min_x, max_x + 1):
            for y in range(min_y, max_y + 1):
                download_tile(z, x, y, output_dir)
                print(f"Downloaded: {z}/{x}/{y}")

def lonlat_to_tile(lon, lat, z):
    """緯度経度をタイル番号に変換"""
    import math
    n = 2 ** z
    x = int((lon + 180) / 360 * n)
    y = int((1 - math.log(math.tan(math.radians(lat)) +
            1/math.cos(math.radians(lat))) / math.pi) / 2 * n)
    return x, y

使用例

Python
# 東京周辺をダウンロード
download_area(
    min_lon=139.5, min_lat=35.5,
    max_lon=140.0, max_lat=36.0,
    min_zoom=10, max_zoom=16,
    output_dir="tiles/"
)

QGISでの設定

【オフラインタイルの読み込み】
1. レイヤ → レイヤを追加 → XYZタイル
2. 新規接続を作成
3. URL: file:///C:/tiles/{z}/{x}/{y}.png
4. 接続してレイヤ追加

4. ローカルLLMの設定

Ollamaのインストール

bash
# オンライン環境で準備
# 1. Ollamaをインストール
# ollama.com からダウンロード

# 2. モデルをダウンロード
ollama pull phi3:mini      # 軽量モデル
ollama pull qwen2.5:7b     # 日本語対応
ollama pull llava          # 画像対応

オフライン移行

【モデルファイルの場所】
Windows: C:\Users\<user>\.ollama\models
Mac: ~/.ollama/models
Linux: ~/.ollama/models

【移行手順】
1. オンライン環境でモデルをダウンロード
2. モデルフォルダをコピー
3. オフラインPCに配置
4. Ollamaを起動

軽量モデルの選択

モデル サイズ 用途 GPU不要
phi3:mini 2.4GB 汎用
qwen2.5:3b 2GB 日本語
llava:7b 4.5GB 画像

CPU推論の設定

bash
# GPU無しでも動作
# Ollamaは自動でCPU推論にフォールバック

# 確認
ollama run phi3:mini
>>> こんにちは

5. 連携システムの構築

基本構成

Python
import subprocess
import json

class OfflineGISAI:
    def __init__(self, model="phi3:mini"):
        self.model = model

    def ask_llm(self, prompt):
        """LLMに質問"""
        result = subprocess.run(
            ["ollama", "run", self.model, prompt],
            capture_output=True,
            text=True
        )
        return result.stdout

    def analyze_coordinates(self, lat, lon):
        """座標を分析"""
        prompt = f"""
        以下の座標について説明してください:
        緯度: {lat}
        経度: {lon}

        この座標の特徴や注意点を教えてください。
        """
        return self.ask_llm(prompt)

    def generate_report(self, data):
        """レポートを生成"""
        prompt = f"""
        以下のGISデータからレポートを作成してください:

        {json.dumps(data, ensure_ascii=False)}

        形式:
        1. 概要
        2. 特徴
        3. 注意点
        """
        return self.ask_llm(prompt)

QGISプラグインとの連携

Python(QGIS)
# QGIS Python コンソールで実行
from qgis.core import QgsProject, QgsVectorLayer
import subprocess

def analyze_layer(layer_name):
    """レイヤーを分析"""
    layer = QgsProject.instance().mapLayersByName(layer_name)[0]

    # データを収集
    features = []
    for feature in layer.getFeatures():
        features.append({
            'id': feature.id(),
            'attributes': dict(zip(
                [field.name() for field in layer.fields()],
                feature.attributes()
            ))
        })

    # LLMで分析
    data_text = str(features[:10])  # 最初の10件
    prompt = f"以下のGISデータの特徴を分析してください:\n{data_text}"

    result = subprocess.run(
        ["ollama", "run", "phi3:mini", prompt],
        capture_output=True,
        text=True
    )

    return result.stdout

# 使用例
analysis = analyze_layer("建物")
print(analysis)

画像分析との連携

Python
import base64
import requests

def analyze_field_photo(image_path, model="llava"):
    """現場写真を分析"""
    with open(image_path, 'rb') as f:
        image_data = base64.b64encode(f.read()).decode('utf-8')

    response = requests.post(
        'http://localhost:11434/api/generate',
        json={
            'model': model,
            'prompt': '現場の状況を説明してください',
            'images': [image_data],
            'stream': False
        }
    )

    return response.json()['response']

6. 実践的な活用例

例1: 現場調査支援

Python
class FieldSurveySystem:
    def __init__(self):
        self.ai = OfflineGISAI()
        self.survey_data = []

    def record_point(self, lat, lon, photo_path=None, notes=""):
        """調査ポイントを記録"""
        record = {
            'lat': lat,
            'lon': lon,
            'notes': notes,
            'timestamp': datetime.now().isoformat()
        }

        # 座標の分析
        record['location_analysis'] = self.ai.analyze_coordinates(lat, lon)

        # 写真がある場合は分析
        if photo_path:
            record['photo_analysis'] = analyze_field_photo(photo_path)

        self.survey_data.append(record)
        return record

    def generate_survey_report(self):
        """調査レポートを生成"""
        return self.ai.generate_report(self.survey_data)

例2: 災害対応支援

Python
def disaster_response_analysis(damage_data):
    """被害状況を分析"""
    prompt = f"""
    以下の被害データを分析し、対応優先度を提案してください:

    {json.dumps(damage_data, ensure_ascii=False)}

    以下の形式で回答:
    1. 被害の概要
    2. 優先対応エリア
    3. 必要なリソースの推定
    4. 注意事項
    """

    ai = OfflineGISAI()
    return ai.ask_llm(prompt)

例3: 設備点検支援

Python
def equipment_inspection(photo_path, equipment_info):
    """設備点検を支援"""
    # 写真分析
    photo_analysis = analyze_field_photo(photo_path)

    # 総合分析
    prompt = f"""
    以下の設備点検結果を評価してください:

    設備情報:
    {json.dumps(equipment_info, ensure_ascii=False)}

    写真分析結果:
    {photo_analysis}

    評価項目:
    1. 設備の状態
    2. 異常の有無
    3. 推奨される対応
    4. 次回点検時期
    """

    ai = OfflineGISAI()
    return ai.ask_llm(prompt)

7. 運用のポイント

事前準備

【必ず準備するもの】
□ オフラインタイル(必要範囲)
□ GISデータ(シェープファイル等)
□ LLMモデル(複数サイズ推奨)
□ 必要なPythonライブラリ

【テスト項目】
□ オフラインでQGISが動作するか
□ Ollamaが動作するか
□ 連携スクリプトが動くか
□ バッテリー持続時間

データ同期

【現場→事務所】
1. 現場でデータ収集
2. 帰社後にデータを転送
3. サーバーと同期

【事務所→現場】
1. 最新データをダウンロード
2. オフライン用に変換
3. ノートPCにコピー

トラブル対策

よくあるトラブル
  • モデルファイルの破損 → バックアップを準備
  • メモリ不足 → 軽量モデルを使用
  • 処理が遅い → バッチ処理で対応
推奨
  • 予備PCの準備
  • 手動作業のマニュアル
  • オフラインドキュメント

8. まとめ

オフラインAI×GISの利点

利点
  • 通信環境に依存しない
  • セキュリティが高い
  • 安定して動作
  • コスト効率が良い

構築のポイント

1. 事前にデータを準備
2. 軽量モデルを選択
3. テストを十分に実施
4. バックアップを用意

活用シーン

活用シーン
  • 山間部での現場調査
  • セキュアな環境での作業
  • 災害時の対応
  • オフライン必須の業務

関連記事

お問い合わせ

オフラインAI×GIS環境の構築についてのご相談は、お気軽にお問い合わせください。

お問い合わせはこちら

最終更新: 2025年1月