概要

工場の作業場には、安全確認や記録のために固定カメラが設置されていることが多くあります。しかし、録画を人が見返すのは手間がかかり、「いつ、どこで、何人が作業していたか」を日報や台帳にまとめる作業は後回しになりがちです。

VLM(Vision Language Model:画像言語モデル)を使えば、画像や動画から人数や作業状況を読み取り、文章と表にまとめることができます。ただし、VLMに「この画像の作業状況を教えて」と1回聞くだけでは、判定がぶれたり、根拠を説明できなかったりします。

DigitalBaseのパイプラインで固定カメラの画像・動画を扱った際の構成をもとに、次の流れを設計の観点から整理します。

[ フォルダに画像・動画が届く ] ↓ [ 前処理:フレーム切り出し・番号の描き込み ] ↓ [ VLM診断:人の位置・区画ごとの状態 ] ↓ [ 判定列:座標とルールで「作業中」などを決める ] ↓ [ 条件分岐:要対応なら別ルートで通知 ] ↓ [ レポート:データセット・Excel台帳・通知 ]

起点:フォルダへの着荷でパイプラインを起動する

カメラやレコーダーからの画像・動画は、共有フォルダに置かれる形が最も扱いやすい入口です。パイプラインは「フォルダの直下にファイルが置かれた」というイベントで起動します。

無人で回す場合、起点の設計では次の点が重要です。

  • 書き込み途中のファイルを読まない:ファイルサイズが落ち着く(settle)のを待ってからイベントを出す
  • 停止中に届いた分も拾う:再起動時に、前回の生存時刻以降に更新されたファイルを走査し直す
  • 同じ着荷を二度処理しない:パス・サイズ・更新日時などから着荷ごとのIDを作り、冪等キーにする

定期実行(例:10分ごと)で「増えた分だけ処理する」構成もとれます。後述する前処理側で処理済みかどうかを判定し、新しいファイルが無い回は描き込みの確認だけで終わらせ、VLMを呼びません。


前処理:動画はフレームに、画像には番号を

動画の扱い

VLMへの動画の渡し方は2通りあります。推論サーバーが動画入力を受け付ける場合は動画のまま(必要なら解像度とfpsを落として再エンコード)、受け付けない場合はフレーム画像の列に変換して渡します。DigitalBaseでは、モデルが動画を受け付けるかを小さな試験用クリップで一度確かめ、受け付けなければフレーム方式に切り替えます。

フレーム方式の既定は、1秒1枚を目安に等間隔で切り出し、最小枚数と最大枚数の範囲に収める方式です。20秒のクリップなら20枚、長い動画は上限の枚数まで間引きます。各フレームには「何分何秒の画面か」を添えて渡すので、VLMは「01:20 に台車が搬入された」のように時刻つきで報告できます。画面録画やスライドのように場面が切り替わる映像では、場面の変わり目を優先して選ぶ方式も選べます。

def plan_frames(duration_sec: float, fps: float = 1.0, min_frames: int = 4, max_frames: int = 32) -> list[float]: """等間隔に切り出す時刻(秒)を返す。各区間の中央を取る。""" if duration_sec <= 0: return [] n = round(duration_sec * fps) n = min(max(n, min_frames), max_frames) return [(i + 0.5) * duration_sec / n for i in range(n)] plan_frames(20) # → 0.5, 1.5, ..., 19.5 の20枚

一方、作業場の状況を定点観測する用途では、動画の細かな動きよりも「一定間隔のスナップショット」が欲しい場面が多くあります。その場合は前処理で一定間隔(例:60秒おき)にフレームを切り出し、静止画として後段に流します。撮影日時はファイル名から読み、動画のフレームは開始時刻+経過秒で表します。

区画に番号を描き込む

床に白線で区画を引いた作業場を、魚眼の固定カメラで撮るケースでは、画像に区画の枠と番号を描き込んでからVLMに渡すことが効果的でした。番号なしで「左から3番目、奥から2列目の区画」と指示しても、歪んだ格子ではVLMが区画を取り違えます。検証では、番号を描かずに20区画を判定させると、ほぼ当てずっぽうの結果になりました。

区画の位置は白線の交点座標として持ちます。カメラが固定である前提なので、向きが変わったら座標を測り直す必要があります。


VLM診断:人の位置と区画の状態を分けて聞く

1回の問い合わせで人数・物の配置・作業状況をすべて答えさせるのではなく、問いを分けて構造化出力で受け取ります。

1. 人の位置を検出する

「写っている人を全員、全身を囲む矩形(0〜1000の相対座標)と姿勢で答える」と指示します。機械の陰で上半身だけ見える人や、遠くに小さく写った人を落とさないよう、画像を9区画に分けて順に確かめるよう手順も書きます。人数は、この検出結果の件数とします。

2. 区画ごとの状態を判定する

各区画について「物あり/空き/判定不可」と、置かれた物の呼び名を答えさせます。プロンプトでは次の点を明示しました。

  • 物に数えないもの(天井から吊られたケーブルや操作盤とその影、床の汚れ、人)
  • 空きと判定する条件(床面と白線がはっきり見える場合だけ。自信がなければ判定不可)
  • 現場で使う物の呼び名と見た目の特徴
  • 各区画に根拠を一言添えること

根拠を書かせると判定が安定したため、出力には根拠を含めさせ、レポートの列からは外しています。温度は0、思考モードはオフにしています。


