0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

UbuntuのUnityでカメラ入力を扱う方法

Posted at

目標

UbuntuのUnity(デスクトップ環境じゃなくてゲームエンジンのほう)で, Webカメラからの入力をカメラに表示する.

環境

Ubuntu 20.04 LTS
Unity 2020.3.16f1

カメラ入力のフォーマットの変換

私が使用しているWebカメラのフォーマット, mjpegにUnityが対応していないようで, そのままではUnityで映像入力として扱うことができませんでした. そこで, ffmpegを使ってv4l2loopbackによる仮想カメラを経由してUnityに映像を渡すことにしました.
私はどちらも導入済みでしたが, まだの方は,

あたりで導入してください.
これで必要なものが揃いました.

では, まずは仮想デバイスを作ります.
sudo modprobe v4l2loopback devices=1 exclusive_caps=0で仮想デバイスを作成し, v4l2-ctl --list-devicesで現在のデバイスの一覧を確認します. すると, 接続されているWebカメラの他に以下のようなデバイスが作成されていることが確認できると思います.

Dummy video device (0x0000) (platform:v4l2loopback-000):
	/dev/video4
GENERAL - UVC : GENERAL - UVC  (usb-0000:00:14.0-3):
	/dev/video0
	/dev/video1

環境によって/dev/video*の数字などが違うかと思いますが, 私の場合は上の/dev/video4が作成した仮想デバイス, /dev/video0がUSB接続のWebカメラを表しています(なぜWebカメラのデバイスが2つあるのかは謎ですが).

次に, Webカメラの映像を仮想デバイスに流します.

$ ffmpeg -f v4l2 -i /dev/video0 -vf format=yuyv422 -f v4l2 /dev/video4

このように, -iのあとにWebカメラ, 末尾に仮想デバイスを指定します. また, Unityが対応しているフォーマットを指定します.

Unityで映像を流す

シーンにCanvasを追加し, その子要素にRaw Imageを追加します. さらに, 以下のようなスクリプトを作成します.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WebCamera : MonoBehaviour
{
    public RawImage rawImage;

    WebCamTexture webCamTexture;
    WebCamDevice[] webCamDevice;
    int selectCamera = 0;

    void Start () {
        this.webCamDevice = WebCamTexture.devices;
        for (int i = 0; i < this.webCamDevice.Length; i++){
            print(i.ToString() + ": " + this.webCamDevice[i].name.ToString());
        }
        this.webCamTexture = new WebCamTexture(webCamDevice[selectCamera].name, 1280, 720, 30);
        this.rawImage.material.mainTexture = this.webCamTexture;
        this.webCamTexture.Play();

	}
}

スクリプトは, Raw Imageあたりにアタッチしましょう. そして, アタッチ先のInspectorからScriptのRaw Imageにシーン内のRaw Imageをアタッチします.

さていよいよ実行…ですが, おそらくエラーが出たり, canvasに何も表示されなかったり, 正しく動作しないと思います. 一度ログを見てみましょう. for文の中でのprintの出力は, 以下のようになると思います.

0: GENERAL - UVC : GENERAL - UVC  (/dev/video0)
UnityEngine.MonoBehaviour:print (object)
1: GENERAL - UVC : GENERAL - UVC  (/dev/video1)
UnityEngine.MonoBehaviour:print (object)
2: Dummy video device (0x0006) (/dev/video4)
UnityEngine.MonoBehaviour:print (object)

この中の, 2: Dummy video device2が, Unity上での識別番号のようです. そこで, 先程のスクリプトのint selectCamera = 0;int selectCamera = 2;に書き換えて実行してみましょう. これでcanvasに映像が出ると思います.
また, うまくやれば, この手動での書き換え操作を処理に組み込めそうですね.

感想

最初はOBSのv4l2-sinkで仮想カメラに接続していましたが, 煩わしさを感じたので重い腰を上げてffmpegのことを調べてみました. なかなか苦戦しましたが, シェルスクリプトにまとめておくことでスッキリさせることができて満足です.
ffmpegすげえ.

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?