開発プラクティス

【体験記】生産ラインで人の動きを検知できそうと思ってSAM2を触ってみた

記事内に商品プロモーションを含む場合があります

なんとなく触ってみた

生産ラインで人の動きを検知できそうだな、と思って Meta の SAM 2(Segment Anything Model 2)を少し触ってみました。

なんか凄そうなアルゴリズムだなって思ってやってみたって感じです。

SAM 2 はいわゆる物体検出モデルと違って、「人」「車」みたいなクラスで画像を見ないようです。代わりに画像上の 1点クリック を受け取って、「ここに欲しい物体があるよ」と伝えると、その物体だけマスクで切り抜いてくれます。

しかも SAM 2 には動画モードがあって、最初の1フレームで1クリックすれば、以降のフレームを勝手に追跡してくれるらしいです。生産ラインの映像で特定の作業者を追えるなら便利そうだな、というのが触ってみた動機でした。

やってみた:1クリックで12秒追跡

素材は Pixabay で拾ってきた駅の人ごみ動画(12秒)です。大勢の通行人の中で、特定の1人を追ってみたいと思いました。

Gradio で簡単な UI を組んで、動画の1フレーム目をブラウザに表示 → 追跡したい人を1クリック → 結果を動画で返す、という流れにしました。

結果がこちらです。画面下のオレンジのベストを着た女性をマスクで切り抜きしてます。

しゅごい〜。
めっちゃ綺麗に検出できますやん。

こんなに綺麗なら、色々なところで活用できそうですね。

どんなふうに追跡動画を作ったか

コードは大きく ①UI(Gradio)②SAM 2 の追跡③マスクを動画に描画 の3つに分かれています。順番に紹介します。

① UI 部分:Gradio で frame 0 を表示してクリックを受ける

UI は Gradio で組みました。frame 0 の画像をブラウザに表示して、追跡したい人をクリックしたらその座標を次の処理に渡し、結果動画を返すだけのシンプルな構成です。

下のベストの女性をクリックすると、以下のように処理が進む感じにしました。
(検出は1つのみにしました)

UI の骨格はこれだけです。肝は inp.select(fn=run_tracking, ...) の部分で、画像をクリックした瞬間に SAM 2 の追跡処理(run_tracking)へ座標が流れていきます。

import gradio as gr
with gr.Blocks(title="SAM 2 Video Tracking") as demo:
    gr.Markdown("# SAM 2 1クリック動画追跡")
    n_frames = gr.Slider(
        minimum=30, maximum=360, step=30, value=60,
        label="追跡フレーム数",
    )
    inp = gr.Image(type="numpy", label="frame 0 — クリックしてください",
                   value=load_frame0())  # frame 0 を表示
    out_video = gr.Video(label="追跡結果", autoplay=True)
    status = gr.Textbox(label="ステータス", interactive=False)
    # クリック → run_tracking に座標を渡す
    inp.select(fn=run_tracking, inputs=[inp, n_frames],
               outputs=[out_video, status])
demo.launch(server_name="0.0.0.0", server_port=7860)

クリック座標は gr.SelectData という型で関数に渡ってきます。公式ドキュメントにも下記のように書かれています。

gr.SelectData ― “The gr.SelectData class is a subclass of gr.EventData that specifically carries information about the .select() event. When gr.SelectData is added as a type hint to an argument of an event listener method, a gr.SelectData object will automatically be passed as the value of that argument.”

Gradio公式 – SelectData


具体的には evt.index にクリックした画像座標 (x, y) が入るので、今回はこれをそのまま SAM 2 の追跡処理に流しています。

② 追跡部分:クリック座標を SAM 2 に渡して全フレームに伝播

SAM 2 の本体が以下のコード。gr.SelectData 経由で受け取ったクリック座標 (x, y) を frame 0 に「この点を追って」と伝え、あとは propagate_in_video が残りのフレームのマスクを順に返してくれます。

from sam2.build_sam import build_sam2_video_predictor
import numpy as np
def run_tracking(image_rgb, evt: gr.SelectData, n_frames):
    x, y = evt.index  # クリックした画像座標
    predictor = build_sam2_video_predictor(CONFIG, CHECKPOINT, device="cpu")
    state = predictor.init_state(video_path=str(FRAMES_DIR))
    # frame 0 で「このクリック座標を追って」と指定
    predictor.add_new_points_or_box(
        inference_state=state, frame_idx=0, obj_id=1,
        points=np.array([[x, y]], dtype=np.float32),
        labels=np.array(, dtype=np.int32),
    )
    # 以降のフレームに自動伝播
    seg = {}
    for out_idx, _, mask_logits in predictor.propagate_in_video(state):
        seg[out_idx] = (mask_logits[0] > 0.0).cpu().numpy().squeeze()

obj_id=1でマスク対象は1つにしてます。

この「プロンプトを1つ与えて、残りのフレームに伝播させる」という考え方は、SAM 2 の公式 README にも下記のように書かれています。

Video prediction ― “For promptable segmentation and tracking in videos, we provide a video predictor with APIs for example to add prompts and propagate masklets throughout a video. SAM 2 supports video inference on multiple objects and uses an inference state to keep track of the interactions in each video.”

SAM 2公式 – facebookresearch/sam2 README


トラッキングの状態保持も、フレーム間の対応付けも自分では1行も書いていません。「クリック座標を渡す」「伝播ループを回す」だけで終わってしまいました。

③ 描画部分:マスクを動画に重ねて MP4 に書き出す

SAM 2 から返ってきたマスクを、各フレームに 緑色の半透明 で重ねて、その輪郭を 黄色 でなぞっています。記事冒頭で見せた動画の「人が緑に光って見える」見た目はここで作っています。

import cv2
import numpy as np
def overlay_mask(frame_bgr, mask):
    # 緑のベタ塗りを半透明で重ねる
    overlay = np.zeros_like(frame_bgr)
    overlay[mask > 0] = (0, 255, 0)
    vis = cv2.addWeighted(frame_bgr, 1.0, overlay, 0.5, 0)
    # 輪郭を黄色で描く
    m8 = (mask > 0).astype(np.uint8) * 255
    cnts, _ = cv2.findContours(m8, cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(vis, cnts, -1, (0, 255, 255), 2)
    return vis

あとはフレームを cv2.VideoWriter で MP4 に書き出して Gradio の gr.Video に返すだけです。

詰まったこと:CPUだと15分かかる

手元の Mac で CPU のまま回したら、12秒の動画を処理するのに 約15分かかりました。GPU ならもっと速いはずなので、現場で使うなら GPU マシンが要るなと思いました。

まとめ

生産ラインに応用できるとすれば、たとえば:

  • 危険エリアを最初の画像に1クリックで囲んでおく(保存すればずっと使い回せる)
  • 特定の作業者の動線を追う
  • 動いている装置の可動範囲を追う

あたりは割と現実的かもしれません。クラス分類ベースの検出だと「人」か「車」しか見られなかったのが、SAM 2 だと 「あの人だけ」「あの装置だけ」を指差しで指定できるのが面白いところだと思います。

まだ本格的に使い込んだわけではありませんが、画像処理を長くやってきた感覚からすると、ちょっと時代が変わった感じがしました。

動画の出典: Pixabay – Waterloo Station London People Busy

ここまで読んでいただきありがとうございました。それでは、また。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA