此方法适用于图像直方图呈现双峰形状。如下图。
方法设计:结果与th敏感。若图像直方图呈现多峰,判定不理想。
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
/***************
*img : 图像
*th : 设置预估阈值
*itertime : 迭代次数
********************/
int PeakSplit(Mat &img, int th, int itertime)
{
int hist[256] = {}; //直方图数据
for (int i = 0; i < img.rows; i++)
{
for (int j = 0; j < img.cols; j++)
{
hist[img.at<uchar>(i, j)]++;
}
}
int p1 = 0, p1_v = 0; //峰值坐标 和 峰值数值
int p2 = 255, p2_v = 0;
int pth = th;
while (itertime--)
{
for (int i = p1; i <= pth; i++)
{
if (hist[i] > p1_v)
{
p1_v = hist[i];
p1 = i;
}
}
for (int i = p2; i > pth; i--)
{
if (hist[i] > p2_v)
{
p2_v = hist[i];
p2 = i;
}
}
int tmp_th = (p1 + p2) / 2; //更新阈值为两个峰值坐标中心
if (pth == tmp_th)
break;
else
pth = tmp_th;
}
return pth;
}
void main()
{
Mat image = imread("1.jpg", IMREAD_GRAYSCALE);
int otsu_th = 0;
Mat dst;
otsu_th = threshold(image, dst, 0, 255, THRESH_OTSU);
cout << "otsu th >> " << otsu_th << endl;
int peak_th = 0;
peak_th = PeakSplit(image, 20, 10);
cout << "peak th >> " << peak_th << endl;
imshow("src", image);
waitKey();
}