1、描述:
该算法和基于谷底最小值的阈值方法类似,只是最后一步不是取得双峰之间的谷底值,而是取双峰的平均值作为阈值。
2、参考代码:
{ int Y, Iter = 0, Index; double* HistGramC = new double[256]; // 基于精度问题,一定要用浮点数来处理,否则得不到正确的结果 double* HistGramCC = new double[256]; // 求均值的过程会破坏前面的数据,因此需要两份数据 for (Y = 0; Y < 256; Y++) { HistGramC[Y] = HistGram[Y]; HistGramCC[Y] = HistGram[Y]; } // 通过三点求均值来平滑直方图 while (IsDimodal(HistGramCC) == false) // 判断是否已经是双峰的图像了 { HistGramCC[0] = (HistGramC[0] + HistGramC[0] + HistGramC[1]) / 3; // 第一点 for (Y = 1; Y < 255; Y++) HistGramCC[Y] = (HistGramC[Y - 1] + HistGramC[Y] + HistGramC[Y + 1]) / 3; // 中间的点 HistGramCC[255] = (HistGramC[254] + HistGramC[255] + HistGramC[255]) / 3; // 最后一点 memcpy(HistGramCC, HistGramC, 256 * sizeof(double)); // 备份数据,为下一次迭代做准备 Iter++; if (Iter >= 10000) return -1; // 似乎直方图无法平滑为双峰的,返回错误代码 } // 阈值为两峰值的平均值 int* Peak = new int[2]; for (Y = 1, Index = 0; Y < 255; Y++) if (HistGramCC[Y - 1] < HistGramCC[Y] && HistGramCC[Y + 1] < HistGramCC[Y]) Peak[Index++] = Y - 1; return ((Peak[0] + Peak[1]) / 2); }
bool IsDimodal(double* HistGram) // 检测直方图是否为双峰的 { // 对直方图的峰进行计数,只有峰数位2才为双峰 int Count = 0; for (int Y = 1; Y < 255; Y++) { if (HistGram[Y - 1] < HistGram[Y] && HistGram[Y + 1] < HistGram[Y]) { Count++; if (Count > 2) return false; } } if (Count == 2) return true; else return false; }