Rust製の動画像可視化ツールRerunの紹介
この記事はRust Advent Calendar 2023 シリーズ2と画像処理・画像解析 Advent Calendar 2023の10日目の記事です。
rerunの紹介
rerunとは、rerun.ioという会社が開発している、動画像の可視化を強みとした
- 可視化UI
- 専用のロギングライブラリ
が一体となったOSSの可視化ツールになります。
こちらは、公式のexampleからの引用になりますが
のような画面を比較的簡単に作成することができます。
Rustで記述されている事による強みや特徴があり、恩恵に強くあやかれている言語だと思います。
rerunの特徴
rerunは開発中の可視化やデモとしての可視化に重きをおいているように見えます。(実運用中のデータを可視化する用途ではない)
rerunのツールとしての特徴は以下だと思っています。
- 可視化ツールとしての独立性が高い
- プログラムとの分離性が高い
- Rust製のツールなので可搬性が高い
各々について書いて行きたいと思います。
可視化ツールとしての独立性が高い
これは可視化UIの独立性になります。
可視化で有名なツールと言えば私の知るところだと、kibanaやgrafanaだと思っています。
kibanaを例にすると、kibanaではElasticSearchをストアとしてそれの可視化を行います。
図にすると以下のようになるかと思います。
実際はプログラム => ElasticSearch には fluentd的な何かが必要かもしれないですが一旦割愛しておきます。
つまり、可視化ツールとデータストアが分離しているということになります。
これに対してrerunは
のように、可視化UIとデータストアが一体になっている構成になります。
この特徴により、
- 気軽に利用を始めることが出来る
- 他人が利用する場合でも立ち上げ手順が簡単
というメリットがあります。
また、デメリットとしては
- 取り扱うことが出来る系列の長さが、可視化UIが実行しているディスクに律速してしまう
というものがありますが、
rerunは開発中の可視化やデモとしての可視化に重きをおいている
というところでの割り切りかと思っています。
プログラムとの分離性が高い
次にrerunはプログラムとの分離性が高いという解説をします。
これも比較対象を置くと、少し乱暴な対象だとは思いますが。
Opencv drawing & imshow可視化略してODIとしましょう
ODIの概略
Opencv drawing & imshow可視化というのは、
動画像の可視化に対して「Opencvのdraw*関数とimshow」で対応するという方針になります。
例として顔検出をして、検出した顔に対して赤い四角を書くというコードは以下のようになります。
import cv2
if __name__ == '__main__':
# 顔検出用のカスケード分類器を読み込む
face_cascade = cv2.CascadeClassifier('./data/haarcascade_frontalface_default.xml')
# 動画を読み込む
cap = cv2.VideoCapture('./data/face.mp4')
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# グレースケールに変換
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 顔検出
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
# 顔の周りに赤い矩形を描画
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
# 結果を表示
cv2.imshow('Face Detection', frame)
# 'q'を押すとループから抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# リソースを解放
cap.release()
cv2.destroyAllWindows()
ODIは上記の独立性を満たすため、動画像の処理を行う際のファーストチョイスに選ばれることが多いです。場合によってはデモとかだとそのまま、ODIで押し切る場合も多いです。
rerunの場合の可視化
import cv2
import rerun
from rerun.components import DrawOrder
if __name__ == '__main__':
# 顔検出用のカスケード分類器を読み込む
face_cascade = cv2.CascadeClassifier('./data/haarcascade_frontalface_default.xml')
# 動画を読み込む
cap = cv2.VideoCapture('./data/face.mp4')
rerun.init("face_detection", spawn=True)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
rerun.log("rgb", rerun.Image(frame[:, :, ::-1], draw_order=[]))
# グレースケールに変換
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
rerun.log("gray", rerun.Image(gray))
# 顔検出
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
# 顔の周りに赤い矩形を描画
for (x, y, w, h) in faces:
rerun.log("rgb/faces", rerun.Boxes2D(mins=[x, y], sizes=[w, h]))
rerun.log("gray/faces", rerun.Boxes2D(mins=[x, y], sizes=[w, h]))
# リソースを解放
cap.release()
cv2.destroyAllWindows()
コードはあんまり変わっていないですがコレを実行するとrerunの可視化UIが起動して以下のような感じになります。(環境によって違うかも)
rerunの可視化画面はあとから表示要素を変えることが出来るので
を押すことで。
グレイスケール画像の可視化を一旦消すことなどができます。
また、このようにタイムバーを動かすと可視化するフレームを変えることも出来ます。
ODI vs rerun
rerunの可視化はODIに比べると以下のような優位性があります。
時系列を遡りながら可視化結果を確認できる。
言わずもがな、
これが出来るということです。
コレをODIでやろうと思うと不可能ではないですが、かなり苦労するかと思います。
3D系の描画が豊富
今回のサンプルには入れていないですが、
SLAMの結果の可視化などにいかがでしょうか?
プログラムを実行しているコンピュータ以外でも可視化出来る
rerunのロガーと可視化UIの間はTCPベースの通信で行われているため、実行しているコンピュータ上にWindowシステムが無くても(imshowは何かしらのWindowシステムか魔改造が必要になる)可視化することができます。
これにより、
- スマートフォンアプリ
- VRデバイス
- テレビ
などの(全部スマホでごめんなさい)環境で動作させるときに、その環境にTCPのAPIさえあれば別のPCにログを送って可視化することなどができます。
他にも色々あるとは思いますが一旦コレくらいにしておきます。
今回のサンプルコードを実行できる環境は以下においておきます。
Rust製のツールなので可搬性が高い
Rust製のツールおなじみの可搬性が高いというのがあります。
可視化UIに関してもWasmでビルド出来たりと可搬性が高いですが、今回はロガーAPIの可搬性について説明します。
まず、rerunはcrateが細かく別れているためロガーのみを切り出して利用することが容易です。
> ls crates
re_analytics re_build_tools re_data_ui re_log_encoding re_sdk re_space_view_spatial re_string_interner re_types_builder re_viewport rerun_c
re_arrow_store re_build_web_viewer re_error re_log_types re_sdk_comms re_space_view_tensor re_time_panel re_types_core re_web_viewer_server
re_build_examples re_crash_handler re_format re_memory re_smart_channel re_space_view_text_document re_tracing re_ui re_ws_comms
re_build_examples_manifest re_data_source re_int_histogram re_query re_space_view re_space_view_text_log re_tuid re_viewer rerun
re_build_info re_data_store re_log re_renderer re_space_view_bar_chart re_space_view_time_series re_types re_viewer_context rerun-cli
ロガーの実装に当たる、re_logに関してはほぼrustのtoolchainのみでコンパイルできるためクロスビルドも容易です。
このロガーのクロスビルドの容易さが先程も上げた
- スマートフォンアプリ
- VRデバイス
- テレビ
などの環境で利用するときに、とても助けになります。
私の場合は、過去にiOS向けにビルドして利用したりをしていましたが、feature flagを少しいじる程度の調整でiOS向けにビルドすることが出来ました。
rerunのおすすめ出来ないポイント
基本的にはないのですが、敷いてあげると以下のような点になります。
安定していないものが嫌いな人
凄まじい速度で発展しているアプリケーションなので、UI・ロガーAPI共に安定していないです。
私はロガーAPIのメインの利用がRustからのため、変わってもコンパイル時にすぐに気付くことが出来ていたためそこまで大きいストレスはありませんでした。
ただ、Python APIを利用していたり、可視化UI側をガッツリ使ったりするとバージョンを上げるのに躊躇してしまうケースは出てくるかもしれません。
可視化UIは手動でしかさわれない
AとBの可視化結果を横に並べて~~
みたいな作業は現時点では、コード化出来ず、手動で行う必要があります。
また、可視化UIの状態はUIアプリケーションを落としても維持されますがなにかの拍子にその状態が消えてしまうとやり直しになってしまいます。
blueprintという機能で2024の1Qに対応予定らしいです。
まとめ
rerunは画像処理アプリケーション開発時の可視化において
- 手軽に利用開始可能
- タイムシーケンス対応
- 2D・3Dともに強力なドローイング機能
なツールになっているのでRustでもRustじゃなくても画像処理を行っている人は使ってみてください。
rerunに興味が出てきた人は、
また、ここでは可視化UIをブラウザ上で試すことが出来ます。
落ち穂拾い
rerunのUIの構成要素について
rerunはeguiというRust製のGUIライブラリの上に構成されています。eguiの記事
このeguiはimmediate modeという特徴を持っていて、よく利用されるUIライブラリがイベントベースナノに対してイベントが有ってもなくても60fps(画面の垂直同期でかわる)で再描画し続けるというものになっています。
これは個人的な推察ですが、eguiの作者はrerun.ioのCTOだったりするので、eguiのマネタイズ先としてrerunを開発しているっていうのもあるかもしれません。
Discussion