📷️

Spresernse SDK でカメラを撮る

に公開

Spresense でカメラ

はい、というわけで、前回 に引き続きカメラやっていきます(# ゚Д゚)

Spresense のカメラもなかなかに糞以下……失礼、言葉が過ぎました、💩です。

はい、サンプルコード に関する記述はここ。

exampls/camera にあるんだって。はい、じゃ、GitHub をドーゾ。

ない。 馬鹿にしてんのかコラ?お?

で、サンプルコードはなんだかよくわからない イーサネット経由Multi Webcamera とかいうサンプルしか無いようです。お?しかもこれ、去年動かんかったぞ。

というかさ、Sony お前さ、いや、Sony に限らず Xilinx とかさぁ(飛び火)、 Nvidia とかさぁ(恨み)、お前らサンプルコードにごちゃごちゃ機能まぜんな、ボケ。お前らのはサンプルじゃなくてただ オナニー デモなんだよ。

サンプルコードとデモコードは分離しろよ。サンプルコードってのは見て読んで、簡単にわかるもんだろうが。読むのがめんどくせぇんだよ、てめぇらの サンプル デモコード!だいたいドキュメントも間違ってること多いしよぉ!

それと Sony のサンプルコードは C89 スタイル?アホか?馬鹿なのか?マジで言ってんのか?本気で C89 が素晴らしいと思ってんなら、もう K&R スタイルで関数書けや

あー、スッキリした。

思いっきり毒吐いたけど消さないよ。

擁護もしておくと、 サンプル デモコードは💩だけど、 Cameraの説明 は関してはしっかり書かれていたので、なんとかなりました。

作ったもの

https://github.com/nodamushi/zenn-program/tree/main/src/spresense/camera

Spresense SDK を用いたごくシンプルなカメラ撮影のサンプルコード (C++) です。

  1. カメラを撮影 (JPEG, HD サイズ)
  2. Base64 で出力

という機能しかありません。ただ、デバッグ用のシリアルポートから出すとあまりに Base64 出力が遅いんで、拡張ボードの USB からも出せるようにしています。

サンプルコードっていうのはこういうレベルを指すんだと思うんだけどな。

必要なもの

以下が必要です

  • Spresense 本体
  • Spresense カメラ

オプション

  • Spresense 拡張ボード

カメラの初期化から撮影まで

Spresense では V4L2 ライクな操作でカメラを操作することが出来ます。

カメラを扱うには spr-configdevice/camera を指定してやればOKです。

spr-config default feature/libcxx device/camera feature/usbcdcacm

今回は C++ で書いてるので feature/libcxx と拡張ボードの USB から CDC-ACM で出力するために feature/usbcdcacm も追加で指定しています。

操作の流れは、Cameraの説明 の「図 50. V4S Sequence Overview」を見るのがわかりやすいです。

  1. カメラデバイスを open
  2. 撮影フォーマットを設定
  3. FPS を設定
  4. バッファの作成と割当
  5. キャプチャの開始
  6. デキューして画像読み出し(終わったらエンキュー)
  7. キャプチャの終了
  8. バッファの破棄
  9. カメラデバイスの破棄

これらの処理は camera.hpp に全部閉じ込めてあります。

これを実際に使っているコードはこちら。今回は HD 画像(1280x720)の静止画(StillImage) で、一応バッファを2つ(意味ない)用意しています。ホワイトバランスは蛍光灯(V4L2_WHITE_BALANCE_FLUORESCENT) を選択。(multi webcam 参考)

https://github.com/nodamushi/zenn-program/blob/main/src/spresense/camera/src/cam/cam_main.cxx#L41-L63

ifprintf でごちゃっとしてますが、全部除けばこれだけです。停止や破棄はRAIIで処理するので不要です。

// HD 画質, 静止画 (StillImage), バッファサイズ 2
cam::Camera camera(cam::HD, cam::StillImage, 2);
// 蛍光灯のホワイトバランス
camera.setWhiteBalance(V4L2_WHITE_BALANCE_FLUORESCENT);
camera.startCapture();
const cam::VideoBuffer* ret = camera.dequeue();

今回は静止画なので dequeue しっぱなしですが、動画の場合は処理が終わったら、バッファを再び使えるように enqueue して戻してやる必要があります。

camera.enqueue(ret);

これぐらいなら誰でも知らなくてもカメラ操作について読めるよね。サンプルコードってこういうものを言うと思うんだよなぁ。

クラスの中の実装も、処理の流れがわかってれば、もう読めると思います。

実行方法

ビルド→書き込みは以下のコマンドで出来ます。(USBなどを WSL に持っていく準備などは 前回の記事 参照)

./start.sh --deploy

プログラムを書き込んだら、screen などで接続し、 nsh で cam とすれば撮影した画像が Base64 で出力されます。

ただし、くっそ遅いです。なんせ HD 画像を Base64 でボーレート 115200 で出力しようとするんですからね。動かないことはないけど。

そこで、外部の拡張ボードにある USB からボーレート 30Mbps で出力できます。

まずは接続したら sercon というコマンドを実行します。よくわからんけど、ドライバが起動するっぽい。これで USB で通信できます。

nsh> sercon

これを実行すると、ホスト側から新たにシリアルポートが見えます。 Windows の場合は Teraterm などで開くとよいでしょう。ボーレートは 30000000 です。

Teraterm などで新たに追加されたシリアルポートを開いたら、 元のシリアリポート の画面で com usb を打ち、プログラムを実行します。

nsh> com usb
start cam program
Use External USB Serial port.
-- Baudrate: 30000000
-- init OK
Camera init OK
Output Base64:

Success! Output Base64

Done !
nsh>

で、Base64 を画像に変換すれば撮影した内容を確認できます。 Base64→画像デコード というサイトを利用しました。

おっけー

まとめ

写真取るだけのすっごいシンプルなプログラム作りました。イーサネットも何もいりません。

以上です。

Discussion