2017年2月6日月曜日

Tutorial1Activityで画像処理を行うための編集2

前回に引き続き、Tutorial1Activityを編集し、細かい画像処理が可能な形に変更します。
今回は前回編集したonCameraFrameメソッドの中の、2つのImgproc.resizeおよびif文の間に以下の文を加えます。

        int imagewidth=mat.cols();//①
        int imageheight=mat.rows();//①
        byte[] ba=mat2ba(mat);//②
        mat = null;

        ba=ba4toba3(ba);//③
        int imageArray[]=ba2ia(ba);//④
        
        //ここで画像処理
        
        ba=ia2ba(imageArray);//⑤
        mat=ba2mat(imagewidth,imageheight,ba);//⑥
        ba=null;

 ①はそれぞれ、matから画像の幅と高さを取得しています。この値は実機によって異なる値です。また、リサイズしている場合にはリサイズ後の値が入ります。
 ②はmatをbyte配列に変換するメソッドです。詳しいメソッド内容は後述します。この時点でのbyte配列は、一つの画素・ピクセルを4個のbyteで表しており、配列上ではred、green、blue、alphaの順に並んでいます。
 ③ではこのバイト配列を変換し、一つのピクセルを3個のbyteで表すように変換します。ここではbyte配列からalphaを削除します。
 ④ではbyte配列をint配列に変換します。このint配列は一つの画素を一つのintで表しており、255*16777216を固定のalpha値、65536の倍数をred、256の倍数をgreen、1の倍数をblueで表しています。このint配列が、このブログで行う画像処理の基本的な処理対象となります。
 ⑤では画像処理した後のint配列を一度byte配列に戻します。この時点でのbyte配列は③と同じく一つのピクセルを3個のbyteで表しています。
 ⑥ではbyte配列をmatに変換しています。この際、必ず画像の幅と高さが必要になります。
 以上が今回の編集部分です。次に、各メソッドの内容を記載します。

mat2ba

    public static byte[] mat2ba(Mat mat){
        int dataSize=mat.cols()*mat.rows()*(int)mat.elemSize();
        byte[] data = new  byte[dataSize];
        mat.get(0, 0,data);
        mat=null;
        return data;
    }

ba4toba3
    public byte[] ba4toba3(byte ba[]){
        int length=ba.length;
        int slash=length/4;
        byte result[]=new byte[slash*3];
        for(int i =0;i < slash;i++){
            result[i*3]=ba[i*4];//r
            result[i*3+1]=ba[i*4+1];//g
            result[i*3+2]=ba[i*4+2];//b

        }
        ba=null;
        return result;
    }

ba2ia
    public static int[] ba2ia(byte ba[]){
        int length = ba.length/3;
        int result[]=new int[length];
        int r,g,b;
        for(int i =0;i < length;i++){
            r=ba[i*3]& 0xFF;
            g=ba[i*3+1]& 0xFF;
            b=ba[i*3+2]& 0xFF;
            result[i]=rgb2int(r, g, b);
        }
        ba=null;
        return result;
    }

ba2iaで使用しているrgb2int (r、g、bの値をint型に変換する)
    public static int rgb2int(int r,int g,int b){
        return 255*16777216+r*65536+g*256+b;
    }

ia2ba
    public static byte[] ia2ba(int ia[]){
        int length=ia.length;
        int red,green,blue;
        byte result[]=new byte[length*3];
        int rgb=0;
        for(int i =0;i < length;i++){
            rgb = ia[i];
            red = (rgb >> 16) & 0xff;
            green = (rgb >> 8) & 0xff;
            blue = (rgb) & 0xff;
            result[i*3]=(byte)red;
            result[i*3+1]=(byte)green;
            result[i*3+2]=(byte)blue;
        }
        ia=null;
        return result;
    }


ba2mat (CvTypeでorg.opencv.core.CVTypeのインポートが必要)
    public Mat ba2mat(int width,int height,byte pixels[]){
        Mat mat = new Mat(height,width, CvType.CV_8UC3);
        mat.put(0,0,pixels);
        return mat;
    }


以上が今回必要なメソッドです。実機で実行すると、これまでよりフレームレートの落ちたプレビューがみられるでしょうが、それ以外に変化はありません。

0 件のコメント:

コメントを投稿