本記事のベンチマーク値・モデルサイズは Raspberry Pi 5 (8GB) / Raspberry Pi 4 (4GB)、64bit Raspberry Pi OS Bookworm 環境を想定した 参考値 です。実機性能はカーネルバージョン・スワップ設定・電源(公式 5V/5A 推奨)・冷却条件で変動します。実運用では必ず本番相当の環境で計測してください。本記事のコードは Python 3.11 系・llama.cpp 2026 年春時点のビルドを前提としています。
はじめに:なぜラズパイで vLM を動かすのか
「カメラ画像を見て、何が起きているか日本語で説明してほしい」「製品の傷を写真から判定して、改善コメントまで出してほしい」——従来の画像分類CNNでは 「クラスを返すだけ」 で止まっていたタスクが、vLM (Vision Language Model) の登場で 「画像を理解して、文章で答える」 領域まで一気に踏み込めるようになりました。
これまで vLM といえば GPT-4o / Claude / Gemini など、クラウド経由で大型GPUを使う前提でした。しかし 2024〜2026 年にかけて 1B〜2B パラメータ級の小型 vLM が急増し、量子化技術と組み合わせれば Raspberry Pi 5 でもローカル推論が現実的 になっています。
本記事では「クラウドに送れない画像」「ネットワークが弱い現場」「サブスクコストを掛けたくない案件」で Raspberry Pi + 小型 vLM を主役に据えた構築ノウハウを、実コード付きで体系的に解説します。
テクノスフィアでは Raspberry Pi をベースとした 産業 IoT・画像認識システムの受託開発 を多数手がけており、近年は 「現場で完結する小型 vLM」 をエッジに搭載するケースが急増しています。本記事は実案件で蓄積した知見と検証結果をもとに構成しています。
vLM (Vision Language Model) とは?
vLM(Vision Language Model、視覚言語モデル)とは、画像と言語(テキスト)を同じ意味空間で扱える マルチモーダル AI の総称です。LLM が「文章を入力して文章を返す」のに対し、vLM は 「画像+質問文を入力して文章を返す」 ことができます。
vLM の基本構造
多くの vLM は以下の 3 つのモジュールで構成されています。
- Vision Encoder:画像を特徴ベクトル列に変換する(SigLIP / CLIP-ViT が主流)
- Projector (Connector):画像特徴を LLM の埋め込み空間にマップする小さな MLP
- LLM (Decoder):画像トークン+テキストトークンを並べてテキストを生成する
つまり vLM の本質は 「画像を擬似的なトークン列に変換して LLM に食わせる」 仕組みであり、LLM 部分が小さいほどラズパイでも動かしやすくなります。
vLM で何ができるか(代表タスク)
- 画像説明 (Image Captioning):画像の内容を文章で記述
- 視覚的質問応答 (VQA):「この製品にキズはありますか?」のような質問に回答
- OCR + 理解:画像中の文字を読み取り、意味を解釈(伝票・ラベル・看板)
- 物体検出+言語化:「左から2番目の棚に欠品があります」のような位置情報付き出力
- 文書理解:図表入りの PDF / スキャン画像を要約
- 動作分析:連続フレームから人や機械の状態を文章化
エッジで vLM を動かす5つのメリット
クラウド vLM API が高品質である現代に、あえてラズパイで動かす理由は何でしょうか。実案件で評価される主な理由は次の 5 点です。
| 観点 | クラウド vLM | ラズパイ vLM |
|---|---|---|
| 機密データの扱い | 外部送信が必要(規制で NG のケース多) | 画像が機器外に出ない |
| 応答遅延 | 500ms〜数秒(往復+待ち行列) | ローカル完結で安定 |
| ランニングコスト | 1呼出 0.5〜数円 × 大量推論 | 電気代のみ |
| ネットワーク依存 | 切断時はサービス停止 | オフラインで動作 |
| カスタマイズ | プロンプト調整のみ | 追加学習・量子化・蒸留が可能 |
医療・製造・防衛・行政の現場では「画像をインターネットに出してはいけない」という制約があります。クラウドが原則NGな案件で、vLM の表現力が欲しい場合の唯一の現実解がエッジ vLM です。
ラズパイで動く小型 vLM の選択肢
2026 年春時点で、Raspberry Pi 4 / 5 クラスのリソース(CPU のみ、RAM 4〜8GB)で実用速度を出せる代表的な vLM を整理します。
| モデル | パラメータ | RAM(INT4量子化) | 強み | 用途 |
|---|---|---|---|---|
| Moondream2 | 1.86B | 約 1.2〜1.5GB | 軽量・VQA 強い | 製品検査・棚モニタ・防犯 |
| SmolVLM-256M / 500M | 0.26B / 0.5B | 0.3〜0.8GB | 圧倒的に軽い・常時推論向け | ストリーム監視・低消費電力 |
| SmolVLM2-2.2B | 2.2B | 約 1.5GB | 軽量+高精度 | OCR・文書理解 |
| Qwen2-VL-2B | 2.0B | 約 1.5GB | 動的解像度・多言語に強い | 日本語UI・帳票読取 |
| InternVL2-1B / 2B | 0.9B / 2.2B | 0.8〜1.5GB | 商用ライセンス・OCR | 業務帳票・図面解析 |
| LLaVA-OneVision 0.5B | 0.5B | 約 0.7GB | 多タスク・低レイテンシ | 軽量バッチ処理 |
まずは 「SmolVLM-256M / 500M で要件を満たせるか」を最初に検証するのがおすすめです。性能が足りなければ Moondream2 や Qwen2-VL-2B へ段階的にスケールアップ。「いきなり 7B/8B モデルから検討」しないのが、エッジ vLM 設計の鉄則です。
ハードウェア構成と前準備
推奨ハードウェア
| 項目 | 推奨 | 備考 |
|---|---|---|
| 本体 | Raspberry Pi 5 (8GB) | Pi 4 (4GB) でも 0.5B 級なら可。Pi 5 で 2B 級が現実的 |
| ストレージ | NVMe SSD (HAT or USB3) | モデル読込が SD カードの 3〜5 倍速くなる |
| カメラ | Pi Camera Module 3 / USB UVC | 1080p で十分。vLM 入力は 384〜512px に縮小される |
| 電源 | 公式 27W USB-C PD アダプタ | 推論中はピーク電流が増えるため必須 |
| 冷却 | アクティブクーラー(純正可) | 長時間推論ではサーマルスロットリングを防ぐ |
| OS | Raspberry Pi OS 64bit (Bookworm) | 32bit では多くのモデルが動かない |
OSの初期セットアップ
# 64bit OSであることを確認
uname -m # → aarch64 であること
# システム更新と基本ツール
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-venv git cmake build-essential \
libopenblas-dev libjpeg-dev libpng-dev v4l-utils
# スワップを増やす(推論中のメモリ逼迫対策)
sudo dphys-swapfile swapoff
sudo sed -i 's/^CONF_SWAPSIZE=.*/CONF_SWAPSIZE=2048/' /etc/dphys-swapfile
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
# GPU メモリは vLM 推論には使わないので最小化(VideoCore は重要でない)
# /boot/firmware/config.txt に下記を追記
# gpu_mem=16
Python 仮想環境
python3 -m venv ~/vlm-env
source ~/vlm-env/bin/activate
pip install --upgrade pip wheel
# 共通の最小依存
pip install pillow numpy opencv-python-headless requests
実装①:Moondream2 で画像を「会話」させる
Moondream2 は 1.86B パラメータの小型 vLM で、Raspberry Pi 5 (8GB) で実用的に動作する代表的なモデルです。VQA(視覚的質問応答)に強く、「製品にキズはあるか」「左の棚に欠品はあるか」 といった現場質問に向いています。
セットアップ
# PyTorch (CPU版、aarch64対応) と transformers
pip install --index-url https://download.pytorch.org/whl/cpu torch torchvision
pip install transformers accelerate einops pyvips
最小実装:画像 → 説明文
from transformers import AutoModelForCausalLM, AutoTokenizer
from PIL import Image
import torch
MODEL_ID = "vikhyatk/moondream2"
# Raspberry Pi は CPU 実行のため float32 でロードする
# (PyTorch の CPU バックエンドは float16 演算をほぼサポートしないため。
# GPU/CUDA がある環境でのみ torch.float16 が有効。
# ※省メモリ・高速化を狙うなら後述の llama.cpp + GGUF 量子化を推奨)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
trust_remote_code=True,
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
image = Image.open("/home/pi/capture.jpg").convert("RGB")
# Step1: 画像をエンコード(重い処理。1回だけ)
enc = model.encode_image(image)
# Step2: 同じ画像に複数の質問を投げる(軽い)
print(model.answer_question(enc, "この画像に何が写っていますか?", tokenizer))
print(model.answer_question(enc, "棚に欠品はありますか?", tokenizer))
print(model.answer_question(enc, "人物は何人いますか?", tokenizer))
encode_image() は重い処理(数秒〜十数秒)ですが、同じ画像に対する複数の質問では再利用できます。製品検査で「キズ」「変色」「ラベルの向き」を順に確認するようなパイプラインでは、エンコードを1回・質問をN回にする設計が必須です。
カメラからリアルタイム推論
import cv2
import time
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
QUESTION = "この映像に異常はありますか?1文で答えてください。"
while True:
ok, frame = cap.read()
if not ok:
continue
img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
t0 = time.time()
enc = model.encode_image(img)
answer = model.answer_question(enc, QUESTION, tokenizer)
dt = time.time() - t0
print(f"[{dt:.1f}s] {answer}")
time.sleep(5) # 5秒ごとに推論(連続推論は熱対策上推奨しない)
実装②:SmolVLM-256M で超軽量ストリーム推論
SmolVLM-256M はわずか 2.6 億パラメータながら、Hugging Face が公開する 「世界最小級の実用 vLM」 です。Raspberry Pi 4 (4GB) でも動作し、Pi 5 では カメラフレーム毎秒の連続推論 に近い速度が出ます。
セットアップ
pip install --upgrade transformers
# 量子化が必要なら
pip install bitsandbytes accelerate
実装例
from transformers import AutoProcessor, AutoModelForVision2Seq
from PIL import Image
import torch
MODEL_ID = "HuggingFaceTB/SmolVLM-256M-Instruct"
processor = AutoProcessor.from_pretrained(MODEL_ID)
model = AutoModelForVision2Seq.from_pretrained(
MODEL_ID,
torch_dtype=torch.float32, # CPU(Raspberry Pi)実行のため float32。CUDA環境なら float16 可
low_cpu_mem_usage=True,
).eval()
def ask(image_path: str, question: str) -> str:
image = Image.open(image_path).convert("RGB")
# SmolVLM はチャットテンプレートで画像位置を指定
messages = [{
"role": "user",
"content": [
{"type": "image"},
{"type": "text", "text": question},
],
}]
prompt = processor.apply_chat_template(messages, add_generation_prompt=True)
inputs = processor(text=prompt, images=[image], return_tensors="pt")
with torch.inference_mode():
out = model.generate(**inputs, max_new_tokens=64, do_sample=False)
return processor.decode(out[0][inputs["input_ids"].size(1):], skip_special_tokens=True)
print(ask("shelf.jpg", "棚の状態を1文で教えて"))
print(ask("road.jpg", "歩行者は何人ですか?"))
SmolVLM-256M は精度では Moondream2 や Qwen2-VL に劣りますが、「常時カメラに張り付かせる用途」では圧倒的に有利です。例えば「人が立ち入ったら通知」「棚の状態が変わったら検知」など、イベント検出のフロントエンドとして使い、詳細解析は別モデル or クラウドへ渡すハイブリッド構成が効果的です。
実装③:llama.cpp + GGUF で速度を稼ぐ
Python (transformers) は実装が楽ですが、ARM CPU での実行速度 という観点では llama.cpp + GGUF(4bit / 5bit 量子化)に分があります。Raspberry Pi 5 では 体感 1.5〜3 倍の高速化 が見込めます。
llama.cpp のビルド(aarch64)
cd ~
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
# NEON/dotprod を有効化したリリースビルド
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DGGML_NATIVE=ON \
-DLLAMA_BLAS=ON -DLLAMA_BLAS_VENDOR=OpenBLAS
cmake --build build --config Release -j$(nproc)
# vLM 用の実行ファイル(マルチモーダル対応)
ls build/bin/ | grep -E "llama-mtmd|llama-llava"
GGUF モデルの取得(例:Moondream2 INT4)
# Hugging Face CLI 経由(モデル名は適宜置換)
pip install -U huggingface_hub
huggingface-cli download vikhyatk/moondream2 \
--include "*q4*.gguf" "*mmproj*.gguf" \
--local-dir ~/models/moondream2
ls ~/models/moondream2/
# moondream2-text-model-f16_q4_0.gguf
# moondream2-mmproj-f16.gguf
推論実行(マルチモーダル CLI)
~/llama.cpp/build/bin/llama-mtmd-cli \
-m ~/models/moondream2/moondream2-text-model-f16_q4_0.gguf \
--mmproj ~/models/moondream2/moondream2-mmproj-f16.gguf \
--image ~/capture.jpg \
-p "この画像に異常があれば1文で報告してください。" \
-n 64 -t 4
# -t : 使うスレッド数。Pi 5 では 3〜4 がスイートスポット
HTTP サーバとしてバックグラウンド起動
常駐させて他のアプリから呼ぶには llama-server を使います。Python / Node.js / シェルから OpenAI 互換 API で叩けるのが強みです。
~/llama.cpp/build/bin/llama-server \
-m ~/models/moondream2/moondream2-text-model-f16_q4_0.gguf \
--mmproj ~/models/moondream2/moondream2-mmproj-f16.gguf \
--host 0.0.0.0 --port 8080 \
-c 2048 -t 4 -ngl 0 &
# Python から呼び出し
import base64, requests
with open("capture.jpg","rb") as f:
b64 = base64.b64encode(f.read()).decode()
r = requests.post("http://localhost:8080/v1/chat/completions", json={
"messages":[
{"role":"user","content":[
{"type":"text","text":"棚に欠品はありますか?"},
{"type":"image_url","image_url":{"url":f"data:image/jpeg;base64,{b64}"}}
]}
],
"max_tokens": 64
})
print(r.json()["choices"][0]["message"]["content"])
Raspberry Pi 5 では Q4_K_M(4bit, K-quant medium)が 速度と精度のバランスが最も良い 選択肢です。Q3_K_M は更に軽いものの、日本語応答の品質が目に見えて劣化します。Q5_K_M / Q6_K は精度は高いが Pi 5 でも速度が体感で重くなり、メモリも逼迫しがちです。
限られたリソースで性能を引き出す8つのテクニック
ラズパイ vLM の体感性能は、モデル選定だけでなく実装の作り込みで2〜10倍変わります。実案件で効いた工夫を 8 つ紹介します。
① 入力解像度を意図的に下げる
vLM の Vision Encoder は内部で 384〜512px などに縮小しています。入力を 1920×1080 のまま渡しても、ほとんどのモデルでは意味がないどころか、デコード負荷で遅くなるだけです。事前に Pillow.thumbnail((640, 480)) 等で縮小しましょう。
② max_new_tokens は最小限に
推論時間は 「生成トークン数」に比例します。「異常があるか/ないか」だけ知りたいケースで 256 トークン生成するのは無駄。max_new_tokens=32〜64 に絞り、プロンプトで「1文で」「Yes/No で」と明示します。
③ 質問を「分類タスク化」する
「異常があれば yes、なければ no で答えなさい」のようにプロンプトを 離散的な選択肢に閉じ込めると、後段プログラムが扱いやすく、生成も短く済みます。チェーン・オブ・ソートが必要ないタスクではこれが最速です。
④ Vision Encoder の結果をキャッシュ
同じ画像に対する複数質問は、Moondream2 のように encode_image() の結果を保持して使い回します。llama.cpp でも --image で同一ファイルを渡せば再エンコードを抑えられます。
⑤ プリプロセスを軽量化(GPU を当てにしない)
OpenCV は opencv-python-headless を使い GUI ライブラリを排除。色変換は cv2.cvtColor 一発で済ませ、リサイズは cv2.INTER_AREA を選択。NumPy→PIL の往復は避けます。
⑥ スレッド数を CPU コアに合わせる
Raspberry Pi 5 は 4 コア。-t 4 が最も速いとは限らず、I/O やシステム動作と競合するため -t 3 がスイートスポットになるケースもあります。本番想定の負荷で必ず実測しましょう。
⑦ プロセス常駐+IPC 設計
毎回 Python を起動してモデルをロードしていては 10〜30 秒のロード時間が毎回乗ります。llama-server や FastAPI でモデルを常駐させ、フロントから HTTP / UNIX ソケット / ZeroMQ で呼び出す設計にします。
⑧ 冷却とサーマルスロットリング対策
長時間推論では Pi 5 で 80℃ を超えやすく、自動的にクロックが下がります。アクティブクーラーは必須、ケースは通気の良いものを。vcgencmd measure_temp で常時温度をモニタし、80℃ 手前で 推論間隔を伸ばすバックオフ制御を入れると安定運用できます。
# サーマルバックオフ例
import subprocess, time
def cpu_temp() -> float:
out = subprocess.check_output(["vcgencmd", "measure_temp"]).decode()
return float(out.split("=")[1].split("'")[0])
while True:
if cpu_temp() > 78:
time.sleep(10)
continue
# 通常の推論ループ
run_inference()
実案件での活用パターン
テクノスフィアでこれまでに検証・提案してきた、ラズパイ vLM の典型的な活用パターンを 5 つご紹介します。
① 製造ラインの簡易外観検査
従来は 欠陥クラスごとに学習データを集めて CNN を作る必要がありましたが、vLM なら プロンプトを変えるだけで検査項目を追加できます。「ラベルが斜めに貼られていないか」「フィルムに気泡はないか」など、定性的な検査項目との相性が抜群です。
② 小売の棚モニタリング・欠品検知
店内 Wi-Fi がない・帯域が細い店舗でも、ラズパイ+USBカメラ+vLM の構成なら 機器内で完結。「2 段目の右端が空いています」のように 位置情報付きで通知させられます。
③ 農業ハウスの作物・病害観察
圃場はネットワーク条件が厳しく、撮影画像をクラウドに送れないケースが多々あります。エッジ vLM で「葉に黄変が見られます」「水滴が異常に多いです」のように 自然言語でログを残し、要約のみクラウドへ送る運用が有効です。
④ 設備保全:計器盤の自動読み取り
古いアナログ計器・指針メーター・LCD パネルを Raspberry Pi カメラ+vLM で読み取り、SCADA 連携。CNN ベースの OCR より レイアウト変動・照明変化に強いのが現場で評価されるポイントです。
⑤ 入退室・安全管理
「ヘルメットを着用していない人がいる」「立入禁止エリアに人がいる」といった 安全ルール監視は、vLM のゼロショット能力が活きる領域。プロンプトでルールを記述するだけでルール追加できます。
テクノスフィアでは、要件ヒアリング → vLM 選定 → 量子化・最適化 → 筐体・配線 → 現場設置 → 運用監視まで 一気通貫で対応しています。「クラウドに送れない画像で AI 化したい」「PoC をすぐ作りたい」場合はお問い合わせからご相談ください。
パフォーマンス比較(参考値)
Raspberry Pi 5 (8GB) / 公式アクティブクーラー / Q4_K_M 量子化(llama.cpp)/ 1枚の画像に「この画像を1文で説明してください」を投げた場合の参考値です。あくまで弊社環境での実測例であり、画像内容・プロンプト長で大きく変動します。
| モデル | 画像エンコード | 生成 (64 tok) | 合計 | ピーク RAM |
|---|---|---|---|---|
| SmolVLM-256M | 約 0.4 秒 | 約 1.5 秒 | 約 2 秒 | 約 0.5GB |
| SmolVLM-500M | 約 0.8 秒 | 約 2.5 秒 | 約 3 秒 | 約 0.9GB |
| Moondream2 (1.86B) | 約 3〜4 秒 | 約 4〜5 秒 | 約 8 秒 | 約 1.5GB |
| Qwen2-VL-2B | 約 4 秒 | 約 5〜6 秒 | 約 10 秒 | 約 1.6GB |
これらは 「リアルタイム動画解析」には足りない速度ですが、「数秒〜数十秒に1回トリガで推論する用途」には十分実用的な水準です。秒間複数フレームが必要なら、軽量検出器(YOLOv8n / OpenCV モーション検出)でイベントトリガを作り、vLM はトリガ時のみ呼ぶ ハイブリッド構成が定石です。
トラブルシューティング
| 症状 | 原因 | 対策 |
|---|---|---|
| モデルロード中に Killed | RAM 不足(OOM Killer 発動) | スワップ拡張、より小さなモデル(256M/500M)、量子化レベルを下げる(Q4→Q3) |
| 推論中に温度上昇でフリーズ | サーモスロットリング・電源不足 | 純正クーラー、27W PD電源、vcgencmdでバックオフ制御 |
| 応答が意味不明・文字化け | 量子化が攻めすぎ / プロンプトテンプレ不一致 | Q5_K_M に上げる、チャットテンプレートを公式準拠で使う |
| 日本語応答が英語混じり | モデルが日本語データを十分に学習していない | Qwen2-VL / InternVL2 を選ぶ、出力に「日本語で」と明示 |
| 毎回起動が遅い | SD カード I/O / モデル毎回ロード | NVMe SSD 化、llama-server 常駐+IPC 構成へ変更 |
| 映像が止まる | 推論ループが UI / カメラ取得をブロック | カメラ取得と推論を別スレッド/プロセスに分離(Queue で連携) |
まとめ
この記事のまとめ
- vLM (Vision Language Model) は「画像+質問 → 文章」を生成するマルチモーダル AI
- Raspberry Pi 5 (8GB) + 量子化により、1〜2B クラスの vLM がエッジで実用速度に到達
- 軽さなら SmolVLM-256M/500M、バランスなら Moondream2、日本語 OCR なら Qwen2-VL-2B / InternVL2 が現実的な選択肢
- 速度の鍵は llama.cpp + Q4_K_M 量子化、常駐サーバ化、解像度・トークン数の圧縮、Vision Encoder のキャッシュ
- 製造検査・棚モニタ・農業観察・計器読み取り・安全管理など、「クラウドに送れない画像」案件で特に強い
- 軽量検出器でイベント検出 → vLM で言語化、というハイブリッド構成が実運用の定石
テクノスフィアでは Raspberry Pi をはじめとした 組込み・エッジ AI 案件 を、要件定義から PoC・量産・運用まで一気通貫で支援しています。「クラウドを使わずに画像 AI を導入したい」「既存のラインに後付けしたい」「vLM の PoC を最短で立ち上げたい」といったご相談は、お気軽にお問い合わせください。
関連記事
ラズパイ × vLM / エッジ画像 AI の受託開発
クラウドに送れない現場画像を、Raspberry Pi / Jetson 上の vLM(視覚言語モデル)で AI 化する PoC と量産導入を一気通貫で対応。要件ヒアリングから筐体・配線・現場設置・運用監視まで。