2017年2月10日金曜日

YCrCb変換による彩度フィルタ(SaturationYCrCbFilter)

今回はYCbCr変換による彩度変換フィルタを作成します。YCbCrとは輝度信号Yと、2つの色差信号Cb(青)Cr(赤)を使って表現される色空間です。RGBと相互に変換することができます。詳しくは以下のリンクを参照してください。
http://www.wdic.org/w/WDIC/YCbCr

今回はまずYCbCrとRGBを相互変換するYCbCRTransクラスを作成します。 Tutorial1Activityクラスと同じ場所にYCbCRTransクラスを作成します。その後、以下のコードを入力します。
 public double[] RGBtoYCbCr(int rgb){
        double red = (double)((rgb >> 16) & 0xff)/255.0;//①
        double green = (double)((rgb >> 8) & 0xff)/255.0;
        double blue = (double)((rgb) & 0xff)/255.0;
        double Y=0.2990*red+0.5870*green+0.1140*blue;//②
        double Cb=-0.1690*red-0.3310*green+0.5000*blue;
        double Cr=0.5000*red-0.4190*green-0.0810*blue;
        double[] YCbCr=new double[]{Y,Cb,Cr};
        return YCbCr;
    }
    public int YCbCrtoRGB(double YCbCr[]){
        double dred=YCbCr[0]+1.4020*YCbCr[2];//③
        double dgreen=YCbCr[0]-0.3441*YCbCr[1]-0.7141*YCbCr[2];
        double dblue=YCbCr[0]+1.7720*YCbCr[1];
        int red=(int)(dred*255.0);//④
        if(red > 255){
            red=255;//⑤
        }else if(red < 0){
            red=0;
        }
        int green=(int)(dgreen*255.0);
        if(green > 255){
            green=255;
        }else if(green < 0){
            green=0;
        }
        int blue=(int)(dblue*255.0);
        if(blue > 255){
            blue=255;
        }else if(blue < 0){
            blue=0;
        }
        return 255*16777216+red*65536+green*256+blue;
    }

 ①はRGB値を0~1の範囲に変換しています。
 ②は①で変換したRGB値をYCbCrに変換しています。
 ③は②の逆変換で、YCbCr値をRGB値(0~1)に変換しています。
 ④はRGB値の範囲を0~255に変換しています。ただし、この時点では0未満や255より大きい値が入る可能性があります。
 ⑤は④の値を丸め、0~255の範囲に変換しています。

 次に、彩度変換を行うクラスを作成します。Tutorial1Activityクラスと同じ場所にSaturationYCbCrFilterクラスを作成します。その後、filterメソッドに以下のコードを入力します。
    public int[] filter(int[] imageArray, int width, int height, double value) {
        YCbCrTrans trans=new YCbCrTrans();
        int length = width*height;
        int[] oimgArray = new int[imageArray.length];
        double YCbCr[]=new double[3];
        for(int i =0;i < length;i++){
            YCbCr=trans.RGBtoYCbCr(imageArray[i]);//⑥
            YCbCr[1]*=value;//⑦
            YCbCr[2]*=value;
            oimgArray[i]=trans.YCbCrtoRGB(YCbCr);//⑧
        }
        return oimgArray;
    }

 ⑥ではRGB値をYCbCr値に変換しています。
 ⑦ではCbとCrにメソッドの引数をかけることで、鮮やかさを変化させています。
 ⑧ではYCbCr値をRGB値に変換しています。

 最後に、 Tutorial1Activityクラスのint imageArray[]=ba2ia(ba);の下に以下の文を記入します。
imageArray=new SaturationYCbCrFilter().filter(imageArray, imagewidth, imageheight, 1.5);

第4引数が変化させる彩度の倍数を指定しています。
 以下に実機での実行結果を示します。HSVによる彩度変化のときと同様に鮮やかさが増していることがわかります。


0 件のコメント:

コメントを投稿