#はじめに
画像処理を簡単に解説していきます。
下部には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に変換されます。
いろいろ試してみると面白い画像が生まれるかもしれませんね。
#アルゴリズム
- 上記の式を用いてLUTを生成する。
- 画像をラスタスキャンし、各画素においてLUTによる値変換を行う。
#ソースコード
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;
}