2017年2月8日水曜日

ベイヤーディザフィルタ(BayerDitherFilter)

 今回はベイヤーディザフィルタを作成します。ベイヤーディザフィルタはディザリング手法の一つです。ベイヤーとはベイヤー型のパターンをさし、4×4のマトリックスを用いて処理を行います。以下にベイヤー型のパターンを載せます。

ベイヤーディザでは4×4のマトリックス内の輝度の平均値をとり、その平均値が上の図の右の各セルの値以上ならばそのセルを白色にするという処理を行います。例えば、160という値では下のような塗りつぶし方になります
このように白黒の数で範囲内の濃淡を表します。なお、平均値をとらず、各ピクセルの場所とマトリックスの場所の対応関係から変換する方法もあります。

 Tutorial1Activityクラスと同じ場所にBayerDitherFilterクラスを作成します。その後、filterメソッドに以下のコードを入力します。
    public int[] filter(int[] imageArray, int width, int height) {
            int Bayer[] = new int[]{//①
                    0, 8, 2, 10,
                    12, 4, 14, 6,
                    3, 11, 1, 9,
                    15, 7, 13, 5
            };
            for (int i = 0; i < 16; i++) {
                Bayer[i] = Bayer[i] * 16 + 8;//②
            }
            int xn = width / 4;
            int yn = height / 4;

            int length = width * height;
            int[] oimgArray = new int[imageArray.length];
            int rgb;
            int red, green, blue;
            int y_val;
            for (int i = 0; i < length; i++) {
                rgb = imageArray[i];
                red = (rgb >> 16) & 0xff;
                green = (rgb >> 8) & 0xff;
                blue = (rgb) & 0xff;
                y_val = (2 * red + 4 * green + blue) / 7;
                oimgArray[i] = 255 * 16777216 + y_val * 65536 + y_val * 256 + y_val;
            }
            int pointer = 0;
            int x, y, xln, yln, sum, xy;
            for (y = 0; y < yn; y++) {
                for (x = 0; x < xn; x++) {
                    pointer = y * 4 * width + x * 4;
                    sum = 0;
                    for (yln = 0; yln < 4; yln++) {
                        for (xln = 0; xln < 4; xln++) {
                            sum += oimgArray[pointer + xln + yln * width]& 0xff;;//③
                        }
                    }
                    sum = sum / 16;//④
                    for (yln = 0; yln < 4; yln++) {
                        for (xln = 0; xln < 4; xln++) {
                            xy = xln + yln * 4;
                            if (sum >= Bayer[xy]) {//⑤
                                oimgArray[pointer + xln + yln * width] = 0xFFFFFFFF;
                            } else {
                                oimgArray[pointer + xln + yln * width] = 0xFF000000;
                            }


                        }
                    }
                }
            }
            return oimgArray;
    }

 ①ではベイヤー型の4×4のマトリックスを作成します。それを②では×16+8の計算をしています。
 ③では4×4の枠内で輝度の合計値を求めています。そして④で平均化しています。
 ⑤ではベイヤー型マトリックスの各セルと、④で得た輝度平均値を比較して、輝度平均値がセルの値以上ならば白に、そうでないならば黒に変換します。これによりベイヤー型のマトリックスに則った白黒の数を表現します。
最後に、 Tutorial1Activityクラスのint imageArray[]=ba2ia(ba);の下に以下の文を記入します。
imageArray=new BayerDitherFilter().filter(imageArray, imagewidth, imageheight);

以下に実機での実行結果を示します。白黒のみですが、前回のランダムディザ同様に濃淡が表現できていることがわかります。人物の顔の部分だけを拡大した図も載せます。


0 件のコメント:

コメントを投稿