# 单阈值大津法

## 单阈值大津法

``````w0=N0/(M×N)
w1=N1/(M×N)
μ=w0×μ0+w1×μ1
g=w0×(μ0-μ)^2+w1×(μ1-μ)^2    ``````

``````#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2\imgproc\types_c.h>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

double Otsu(Mat& image)
{
int threshold = 0;
double maxVariance = 0;
double w0 = 0, w1 = 0;//前景与背景像素点所占比例
double u0 = 0, u1 = 0;//前景与背景像素值平均灰度
int histogram[256] = { 0 }; //定义一个数组 长度为256  0-255
int Num = image.cols * image.rows;  //总像素个数
//统计256个bin，每个bin像素的个数
for (int i = 0; i < image.rows; i++)
{
const uchar* p = image.ptr<uchar>(i);
for (int j = 0; j < image.cols; j++)
{
histogram[int(*p++)]++; //cout<<"Histogram[data[i*image.step+j]]++:;"<<histogram[int(*p++)]++<<endl;
}
//*p++,  *和++优先级是相同的 先解引用取出指针指向的值，
//然后再将指针地址加1，指向下一个位置。也就是取值为 *p   但是这时候指针已经指向下一个位置
}
//前景像素统计
for (int i = 1; i < 256; i++)
{
w0 = 0;    //前景像素所占比例
w1 = 0;    //背景像素所占比例
u0 = 0;    //前景像素灰度均值
u1 = 0;    //背景像素灰度均值
for (int j = 1; j <= i; j++)
{
w0 = w0 + histogram[j];//以i为阈值，统计前景像素比例
u0 = u0 + j * histogram[j];//以i为阈值，统计前景像素灰度总和
}
u0 = u0 / w0; w0 = w0 / Num;    //Num是总像素个数

//背景像素统计
for (int j = i + 1; j <= 255; j++)
{
w1 = w1 + histogram[j];//以i为阈值，统计前景像素个数
u1 = u1 + j * histogram[j];//以i为阈值，统计前景像素灰度总和  histogram[j]是像素值为j的像素个数
}
u1 = u1 / w1; w1 = w1 / Num;
// 前面的u1是总灰度和  除以w1总个数是前景的灰度均值
// 前面的w1是总个数 除以Num以后才是比例
double variance = w0 * w1 * (u1 - u0) * (u1 - u0); //当前类间方差计算
if (variance > maxVariance)
{
maxVariance = variance;
threshold = i;
}
}
cout << "threshold:" << threshold << endl;
return threshold;
}

int main()
{
imshow("原图", img);

Mat img1;
img.copyTo(img1);
cvtColor(img, img, CV_BGR2GRAY);   // 把img转为灰度图
cvtColor(img1, img1, CV_BGR2GRAY); //把img1转为灰度图
double th = Otsu(img);   //调用Otsu函数 得到阈值th
cout << "The return value of getOstu is: " << th << endl;   //输出阈值th
cout << "The return value of opencv threshold is: " << threshold(img1, img1, th, 255, CV_THRESH_OTSU);//opencv已实现的大津法

for (int i = 0; i < img.rows; i++)  //行循环
{
uchar* data = img.ptr<uchar>(i);  //获取第i行的首地址
for (int j = 0; j < img.cols; j++)   //列循环
{
if (data[j] <= th)
data[j] = 0;
else
data[j] = 255;
}  //行处理结束
}

imshow("Ostu_img", img);
//cv::namedWindow("Opencv_img", CV_WINDOW_NORMAL);
cv::imshow("Opencv_img", img1);
//对一次大津法 的黑色或者白色部分进行掩膜
//bitwise_not(img1, img1); //这里先变反转颜色
src.setTo(0,img1);
imshow("掩膜", src);*/
waitKey(0);
return 0;
}
``````

（威少的黑白图还有点像利拉德）

1 声望1 粉丝

0 条评论