2011年10月5日水曜日

BitmapToMat & MatToBitmapを使う際の注意点 OpenCV Java API for Android

OpenCVで使われる万能な画像型のMat。
それを使った際の注意点のメモ



org.opencv.android.にある
boolean matToBitmap(Mat m, Bitmap b) 
Mat bitmapToMat(Bitmap b) 
を使うことで、Bitmap型をMat型を相互に変換できる。
OpenCVのカメラを使って直接Matにすることも出来ますが、既存のコードや、ファイルエクスプローラーを使って既存の画像を扱う際はこちらが良いと思われる。

しかし、注意点としてMatはnewで新規作成されたものが帰ってくるのに対し、Bitmapはメモリを確保しないと行けないという点だ。Bitmap srcに画像を読み込んでMatに変換してからOpenCVで画像処理をしてからsrcに戻そうとすると画像の回転や拡大縮小等でサイズが変わっていると大変なことになってしまうので気をつけて欲しい。

以下OpenCVのソースコードを一部抜粋


    public static Mat bitmapToMat(Bitmap b) {
        return new Mat(nBitmapToMat(b));
    }

    public static boolean matToBitmap(Mat m, Bitmap b) {
        return nMatToBitmap(m.nativeObj, b);
    }

    // native stuff
    static {
        System.loadLibrary("opencv_java");
    }

    private static native long nBitmapToMat(Bitmap b);

    private static native boolean nMatToBitmap(long m, Bitmap b);

Bitmap→Matはnew Mat();が帰ってきているのに対して、Bitmapは引数のオブジェクトに中身が入る。

なので、Bitmapを読み込んで画像処理をする際は、以下のように書くのが望ましい。

        //  画像を読み込む
        Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.lena);

        //  画像をMatへ変換
        Mat m = Utils.bitmapToMat(src);

        //  グレースケール変換
        Imgproc.cvtColor(m, m, Imgproc.COLOR_RGB2GRAY);

        //  Cannyでエッジ検出
        Imgproc.Canny(m, m, 80, 100);

        //  Bitmapに変換する前にRGB形式に変換
        Imgproc.cvtColor(m, m, Imgproc.COLOR_GRAY2RGBA, 4);

        //  Bitmap dst に空のBitmapを作成
        Bitmap dst = Bitmap.createBitmap(m.width(), m.height(), Bitmap.Config.ARGB_8888);

        //  MatからBitmapに変換
        Utils.matToBitmap(m, dst);

        //  処理をした画像を表示する
        ImageView iv = (ImageView)findViewById(R.id.ImageView01);
        iv.setImageBitmap(dst);

ただ単にエッジ検出をするだけなら、画像のサイズが変わらないので今回のように空のBitmapをMatにあわせて作り直す必要はなく、srcに入れなおしても無事に動くが、回転や拡大縮小、アフィン変換や透視変換を行うと画像サイズが変わるので大変なことになります。

0 件のコメント:

コメントを投稿