2006 年 2 月 11 日 23 時 49 分

Floyd-Stein 法による 2 値化+α


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


[写真] [写真] [写真]


誤差拡散法の中でも、非常によく使われている配列に、
Floyd-Stein 法というものがある。
誤差拡散のアルゴリズムや誤差配列には様々な方法があるが、
この方法は計算速度が速い割りに精度が高い。

これは、以下のような比率で差分値を分散する。

×××
×■7
351

つまり、差分値の 7/16 を右へ、3/16 を左下へ、
5/16 を下へ、1/16 を右下へ割り振る計算である。
実装は昨日とほとんど変わらないため割愛する。

これだけでは短いので、番外編的な 2 値化を紹介しよう。
それは「ランダム 2 値化」だ。
方法は単純で、ピクセルごとに閾値をランダムで決める。

乱数処理が入るので、処理ごとに結果が異なる事となる。
ランダムなので、品質は高いとはいえないが、
ランダム処理がノイズのような役割を果たすため、
大き目の画像に対して処理をすると面白い。


# BMP 読み込み。
my $data = read_bmp;

foreach my $line (@$data) {
    foreach my $pixel (@$line) {
        my ($red, $green, $blue) = unpack_rgb($pixel);
        no integer;

        # 明度を求める。(0~255)
        $pixel = $red * 0.299 + $green * 0.587 + $blue * 0.114;

        # ランダムな閾値で白か黒に。
        $pixel = $pixel > rand() * 255 ? 1 : 0;
    }
}

# カラーテーブルを定義。0 = 黒、1 = 白。
my @colors = (0x00000000, 0x00ffffff);

# 白黒の BMP を書き出す。
write_bmp($data, 1, \@colors);


さて、白黒 2 値化だけで何日かやってきたが、
これらの考え方は減色処理の基本となる。

また、例示したコードは最適化の余地が十分残されている。
例えば、昨日の誤差分散のコードでは、
差分値を切り捨てているので、
積み重なる端数が無視される結果となっている。
それを修正すれば、若干品質が上がる可能性はある。

今回は Perl を使っているため、
処理速度的には他の言語に劣るが、
基本的な考え方が分かれば、他の言語で表現するのは
それほど難しくはないはずだ。

また、2 値化には他にも色々な方法があるので、
ぜひともそれらを試してみてほしい。
例えば、Jarvis-Judice-Ninke 法というのも、
なかなか有名な配列である。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.