はじめに
画像処理を簡単に解説していきます。
下部にはJavaでのソースコードも載せているのでぜひご参照ください。
不定期にはなりますが、随時更新していく予定です。
二値化とは?
名前の通り、画像を0(黒)と1(白)の二値に変換する処理です。
なお、処理によっては1ではなく255を設定することもあります。
二値化された画像は白と黒の二色だけで構成されます。
下部の例を見て頂いた方が理解しやすいかと思います。
この変換は領域分割や境界線抽出などの前処理としてよく用いられます。
白黒はっきりつけることで、画像の解析がしやすくなると理解しておけば十分です。
どうやって二値にするの?
画像を二値化するにはしきい値というものを用います。
処理としては単純で、画素値がしきい値より大きければ白、小さければ黒とするのが一般的です。
カラー画像のままでは処理ができないため、前処理としてグレースケール変換が用いられます。
余談ですが、二値化には2つ以上のしきい値を用いるものも存在します。
応用として実装してみても面白いかもしれませんね。
しきい値の決め方は?
しきい値の決め方については、手動で決め打ちする方法と自動で決定する方法があります。
自動で決める方法としては判別分析法(大津の二値化法)が有名です。
これは次回説明する予定です。
今回は手動で決める方法を選択します。
手動のメリットとしては、好きなように微調整ができるという点があります。
一方、その調整が手間であることがデメリットになります。
アルゴリズム
- カラー画像はグレースケール変換する。
- グレースケール画像をラスタスキャンし、各画素に対して3と4の処理を行う。
- 画素のグレー値を取得する。
- グレー値がしきい値以上ならば255を、そうでなければ0をバイナリ画像にセットする。
二値化の例
ソースコード
以下のプログラムでは白領域を255としています。
1でも処理上は問題ないのですが、表示した際に結果が確認しにくいためです。
public static SImage binarize(SImage grayImg, int threshold) {
// グレースケール画像でない場合、まずグレースケール変換する
if (grayImg.channel != 1)
return binarize(toGray(grayImg), threshold);
// 二値画像の生成
var binaryImg = new SImage(grayImg.width(), grayImg.height(), 1);
// 画像をラスタスキャン
for (int x = 0; x < grayImg.width(); x++)
for (int y = 0; y < grayImg.height(); y++) {
// グレー値を取得
int gray = grayImg.getGray(x, y);
// グレー値がしきい値以上ならば255を、そうでなければ0をバイナリ値にセット
int binary = gray >= threshold ? 255 : 0;
// バイナリ値を画像にセット
binaryImg.setGray(x, y, binary);
}
return binaryImg;
}