情報工学部学生による備忘録

1学生の備忘録です。開発したときのことを思い出せるように。

Unity+OpenCvSharp3でWebカメラの映像を表示する

ssssota.hatenablog.com

続きです。

お疲れ様です。 前回は画像を適当に保存するところまでしかやってないので、それではゲームに使えないだろうと表示を実装していきます。

結論から

まず、VideoCaptureクラスから取得できる画像データはMatクラスのインスタンスとして変数に保存されます。
MatのメソッドとしてImEncodeというものありますが、これを用いpng画像のバイトデータを生成します。
これを、UnityのLoadImage関数に渡すことでTextureに読み込むことができます。

さて、仕組みは以上です。
Mat -> png -> Texture2Dという風に変換するわけですね。

実装

usingディレクティブ

using UnityEngine;
// uGUIのRawImageに読み込む場合
//using UnityEngine.UI;
using OpenCvSharp;

フィールド宣言

[SerializeField] private int m_WebCamIndex = 0;
private Texture2D m_Texture;
private VideoCapture m_Video;
private Mat m_Frame;

Startメソッド

private void Start()
{
    // m_WebCamIndexによって指定されたウェブカメラを初期化
    m_Video = new VideoCapture(m_WebCamIndex);

    // Texture2Dをウェブカメラのサイズ、フォーマットで初期化
    m_Texture = new Texture2D(
        m_Video.FrameWidth, // ウェブカメラのwidth
        m_Video.FrameHeight, // ウェブカメラのheight
        TextureFormat.RGB24, // フォーマットを指定
        false // ミップマップ設定(よくわかっていない)
    );

    // テクスチャを適用したいオブジェクトにスクリプトを登録する
    // 以下どちらか
    // 1. スクリプトをuGUIのRawImageに登録している場合
    GetComponent<RawImage>().texture = m_Texture;
    // 2. スクリプトをオブジェクトに登録している場合
    GetComponent<Renderer>().material.mainTexture = m_Texture;
}

Updateメソッド

private void Update
{
    // ウェブカメラから画像読み込み
    m_Video.Read(m_Frame);
    // MatオブジェクトをPNGデータに変換、読み込み
    m_Texture.LoadImage(m_Frame.ImEncode());
}

OnDestroyメソッド

private void OnDestroy()
{
    // カメラを閉じる処理を書かないと起動し続ける
    // .NETのバージョンをイジってないと動かないかもしれません
    m_Video?.Dispose();
    m_Video = null;
}

以上です。
Unityに慣れている人には特に難しくないと思います。
問題としては、そこそこ処理が重い点でしょうか。 私はコルーチンで15fpsで動作させてゲームに導入しています。
マルチスレッドの方が相応しいのでしょうが、Unityの一部機能が別スレッドでは使えない関係もあり導入は容易ではないと思います。
私はよくわからず妥協しました。

余談

今回の記事は、このブログの総アクセス数がキリ番を達成したので書きました。
閲覧頂きありがとうございます。アクセス数は励みです。
コメントもぜひ残していってください。