算法實現(不調用函數)
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//實現灰度直方圖的繪制
void drawpicture(Mat &inpicture, Mat &outpicture)
{
MatND hist;
const int bins = 256;
int hist_size[] = { bins };
float range[] = { 0, 256 };
const float* ranges[] = { range };
int channels[] = { 0 };
calcHist(&inpicture, 1, channels, Mat(), hist, 1, hist_size, ranges, true, false);
double maxnum;
minMaxLoc(hist, 0, &maxnum, 0, 0);
int scale = 1;
int histheight = 256;
for (int i = 0; i < bins; i++)
{
float binvalue = hist.at<float>(i);
int height = cvRound(binvalue*histheight / maxnum);
// 繪制長方形
rectangle(outpicture, Point(i*scale, histheight), Point((i + 1)*scale, histheight - height), Scalar(255));
namedWindow("windown", CV_WINDOW_NORMAL);
imshow("windown", outpicture);
}
}
int main()
{
//以灰度方式讀入圖片
Mat img = imread("F:\\work_three_grade\\DigitalImage\\d.jpg", IMREAD_GRAYSCALE);
double max = 0.0; //方差
int otsu = 0; //閾值
//得到像素點總個數
int h = img.rows;
int w = img.cols;
int num = h * w;
//聲明一個一維數組,用來記錄各像素級的個數
int m[256];
for (int i = 0; i < 256; i++)
{
m[i] = 0;
}
//Mat M(256, CV_8U, m);
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
int temp = img.at<uchar>(i, j);
m[temp]++;
}
}
//小於等於t的和大於t的像素出現的概率和平均灰度
int t;//將閾值從0-255依次遍歷,尋找結果最好的
double outcome[256];//存放閾值為i的類間方差
for (t = 0; t < 256; t++)
{
double w0=0.0;//小於等於t的像素出現的概率
double w1= 0.0;//大於t的像素出現的概率
double u0= 0.0;// 平均灰度
double u1= 0.0;// 平均灰度
double sum1 = 0.0;
double sum2 = 0.0;
for (int i = 0; i <= t; i++)
{
sum1 += m[i];
}
w0 = sum1 / num; //小於等於t的像素出現的概率,應該是double類型,后面再說
w1 = 1 - w0; //大於t的像素出現的概率,應該是double類型,后面再說
sum1 = 0;
for (int i = 0; i <= t; i++)
{
sum1 += i * m[i];
}
u0 = sum1 / num / w0;
for (int i = t + 1; i < 256; i++)
{
sum2 += i * m[i];
}
u1 = sum2 / num / w1;
//暫存結果
outcome[t] = w0 * w1*(u0 - u1)*(u0 - u1);
}
//求最大類間方差
for (int i = 0; i < 256; i++)
{
if (max < outcome[i])
{
max = outcome[i];
otsu = i;
}
}
//輸出原圖像
namedWindow("img",CV_WINDOW_NORMAL);
imshow("img", img);
//輸出灰度直方圖
Mat grayimg = Mat::zeros(256, 256, CV_8UC1);
std::string grayimgwin;
drawpicture(img, grayimg);
cout << "閾值: " << otsu << endl;
cout << "最大類間方差: " << max << endl;
waitKey();
return 0;
}