大津の方法による閾値の計算
判別分別法を用いた大津の方法によって、二値化処理を行うための閾値を求めてみます。
あまり詳しくありませんが、閾値を求める方法の中でもこれが一番ポピュラーな方法らしいです。
大津の方法に関してはこのサイトを参考にしました。
以前と同じように、画像はグレー画像であらかじめ二次元配列imageに読み込まれているものとします。
void DiscriminantAnalysis(void) { int histgram[256] = {0};//ヒストグラム int sum = 0; int max_no; long data = 0; double average, average1, average2; double max = 0.0; int count1, count2; double breakup1, breakup2; double class1, class2; double tmp; for(int i=0;i<y_size;i++){ //y_sizeは画像の縦幅 for(int j=0;j<x_size;j++){ //x_sizeは画像の横幅 /*各画素値が画像中にどれくらいあるのか算出する*/ histgram[image[i][j]]++; sum += image[i][j]; } } average = sum / (x_size * y_size); for(int i=0;i<256;i++){ count1 = count2 = 0; data = 0; breakup1 = breakup2 = 0.0; tmp = 0; for(int j=0;j<i;j++){ count1 += histgram[j]; data += histgram[j] * j; } /*クラス1の平均*/ /*平均 =(データの総和 / 個数)*/ if(count1 != 0){ average1 = (double)data / (double)count1; /*分散*/ /*分散=(データ - 平均値)^2の総和/個数 */ for(int j=0;j<i;j++){ breakup1 += pow( (j- average1), 2 ) * histgram[j]; } breakup1 /= (double)count1; } data = 0; for(int j=i;j<256;j++){ count2 += histgram[j]; data += histgram[j] * j; } if(count2 != 0){ average2 = (double)data / (double)count2; for(int j=i;j<256;j++){ breakup2 += pow( (j - average2), 2 ) * histgram[j]; } breakup2 /= (double)count2; } /*クラス内分散*/ class1 = (count1 * breakup1 + count2 * breakup2); /*クラス間分散*/ class2 = count1 * pow( (average1 - average), 2 ) + count2 * pow( (average2 - average), 2 ); tmp = class2 / class1; if(max < tmp){ max = tmp; max_no = i; } } printf("閾値 = %d\n",max_no); }