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

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

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

■うまくいった画像
<img width="580" alt="スクリーンショット 2019-05-08 18.43.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314351/0e0e84f1-35b9-1571-71d7-bccd9187b6b7.png">

■うまくいかない画像
![スクリーンショット 2019-05-08 19.16.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314351/8f20dcbf-cc9d-55a3-d0fc-cab4e2b7eb84.png)


画像の設定で何か問題があるのかなぁ…と思い、設定を全て揃えたのですが、うまくいかず…
<img width="686" alt="スクリーンショット_2019-05-08_18_52_22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314351/4861fe21-c029-9764-ae92-c72b72b193c4.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314351/e550c1f9-1727-4619-e8c8-5d8f549722b0.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さん、本当にありがとうございました！！！

## 参考リンク
- [画像処理100本ノック!!](https://github.com/yoyoyo-yo/Gasyori100knock)
- [OpenCV plus Unityを使ってみる（セットアップ、画像処理100本ノック1~10編）](https://qiita.com/Hirai0827/items/fd7b1dea42103841d033)