カメラで撮影している画像情報を取得したいなぁ。
いえ、Unity上のカメラじゃないですよ。
iOSやAndroidの端末にあるカメラで映している画像情報が欲しいのです。
望むことなら、エディター上でもWebカメラで映している画像情報を取りたいな。
でもネイティブコードを書くのは大変そうだし、どうしよう……。
そんなときは、WebCamTexture
。
ネイティブコードを書かなくても、パパっと簡単にカメラで映している画像情報が取得できるみたい!
さっそく使ってみましょう。
この記事にはUnity5.6.2f1を使用しています。
WebCamTextureを使おう
では以下のスクリプトにWebCamTexture
を使って、カメラが映している画像情報を取得する流れを記述してみますよ。
public class TestCamera : MonoBehaviour { private IEnumerator Start() { yield return null; } } // class TestCamera
WebCamTexture.devicesを使って、接続されているカメラを探すよ!
さて、まずはそもそもカメラがあるかを調べなくちゃいけませんよね。
WebCamTexture.devices
を使って存在するカメラを探してみましょう。
docs.unity3d.com
private IEnumerator Start() { if( WebCamTexture.devices.Length == 0 ) { Debug.LogFormat( "カメラのデバイスが無い様だ。撮影は諦めよう。" ); yield break; } }
とりあえず、無ければそれまでという形でいきます。
カメラの利用の許可が出ているか調べてみるよ!
カメラがあったとしても、カメラの使用許可が出ていないと使えませんよね。
Application.RequestUserAuthorization()
を使って許可のリクエストを出し、Application.HasUserAuthorization
で確認してみましょう。
docs.unity3d.com
ドキュメントを読む限り、リクエストの方はWebPlayer用だよ的なことが書かれているけど、今回は一応呼んでおきましょう。
private IEnumerator Start() { if( WebCamTexture.devices.Length == 0 ) { Debug.LogFormat( "カメラのデバイスが無い様だ。撮影は諦めよう。" ); yield break; } yield return Application.RequestUserAuthorization( UserAuthorization.WebCam ); if( !Application.HasUserAuthorization( UserAuthorization.WebCam ) ) { Debug.LogFormat( "カメラを使うことが許可されていないようだ。市役所に届けでてくれ!" ); yield break; } }
WebCamTextureを作ってみるよ!
さて、前準備は整えたので、テクスチャの解像度を指定してWebCamTexture
を作ってみます。
docs.unity3d.com
public class TestCamera : MonoBehaviour { [SerializeField] private int m_width = 1920; [SerializeField] private int m_height = 1080; private WebCamTexture m_webCamTexture = null; private IEnumerator Start() { if( WebCamTexture.devices.Length == 0 ) { Debug.LogFormat( "カメラのデバイスが無い様だ。撮影は諦めよう。" ); yield break; } yield return Application.RequestUserAuthorization( UserAuthorization.WebCam ); if( !Application.HasUserAuthorization( UserAuthorization.WebCam ) ) { Debug.LogFormat( "カメラを使うことが許可されていないようだ。市役所に届けでてくれ!" ); yield break; } // とりあえず最初に取得されたデバイスを使ってテクスチャを作りますよ。 WebCamDevice userCameraDevice = WebCamTexture.devices[ 0 ]; m_webCamTexture = new WebCamTexture( userCameraDevice.name, m_width, m_height ); } } // class TestCamera
今回はデバイスの名前を指定していますが、指定しない場合には最初に検出されたデバイス名を使うみたいです。
他にもフレームレートも指定できるみたいです。
さあ、撮影を開始するよ!
あとは、画面上でUIのRawImage
に先ほど作ったWebCamTexture
を設定して動かしてみましょう。
using UnityEngine; using UnityEngine.UI; using System.Collections; public class TestCamera : MonoBehaviour { [SerializeField] private int m_width = 1920; [SerializeField] private int m_height = 1080; [SerializeField] private RawImage m_displayUI = null; private WebCamTexture m_webCamTexture = null; private IEnumerator Start() { if( WebCamTexture.devices.Length == 0 ) { Debug.LogFormat( "カメラのデバイスが無い様だ。撮影は諦めよう。" ); yield break; } yield return Application.RequestUserAuthorization( UserAuthorization.WebCam ); if( !Application.HasUserAuthorization( UserAuthorization.WebCam ) ) { Debug.LogFormat( "カメラを使うことが許可されていないようだ。市役所に届けでてくれ!" ); yield break; } // とりあえず最初に取得されたデバイスを使ってテクスチャを作りますよ。 WebCamDevice userCameraDevice = WebCamTexture.devices[ 0 ]; m_webCamTexture = new WebCamTexture( userCameraDevice.name, m_width, m_height ); m_displayUI.texture = m_webCamTexture; // さあ、撮影開始だ! m_webCamTexture.Play(); } } // class TestCamera
おお、いい感じにPCに取り付けたWebカメラの映像が表示されています。
これは僕が作ったノートの映像ですね。
ちょっとだけUIを改良するよ!
あとせっかくなので、UIを少しだけ改良しましょう。
PlayボタンとStopボタンを追加してみました。
public void OnPlay() { if( m_webCamTexture == null ) { return; } if( m_webCamTexture.isPlaying ) { return; } m_webCamTexture.Play(); } public void OnStop() { if( m_webCamTexture == null ) { return; } if( !m_webCamTexture.isPlaying ) { return; } m_webCamTexture.Stop(); }
Androidで使えるかな
さあ、このシーンをAndroidにビルドしてみましょう。
上手くいくといいけど。
わーい、あっさり出来ました。
簡単ですね!
iOSで使えるかな
では引き続きiOSにもビルドしてみましょう。
さあ、どうでしょうか。
この後、即クラッシュ!
なぜなのか。
iOS10以降では一手間必要だ!
インターネットで検索したところ、こんな情報がありました。
qiita.com
んー、カメラを使うにはInfo.plistにカメラ許可用のキーを設定する必要があるみたいですね。
Xcodeで設定してあげればいいんですが、僕のこのPCはWindows。Xcodeはありませんわ!
iOS用のビルドはCloudBuildを使って作っているんですよね……。
PostProcessBuildAttribute
を使って、自動でInfo.plistに書き込むようにするしかないね!
Editorフォルダをつくって、その中にPostProcessBuild用のスクリプトを作ってっと。
using UnityEngine; using UnityEditor; using UnityEditor.iOS.Xcode; using UnityEditor.Callbacks; public class PostBuilder { [PostProcessBuildAttribute()] public static void OnPostProcessBuild( BuildTarget i_buildTarget, string i_pathToBuiltProject ) { if( i_buildTarget == BuildTarget.iOS ) { OnPostProcessBuild_iOS( i_buildTarget, i_pathToBuiltProject ); } } private static void OnPostProcessBuild_iOS( BuildTarget i_buildTarget, string i_pathToBuiltProject ) { var plistPath = System.IO.Path.Combine( i_pathToBuiltProject, "Info.plist" ); var plist = new PlistDocument(); plist.ReadFromFile( plistPath ); plist.root.SetString( "NSCameraUsageDescription", "" ); plist.WriteToFile( plistPath ); } } // class PostBuilder
さあ、これでiOSビルドに再チャレンジですよ。
やったー、うまくいきましたよー。
締めの言葉
WebCamTexture
を使って簡単にカメラの画像が取得できました。
iOS,Androidそしてエディタ上全てで共通処理で出来るので楽ちんです。
フレームレート的に動画として使うのは、ちょっと難しいかな。