#はじめに
画像処理を簡単に解説していきます。
下部にはJavaでのソースコードも載せているのでぜひご参照ください。
不定期にはなりますが、随時更新していく予定です。
#グレースケール画像とは?
一言でいうと白黒画像です。
プリンターなどで白黒印刷を選択すると出てくる画像です。
前回、カラー画像は3チャネルで構成されると説明しました。
グレースケール画像はチャネル数が1つとなります。
すなわち、8bitのみで画像を表示することができます。
ただし、8bitに対応していないライブラリでは、24bitのままグレースケール画像を扱うことがあります。
その場合、各画素のR, G, Bには同じ値をセットすることになります。
#公式はあるの?
単にRGB値の平均を取ることでもグレースケール化はできます。
しかし、一般的には以下の式が用いられています。
$ V = 0.213R + 0.715G + 0.072B $
人間の視覚は緑に対して敏感な一方、青に対して鈍感となっています。
そのため、上記のような重みづけをした式を用いることで、より人間の視覚に適した変換ができます。
#アルゴリズム
- カラー画像をラスタスキャンし、各画素に対して2から4の処理を行う。
- 画素のR, G, Bのそれぞれの値を取得する。
- 先述の公式を用いて、グレー値を算出する。
- 画素に対して、4で算出したグレー値をセットする。
#ソースコード
SImageでグレースケール画像を扱うにはチャネル数を1にします。
Color.java
public static SImage toGray(SImage colorImg) {
// カラー画像でない場合、そのまま返す
if (colorImg.channel == 1)
return colorImg.copy();
// アルファチャネルを持つ場合、処理を分ける
if (colorImg.channel == 4) {
var grayImg = new SImage(colorImg.width(), colorImg.height(), 1);
for (int x = 0; x < colorImg.width(); x++)
for (int y = 0; y < colorImg.height(); y++) {
int[] argb = colorImg.getARGB(x, y);
int gray = (int) Math.rint(0.213 * argb[1] + 0.715 * argb[2] + 0.072 * argb[3]);
grayImg.setGray(x, y, gray);
}
return grayImg;
}
// グレースケール画像の生成
var grayImg = new SImage(colorImg.width(), colorImg.height(), 1);
// 画像をラスタスキャン
for (int x = 0; x < colorImg.width(); x++)
for (int y = 0; y < colorImg.height(); y++) {
// RGB配列を取得
int[] rgb = colorImg.getRGB(x, y);
// 公式を用いてグレー値を計算
int gray = (int) Math.rint(0.213 * rgb[0] + 0.715 * rgb[1] + 0.072 * rgb[2]);
// グレー値を画像にセット
grayImg.setGray(x, y, gray);
}
return grayImg;
}