Edited at

【OpenCV for Unity】texture2DToMatは絶対に必要なので忘れないように

OpenCV for Unityを使い始めました。基本的な画像処理で間違ったためメモします。


画像によって、うまくいかない現象が起きる

基本的な画像処理”チャネル入れ替え”の処理を作ったのですが、うまくいく画像といかない画像の2パターンがでてきました。

■うまくいった画像

スクリーンショット 2019-05-08 18.43.40.png

■うまくいかない画像

スクリーンショット 2019-05-08 19.16.07.png

画像の設定で何か問題があるのかなぁ…と思い、設定を全て揃えたのですが、うまくいかず…

スクリーンショット_2019-05-08_18_52_22.png


原因:texture2DToMatがないから

うまくいかないコードがこちらです。


RGB2BGR.cs

    void Start()

{
Texture2D srcTex = Resources.Load("imori") as Texture2D;

Mat srcMat = new Mat(srcTex.height, srcTex.width, CvType.CV_8UC4);
Mat dstMat = new Mat(srcTex.height, srcTex.width, CvType.CV_8UC4);

Imgproc.cvtColor(srcMat, dstMat, Imgproc.COLOR_RGBA2BGRA);
Texture2D dstTex = new Texture2D(dstMat.cols(), dstMat.rows(), TextureFormat.RGBA32, false);
Utils.matToTexture2D(dstMat, dstTex, false);

Sprite texture_sprite = Sprite.Create(dstTex, new UnityEngine.Rect(0, 0, dstTex.width, dstTex.height), new Vector2(-0.25f, 0.5f));
GetComponent<SpriteRenderer>().sprite = texture_sprite;
}


原因は致命的で、texture2DToMatがなかったためです。new Mat()だけでは初期化しかしていないので、うまくいかないのも当然であります。

修正したコードはこちらになります!


RGB2BGR.cs

    void Start()

{
Texture2D srcTex = Resources.Load("imori") as Texture2D;

//ここではmatの入れ物を用意するだけ
Mat dstMat = new Mat(srcTex.height, srcTex.width, CvType.CV_8UC4);

//テクスチャ→Mat
Utils.texture2DToMat(srcTex, dstMat);

//チャネル入替
Imgproc.cvtColor(dstMat, dstMat, Imgproc.COLOR_RGBA2BGRA);

//Mat→テクスチャ
Texture2D dstTex = new Texture2D(dstMat.cols(), dstMat.rows(), TextureFormat.RGBA32, false);
Utils.matToTexture2D(dstMat, dstTex);

//テクスチャ→sprite→表示
Sprite texture_sprite = Sprite.Create(dstTex, new UnityEngine.Rect(0, 0, dstTex.width, dstTex.height), new Vector2(-0.25f, 0.5f));
GetComponent<SpriteRenderer>().sprite = texture_sprite;
}


ちゃんとチャネル変換されていることがわかります。

スクリーンショット 2019-05-08 19.28.15.png

大きな違いはUtils.texture2DToMatがあるかどうかです。うまくいっている処理は、texture2DToMatがあります。

あくまでも仮説にはなりますが、Utils.texture2DToMatなしでもうまくいったのは、Mat srcMat = new Mat(srcTex.height, srcTex.width, CvType.CV_8UC4)で元々のテクスチャをMat変換+TextureやMatの型が合致したからかもしれません。

もしOpenCV for UnityでMat変換するときは、必ずUtils.texture2DToMatを用いた方が良さそうです。

(原因が仮説段階のため、断定はしていません。もし詳細がわかる方いらっしゃりましたら、コメントいただけると嬉しいです!)

追記:2019/5/9

原因はtexture2DToMatがなかったためです。new Mat(~,~,~)でも処理が動いたのは、openCV以外の原因(キャッシュが残るなど)、他が原因になります。

コメントしてくださった@utibenkeiさん、本当にありがとうございました!!!


参考リンク