zoukankan      html  css  js  c++  java
  • 阈值分割-Otsu法

     算法实现(不调用函数)

    #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;

    }

  • 相关阅读:
    spring reference
    Connector for Python
    LDAP
    REST
    java利用泛型实现不同类型可变参数
    java细节知识
    事务隔离的级别
    servlet cdi注入
    session and cookie简析
    CORS’s source, principle and implementation
  • 原文地址:https://www.cnblogs.com/loyolh/p/10105423.html
Copyright © 2011-2022 走看看