OpenCV for Unityを使ってウェブカメラの画像をいじろうとしたところ、WebCamTextureをMatに変換するときにエラーが出たため、その時のメモ
※ ビギナーのためコードが汚いと思いますが、ご指摘あればいただけると嬉しいです。
利用環境:Unity5.3, OpenCV for Unity 2.0.1(OpenCV 3.1.0)
問題:WebCamTextureとMatのサイズが違うと言われる
void Start() {
webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name);
webCamTexture.Play();
mat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
colors = new Color32[webCamTexture.width * webCamTexture.height];
texture = new Texture2D(webCamTexture.width, webCamTexture.height);
GetComponent<Renderer> ().material.mainTexture = texture;
}
void Update() {
Utils.webCamTextureToMat(webCamTexture, mat, colors); // ArgumentException: The output Mat object has to be of the same size
// 以下Mat処理
}
}
という風に、webCamTextureToMatする時に「Matを同じサイズにしろ」と言われます。
Mat宣言するときにWebCamTextureからwidthとheightを持ってきてるのになんでや。。?
原因:WebCamTexture.widthが16と出力される
なにやら、WebCamTexture.didUpdateThisFrame == false
の状態でWebCamTexture.width
とWebCamTexture.height
の値を取得しようとすると(16, 16)で出力されるらしい。そのためmatのサイズが(16, 16)になっていた。
WebCamTexture.width
の値自体は正常なので、webCamTextureとmatの間にサイズの違いが生じていた模様。
ちなみに下記の参考URLではiOSへのビルドに限って起こるUnity自体のバグと書かれているけど、自分の場合は他のプラットフォームにswitchしても生じたので、そこのところは謎。
参考URL
https://issuetracker.unity3d.com/issues/ios-webcamtexture-dot-width-slash-height-always-returns-16
解決法:WebCamTexture.didUpdateThisFrame == trueになるまで待つ
WebCamTexture.didUpdateThisFrame == true
になるまでmatの宣言を待ちつつ、Utils.webCamTextureToMat(webCamTexture, mat, colors);
はmatが宣言されるまで実行しないようにしたところ、一応問題は解決した。
void Start() {
webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name);
webCamTexture.Play();
StartCoroutine (init ());
}
private IEnumerator init (){
if(webCamTexture.width <= 16){
while(!webCamTexture.didUpdateThisFrame){
yield return new WaitForEndOfFrame();
}
webCamTexture.Pause ();
colors = webCamTexture.GetPixels32 ();
webCamTexture.Stop ();
yield return new WaitForEndOfFrame ();
webCamTexture.Play();
// 宣言
texture = new Texture2D(webCamTexture.width, webCamTexture.height);
mat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
GetComponent<Renderer> ().material.mainTexture = texture;
}
}
void Update() {
if (webCamTexture.didUpdateThisFrame && mat != null) {
Utils.webCamTextureToMat (webCamTexture, mat, colors);
// 以下Mat処理
}
}