みなさんこんにちわ、こんばんわ。
SAIです。
今日はJupiterNoteBookでカメラを動かしてみます。
シングルボードコンピュータでデバイスを使うのは難しそうですが、
JupiterNoteBookを使うと、各コードの意味を理解しながら動かすことができますよ!
それでは、
今日のソースも、Nvidiaの「Getting Started with AI on Jetson Nano」です。
今日はCSIカメラを使います。
(ちなみにUSBカメラでもOKですが、コマンドが違います)
CSIカメラを繋いだ状態で、JupiterNoteBookを起動し、
Hello_Cameraを動かしてみましょう!
1.Hello_cameraを開く
JupiterNotebookを起動したら以下のようなフォルダ構成が見えると思います。
Hello_cameraというフォルダがありますね。
これを開きます。
↓こんな画面が見れると思います。
右半分がノートブックですね!
JupiterNotebookでは、ノートに記載しているコマンドをステップ実行できるようです。
2.Hello_cameraを実行する
初めて実行するときは、とりあえず実行ボタンをポチポチしてみるのがいいと思います。
そのうえで、改めてコマンドの意味を考えてみましょう。
実行は、↓この赤枠の▶をポチポチするか、
キーボードショートカット: [SHIFT][ENTER] で実行できます。
実行すると、結果が下に表示されます
この↓の絵の、 res のところが結果ですね。
こんな感じでポチポチしていくと、[6]のところでカメラで撮影した画像が実行できますよ!
3.JupiterNotebookの小技
ここでJupiterNotebookの小技です。
実行結果がノートの途中に表示されます。
しかし、続けて実行していくと表示結果が上の方に行って見えなくなりますよね。
そんなときの小技
右クリックで「Create New Ciew Output」でサブウィンドウ化!
クリックすると、
下、もしくは横に別画面が表示されます。
こうすれば、Notebookが進んでも画面の表示が見続けられます!
さて、カメラ画像が表示できたでしょうか?
4.JupiterNotebookのカメラ起動の詳細
コマンドを見てみましょう。
(JupiterNotebookの説明をするだけですが。)
各コマンドはPythonで書かれているようです。
◆まずは1コマンド目
!ls -ltrh /dev/video*
Jetson Nano 上のすべてのビデオ デバイスを一覧表示します。
SAIのJetsonはこんな応答になりました。
crw-rw---- 1 root video 81, 0 Aug 14 12:25 /dev/video0
video0 が割り当てられていますね。
◆次は2コマンド目
from jetcam.csi_camera import CSICamera
camera = CSICamera(width=224, height=224, capture_device=0)
# confirm the capture_device number
1行目で CSICamera クラスをインポートし、
2行目でカメラ オブジェクトを作成しています。
CSICamera()の引数を見ると、
高さ224、横幅224でカメラオブジェクトを生成していますね。
CSICamera インスタンスは 1 つだけ作成できています。
◆次は3コマンド目
image = camera.read()
print(image.shape)
2コマンド目で作ったcamera インスタンスから、Read()により画面をキャプチャしてます。
Shapeをプリントしています。
結果は以下の通り、イメージサイズが表示されていますね。
◆次は4コマンド目
print(camera.value.shape)
これも似たような出力ですね。
カメラの値を直接見ても、Shapeは同じですね。
◆次は5コマンド目
import ipywidgets
from IPython.display import display
from jetcam.utils import bgr8_to_jpeg
image_widget = ipywidgets.Image(format='jpeg')
image_widget.value = bgr8_to_jpeg(image)
display(image_widget)
1行目でウィジェット関連をインポート
2行目でDisplayをインポート
3行目はrgbからJpegに変換する処理のインポート
4行目は、Jpegイメージを生成
5行目は、3コマンド目で作ったimageからJpegへ変換する処理ですね。
6行目で、Wiget画像を画面に表示します。
はい、うちの猫が映りました。
不貞寝していますね。
このようにして画像を撮影する形になるようですよ!
この段階では、写真は1枚取れただけですね。
次は、カメラで撮影した画像を連続的に表示するパターンです。
◆次は6コマンド目
camera.running = True
def update_image(change):
image = change['new']
image_widget.value = bgr8_to_jpeg(image)
camera.observe(update_image, names='value')
連続的に表示する処理だというのは判るのですが、
実はこのコードにはSAIは自信が無いです。
1行目は・・・すみません詳しくは判りません。
カメラを常時動作にする設定だと思います。
おそらく、camera.observerを連続して更新できるようにする処理かな?
2行目から4行目は、update_image()という関数を作っています。
中では、新しいimageを取得してimage_Widgetのデータを更新しています。
5行目では、camera.observerでupdate_imageを呼び出して更新し続ける形になってるようです。
というわけで、このコマンドを呼ぶと連続的にWidgetイメージが更新され続けます。
カメラを動かすと、先程表示していたwidget画像が追従しますね。
◆次は7コマンド目
camera.unobserve(update_image, names='value')
連続実行の処理を停止する処理です。
observerをリリースしているイメージですね。
◆8コマンド目は、別の画像表示する方法とのことです。
traitlets メソッドを使用すると、カメラをwidgetに接続する方法だそうです。
import traitlets
camera_link = traitlets.dlink((camera, 'value'), (image_widget, 'value'), transform=bgr8_to_jpeg)
1行目は traitlets をインポート
2行目は、traitlets を使ってリンクしている処理だそうです。
解除するには
camera_link.unlink()
もう一回接続するには
camera_link.link()
とのことです。
今後自分の好きな処理を作るときには、
上記のようなコードを書けばいいのですね!
◆さいごに
処理が終わった後は、リソースの解放を忘れてはいけませんね。
最後に必ず以下の処理を行いましょう。
次、新しい処理をしたくても、リソース接続中としてリークが発生しちゃいますよ!
camera.running = False
camera.cap.release()
というわけで、今回はHello_Cameraの解説でした。
ちなみに、USBカメラもソースはほぼ同じですね。
cameraの作り方が、CSIカメラだったのがUSBカメラになる感じですね。
それでは今日はこの辺で。
◆目次へ戻る◆