判定列:「作業中」はVLMではなく座標で決める

「その区画で作業しているか」をVLMに直接聞くと、判定の理由を後から説明できません。そこで、VLMには観察できる事実(人の位置・物の有無)だけを答えさせ、判定はルールで決める構成にしています。

  • 足元の位置:人の矩形の下辺中央付近を足元とする
  • 作業中:物がある区画に、足元が接している
  • 接している範囲:区画の大きさに対する割合で決める(足元が区画の外なら広め、中なら狭め)
  • 仮置き:物はあるが、人が接していない
def classify_cell(has_object: bool, cell_polygon, feet, near_ratio: float) -> str: """区画の状態を、VLMの観察結果と座標から決める。""" if not has_object: return "空き" size = polygon_area(cell_polygon) ** 0.5 for foot in feet: if distance_to_polygon(foot, cell_polygon) <= near_ratio * size: return "作業中" return "仮置き"

この結果を列として持つと、「作業中の区画」「判定不可の区画」「人の位置(区画19・立つ、白線の外・しゃがむ など)」が表で追えます。最後に、この判定結果だけを根拠にして、LLMに2〜3文の作業状況を書かせます。「結果に無いことは推測で書かない」と指示し、文章が表と食い違わないようにします。

導入時に確かめておくこと

VLMの観察結果は、導入時に現場の画像を目視の正解と照合して確かめます。照合では、次のような点が課題として出やすくなります。

  • 機械や部材の陰にいる人、ヘルメットだけが見える人を数え落とすことがある
  • 似た台車やパレットの呼び名を取り違えることがある
  • 区画のすぐ奥の機械で作業している人に反応し、作業中を余分に付けることがある
  • 「接している」とみなす割合は、合わせた画像とは別の時間帯・日の画像でも確かめる必要がある

また、映像に焼き込まれた時計とファイル名の時刻がずれることもあるため、撮影日時の扱いも導入時に確認します。


条件付き通知:要対応のときだけ別ルートで知らせる

レポートは全件を台帳に残しつつ、条件を満たしたものだけ別ルートでも知らせる分岐を入れます。汎用の画像・動画レポートでは、VLMの構造化出力に判定用の列を持たせています。

列内容
urgent至急知らせるべきか(安全・品質・設備停止の兆候。迷ったら真)
status正常/要確認/異常 のいずれか1語
severity重要度1〜5
summary1行の要約
findings観察した事実(動画は「mm:ss」で始まる箇条書き)
action推奨する対応

後段は2つに分かれます。

[ VLM診断 → レポート整形 ] ├─→ [ Excel台帳に追記 ] → [ 通常の通知 ] └─→ [ 条件: urgent == true ] → [ 要対応の通知(別の宛先) ]

台帳への追記は通知より先に行い、台帳の書き込みに失敗しても通知は止めない設定にしています。要対応の通知はチャットツールの別チャンネルなど、宛先を分けて設定します。

条件分岐は型付きで評価します。両辺が数値なら数値、真偽値なら真偽値として比べ、片方だけが数値のような比較では「文字列として比べた」ことを理由に残します。実行結果には、各行が「どの条件で、どの値と比べて、通ったか落ちたか」が残るため、「なぜこの画像で通知が飛んだのか」を後から確認できます。

固定カメラの区画判定に通知を組み合わせる場合も、同じ考え方が使えます。たとえば「判定不可の区画が一定数を超えた」「通路にあたる区画が物ありになった」といった条件を判定列に対して書けば、VLMの文章ではなく表の値で分岐できます。どの条件を要対応とするかは現場ごとに決める必要があり、最初は台帳だけを残して、条件の妥当性を確かめてから通知を有効にするのが安全です。


運用上の注意

  • 処理済みの管理:保存が終わってから画像を「解析済み」フォルダへ移す。途中で失敗した分は次の回に再解析される。保存直後に止まった場合は同じ画像の行が重複しうるため、追記型の台帳では重複の確認手段を用意する
  • 処理時間と実行間隔:1回の処理時間より定期実行の間隔を長くする。溜まった動画を初回にまとめて流すと前処理の制限時間を超えることがあるため、数本ずつ投入する
  • 任意コードの実行権限:ファイル操作や画像処理のためにサンドボックスを外したPythonステップを使う場合、パイプラインを編集できる人はサーバー上で任意の処理を書けることになる。編集権限を持つ人を限定する
  • モデルの差:精度は使うVLMで変わる。モデルを替えたときは、同じ画像で照合し直す

まとめ

固定カメラの画像・動画を作業状況レポートにする際の要点は、次のとおりです。

  1. 起点はフォルダへの着荷:書き込み完了を待ち、停止中の分も拾い、冪等キーで二重処理を防ぐ
  2. 前処理でVLMを助ける:動画は時刻つきのフレームにし、区画には番号を描き込んでから渡す
  3. 問いを分けて事実だけを聞く:人の位置と区画の状態を別々に構造化出力で受け、根拠を添えさせる
  4. 判定はルールで決める:「作業中」などの判定列は座標とルールで作り、説明できる形にする
  5. 通知は条件で分岐する:全件を台帳に残し、要対応だけを別ルートで知らせる。分岐の理由は実行結果で追える

VLMは観察役、判定と通知の分岐は決定的な処理が担う、という役割分担にすることで、結果を現場で検証しながら改善していける構成になります。


関連記事