LoginSignup
3
5

More than 5 years have passed since last update.

Android(Java)でのOpenCVを用いたソーベルフィルタ

Last updated at Posted at 2017-02-16

はじめに

AndroidでOpenCV3.2を利用してソーベルフィルタを実装した。
JavaのOpenCVでは思うようにできない部分がいくつかあったのでメモ

実行環境など

ソフトウェア

Windows 10 Home 64bit
Android Studio 2.2.3
OpenCV 3.2

デバッグ端末

Nexus 5x (Android 7.1.1)

OpenCVの準備

以下参照
OpenCV for AndroidをAndroid Studioに導入するメモ

ポイント

ただの一方向のソーベルフィルタだとつまらないので、グレースケールに変換してからフィルタ処理を行わずあえてRGB成分に分割してそれぞれの色でX方向とy方向のフィルタ処理を行い二乗平均平方根をとった後で、三つの成分の値なかでの最大値を最終的な画素値とした。

メモ

C++のOpenCVだと

matC = matA +matB;

みたいな書き方ができるけどJavaのOpenCVではできない

コード

    private Bitmap sobel(Bitmap bitmap) {
        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        Mat mat = new Mat();
        Mat matR = new Mat();
        Mat matG = new Mat();
        Mat matB = new Mat();
        Utils.bitmapToMat(bitmap, mat);

        Core.extractChannel(mat, matR, 0);
        myFiltering(matR);

        Core.extractChannel(mat, matG, 1);
        myFiltering(matG);

        Core.extractChannel(mat, matB, 2);
        myFiltering(matB);

        matMax3(matB, matG, matR, matB);

        Utils.matToBitmap(matB, bitmap);
        return bitmap;
    }

    private void myFiltering(Mat src){
        Mat matX = new Mat();
        Mat matY = new Mat();

        Imgproc.GaussianBlur(src, src, new Size(3, 3), 0, 0);
        Imgproc.Sobel(src, matX, src.depth(), 0, 1);
        Imgproc.Sobel(src, matY, src.depth(), 1, 0);
        matRMS(matX, matY, src);
    }

    private void matRMS(Mat src1, Mat src2, Mat dst) {

        int size = (int) (src1.total() * src1.channels());
        byte[] temp1 = new byte[size];
        byte[] temp2 = new byte[size];
        byte[] temp3 = new byte[size];
        src1.get(0, 0, temp1);
        src2.get(0, 0, temp2);

        for (int i = 0; i < size; i++) {
            temp3[i] = (byte)Math.sqrt((temp1[i] * temp1[i] + temp2[i] * temp2[i]) / 2);
        }

        dst.put(0, 0, temp3);
    }

    private void matMax3(Mat src1, Mat src2, Mat src3, Mat dst) {

        int size = (int) (src1.total() * src1.channels());
        byte[] temp1 = new byte[size];
        byte[] temp2 = new byte[size];
        byte[] temp3 = new byte[size];
        byte[] temp4 = new byte[size];
        src1.get(0, 0, temp1);
        src2.get(0, 0, temp2);
        src3.get(0, 0, temp3);

        for (int i = 0; i < size; i++) {
            temp4[i] = chooseBig(chooseBig(temp1[i], temp2[i]), temp3[i]);
        }

        dst.put(0, 0, temp4);
    }

    private byte chooseBig(byte a, byte b) {
        if(b > a) {
            return b;
        }else {
            return a;
        }
    }

実機での実行結果

Screenshot_20170216-223854-1.jpg

GitHubのリンク

GUIの都合上AsyncTaskを用いて実装した。
こちら

apk

ビルドしたapkのリンク
こちら
※Android端末にOpenCV Managerのインストールが必要です。インストールされていない場合はGoogle Play Storeへ飛ばされます
※インストールは自己責任で

参考

OpenCVとVisual C++による画像処理と認識(7)----- いろいろなエッジ検出フィルタを使用する -----

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5