はじめに
こんにちは!今回は、Ubuntu 24.10 + Raspberry Pi 4という組み合わせでMIPIカメラを動かすまでの試行錯誤を記録してみました!
「Raspberry Pi OS以外でMIPIカメラって使えるの?」「libcameraって実際どうなの?」という疑問を持っている方も多いと思います。実際に私も最初は「PPMファイルって何?」「JPEG変換どうするの?」と戸惑いました😅
でも最終的には39.8倍という驚異的な圧縮効率を実現できたので、その過程をシェアしたいと思います!
🎯 今回の環境
- OS: Ubuntu 24.10 (Linux 6.11)
- ハードウェア: Raspberry Pi 4 + OV5647 MIPIカメラ
- Python環境: uv 0.8.4 + Python 3.12.7
📝 試行錯誤の記録
1. カメラ検出から始めよう
まず最初に「そもそもカメラが認識されているの?」という基本的なところから確認しました。
# libcameraでカメラ検出
cam --list
結果:
Available cameras:
0 : imx708 [4608x2592] (/base/soc/i2c0mux/i2c@1/imx708@1a)
Modes: 'SRGGB10_CSI2P' : 1536x864 [120.13 fps]
'SRGGB10_CSI2P' : 2304x1296 [56.03 fps]
'SRGGB10_CSI2P' : 4608x2592 [14.35 fps]
1 : ov5647 [2592x1944] (/base/soc/i2c0mux/i2c@1/ov5647@36)
Modes: 'SGBRG10_CSI2P' : 640x480 [58.92 fps]
'SGBRG10_CSI2P' : 1296x972 [43.25 fps]
'SGBRG10_CSI2P' : 1920x1080 [30.62 fps]
'SGBRG10_CSI2P' : 2592x1944 [15.63 fps]
おお!OV5647カメラがちゃんと認識されているじゃないですか!これは期待が持てますね😊
2. 最初の壁:JPEG出力問題
「よし、じゃあJPEGで撮影してみよう!」と思って試してみると...
cam --camera=1 --capture=1 --file=test.jpg
ERROR: Unknown extension ".jpg"
あれ?JPEGが直接出力できない?!😱
ここで初めて知ったのですが、libcameraのcamコマンドはPPM形式でしか出力できないんですね。これが最初の大きな壁でした。
3. PPM→JPEG変換の道
「PPMって何?」という状態から調べ始めました。PPM(Portable Pixmap Format)は無圧縮の画像形式で、libcameraが標準で出力する形式だということがわかりました。
じゃあPPMからJPEGに変換すればいいじゃない!ということで、PIL(Pillow)を使った変換に挑戦。
from PIL import Image
# PPMをJPEGに変換
img = Image.open('capture.ppm')
img.save('output.jpg', 'JPEG', quality=85)
4. uvを使った環境構築
今回は最新のuv(Python package manager)を使って環境を構築しました。
# uv環境作成
uv venv
# 依存関係インストール
uv sync
pyproject.tomlで管理していたので、36パッケージが一発でインストール!uvの速さに感動しました⚡
5. 実装コードと動作確認
最終的に完成したコードがこちら:
import subprocess
import os
from PIL import Image
def capture_libcamera_jpeg():
'''libcameraでPPM取得→JPEG変換'''
try:
# libcameraでPPM形式で撮影
cmd = ['cam', '--camera=1', '--capture=1', '--file=capture.ppm',
'--stream', 'pixelformat=BGR888']
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode == 0 and os.path.exists('capture.ppm'):
# PPMをJPEGに変換
img = Image.open('capture.ppm')
img.save('output.jpg', 'JPEG', quality=85)
# ファイルサイズ確認
ppm_size = os.path.getsize('capture.ppm')
jpg_size = os.path.getsize('output.jpg')
print(f'成功!PPM: {ppm_size:,} bytes → JPEG: {jpg_size:,} bytes')
print(f'圧縮率: {ppm_size/jpg_size:.1f}倍')
# クリーンアップ
os.remove('capture.ppm')
return True
else:
print(f'失敗: {result.stderr}')
return False
except Exception as e:
print(f'エラー: {e}')
return False
# 実行
capture_libcamera_jpeg()
6. 驚愕の結果!
実際に実行してみると...
libcamera capture success!
PPM size: 1,440,015 bytes
JPEG size: 36,183 bytes
Compression ratio: 39.8x
39.8倍の圧縮効率!!😱
800x600の高品質な画像が36KBまで圧縮されました。これは素晴らしい結果です!
📊 OpenCVとの比較
既存のOpenCV実装と比較してみました:
項目 | OpenCV方式 | libcamera方式 |
---|---|---|
解像度 | 480p | 800x600 |
フレームレート | 30 FPS | 28.8 FPS |
画質 | 標準 | 高品質 |
実装複雑度 | シンプル | やや複雑 |
JPEG出力 | 直接可能 | 変換必要 |
ディレクトリ構成
最終的にすっきりとした構造になりました:
myhome-raspi-camServer/
├── .venv/ # uv仮想環境
├── backend/ # FastAPIサーバー
├── frontend/ # React UI
├── camera_servo_controller.py
├── pyproject.toml # uv依存関係管理
└── uv.lock # uv lockファイル
💡 おすすめの使い分け
最終的には、用途に応じた使い分けがベストだと感じました:
リアルタイムストリーミング
→ OpenCV方式 (安定性・シンプルさ重視)
高品質撮影
→ libcamera + PIL変換 (画質・圧縮効率重視)
ハイブリッド構成(推奨)
→ 両方を状況に応じて切り替え
🎉 まとめ
Ubuntu 24.10 + Raspberry Pi 4でMIPIカメラを使うのは「思っていたより簡単」でした!
最初は「PPMって何?」「JPEGにできないの?」と戸惑いましたが、PIL変換という解決策で39.8倍という驚異的な圧縮効率を実現できました。
uvを使った環境構築も快適で、モダンなPython開発環境を手軽に作れるのが良いですね!
皆さんもぜひ試してみてください😊 何か質問があればコメントで教えてくださいね!
📚 参考情報
- libcamera公式ドキュメント
- Raspberry Pi カメラ仕様
- uv公式ドキュメント
- PIL/Pillow画像処理ライブラリ