script day.log

大学生がなんとなく始めた、趣味やら生活のことを記録していく。

ヒストグラム伸張化について

まずは濃度ヒストグラムを作成するところから始めましょう。
こんな感じで画像の濃度値でヒストグラムをインクリメントする。

for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            histgram[image[i][j]]++;
        }
}

作成した濃度ヒストグラムを表示しますが、何度も同じコマンドを叩くのも面倒なので、
シェルスクリプトを作成して、stdlib.hをincludeして、systemを使って、実行しましょう。

#include <stdlib.h>
int main(){
//省略
system("zsh hoge.sh");
return 0;

シェルスクリプトの作成例(濃度ヒストグラムのデータ:plot.dat)

#!/bin/sh
gnuplot  <<- EOF
set style fill solid border lc rgb "black"
set terminal png
set title "Histgram"
set xlabel "value"
set ylabel "frequency"
set output "./histgram.png"
set xtic 0, 50, 255
plot "plot.dat" using 0:2 with boxes lw 2 lc rgb "light-cyan" notitle
EOF
display histgram.png &
exit 0

さあ、本題の伸張化です。
引き伸ばす範囲を決めるのですが、今回は0~255としました。
原画像の濃度値の範囲を求めましょう。

int lMin = 255;
    int lMax = 0;
    for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            histgram[image[i][j]]++;
            if (image[i][j] > lMax)
            {
                lMax = image[i][j];
            }
            if (image[i][j] < lMin)
            {
                lMin = image[i][j];
            }
        }
}

そして、伸張化を行います。
濃度値の変換には以下の式を使います。
\hat{z} = \frac{MAX - MIN}{max - min}(z - min) + MIN
MAX,MIN:伸張化の範囲\\
max,min:原画像の濃度値の範囲\\
z:変換前の濃度値\\
\hat{z}:変換後の濃度値

作成したcプログラム(一部抜粋).

    for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            int d = (float)(MAX - MIN) / (float)(lMax - lMin) * (int)(image[i][j] - lMin);
            if (d > 255)
            {
                image_w[i][j] = 255;
            }
            else if (d < 0)
            {
                image_w[i][j] = 0;
            }
            else
            {
                image_w[i][j] = (unsigned char)d;
            }
        }
}

実行後、濃度ヒストグラムが全体的に広がっていたので、
原画像と比べて少し明るくなりました。

[プログラム全文は以下より(ex2-*を参考)]
github.com