0
2

More than 3 years have passed since last update.

【画像処理解説】ポスタリゼーション(Javaソース付き)

Last updated at Posted at 2021-08-16

はじめに

画像処理を簡単に解説していきます。
下部にはJavaでのソースコードも載せているのでぜひご参照ください。
不定期にはなりますが、随時更新していく予定です。

ポスタリゼーションとは?

階調変更アルゴリズムであり、色の階調を変更する画像処理です。
一般的な画像は0から255の256階調で成立しています。
これをルックアップテーブル(LUT)を用いて、任意の階調数に変更します。

似たような処理として減色処理があります。
減色処理では、階調を減らすというよりも、画像情報を残しつつ情報量を減らすことが目的となります。
ポスタリゼーションは画像を加工してアートみたいにできるのが特徴ですね。

LUTとは?

画素値変換用の参照テーブルのことです。
ポスタリゼーションの場合、階調数を$t$とするとLUTは以下の式で定義されます

lut(i) = \left[\left[\frac{i\times t}{256}\right]\times\frac{255}{t-1}\right]

階調数が4の時、画素値100は85に、画素値200は255に変換されます。
いろいろ試してみると面白い画像が生まれるかもしれませんね。

アルゴリズム

  1. 上記の式を用いてLUTを生成する。
  2. 画像をラスタスキャンし、各画素においてLUTによる値変換を行う。

ポスタリゼーションの例

元画像(カラー画像)
imori_256x256.png

結果画像(ポスタリゼーション画像)
out06.png

ソースコード

Color.java
public static SImage posterization(SImage oriImg, int tone) {
    // 階調数を2から128に制限する
    if (tone < 2)
        tone = 2;
    else if (tone > 128)
        tone = 128;

    // LUTの生成
    int[] lut = new int[256];
    for (int i = 0; i < 256; i++)
        lut[i] = (int) ((int) (i * tone / 256.0) * 255.0 / (tone - 1));

    // ポスタリゼーション画像用を生成
    var posterImg = new SImage(oriImg.width(), oriImg.height(), oriImg.channel);

    // グレースケール画像の場合
    if (oriImg.channel == 1) {
        // 画像をラスタスキャン
        for (int y = 0; y < oriImg.height(); y++)
            for (int x = 0; x < oriImg.width(); x++) {
                // 値を取得
                int v = oriImg.getGray(x, y);

                //LUTで変換した値をを出力画像にセット
                posterImg.setGray(x, y, lut[v]);
            }

        // RGBカラー画像の場合
    } else if (oriImg.channel == 3) {
        // 画像をラスタスキャン
        for (int y = 0; y < oriImg.height(); y++)
            for (int x = 0; x < oriImg.width(); x++) {
                // 値を取得
                int[] rgb = oriImg.getRGB(x, y);

                // LUTを用いて変換
                int[] newRgb = new int[]{lut[rgb[0]], lut[rgb[1]], lut[rgb[2]]};

                //LUTで変換した値をを出力画像にセット
                posterImg.setRGB(x, y, newRgb);
            }

        // アルファチャネルを持つ場合
    } else {
        // 画像をラスタスキャン
        for (int y = 0; y < oriImg.height(); y++)
            for (int x = 0; x < oriImg.width(); x++) {
                // 値を取得
                int[] argb = oriImg.getARGB(x, y);

                // LUTを用いて変換
                int[] newRgb = new int[]{lut[argb[0]], lut[argb[1]], lut[argb[2]], lut[argb[3]]};

                //LUTで変換した値をを出力画像にセット
                posterImg.setARGB(x, y, newRgb);
            }

    }
    return posterImg;
}
0
2
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
0
2