• 2. ostu自适应二值化


    Otsu算法原理:
    对于图像 I(x,y),前景(即目标)和背景的分割阈值记作 T,属于前景的像素点数占整幅图像的比例记为 ω0,平均灰度为 μ0;背景像素点数占整幅图像的比例为 ω1,平均灰度为 μ1;整幅图像的平均灰度记为μ,类间方差记为g。
    假设图像大小为M×N,图像中像素的灰度值小于阈值 T 的像素个数为 N0,像素灰度大于阈值T的像素个数为 N1,那么:
          ω0=N0/ M×N                      (1)
          ω1=N1/ M×N                      (2)
          N0+N1=M×N                      (3)
          ω0+ω1=1                    (4)
          μ=ω0*μ0+ω1*μ1                 (5)
          g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)
          g=ω0ω1(μ0-μ1)^2         (7) 

    特别说明:

    【1】实现过程中构造了三个容器,s[i] 表示像素值小于 i 的像素个数;m[i] 表示像素值小于 i 的平均像素;p[i] 表示像素值小于 i 的 m[i] *i 的所有值;

    【2】我本想利用中值法来确定最佳的分割点,但没有很好的思路。当前使用的是遍历法来求值。

    代码如下:

    #include "opencv.h"
    
    //大津展之算法
    void otsu(cv::Mat& src, cv::Mat& dst)
    {
        if (src.empty()) { cout << "Source image is empty ..." << endl; return; }
        cv::resize(src, dst, cv::Size(src.cols, src.rows));
        vector<int> s(256, 0);//积分 像素个数
        vector<int> m(256, 0);//存储前n个像素均值
        vector<long> p(256, 0);//积分 像素*个数
    
        for (int i = 0; i < src.rows; i++)
        {
            uchar* temp = src.ptr<uchar>(i);
            for (int j = 0; j < src.cols; j++)
                s[temp[j]]++;
        }
    
        for (int i = 1; i < 256; i++)
        {
            s[i] += s[i - 1];
            p[i] = p[i - 1] + s[i] * i;
            m[i] = p[i] / s[i];
        }
    
        int result = 0; int t;
        for (int i = 0; i < 256; i++)
        {
            float w0 = 1.0*s[i] / s[255];
            float w1 = 1 - w0;
            float u0 = m[i];
            float u1 = p[255] / s[i] - m[i];
            if (result < (int)(w0*w1*(u1 - u0)*(u1 - u0)))
            {
                result = (int)(w0*w1*(u1 - u0)*(u1 - u0));
                t = i;
            }
        }
    
        for (int i = 0; i < dst.rows; i++)
        {
            uchar* temp = dst.ptr<uchar>(i);
            for (int j = 0; j < dst.cols; j++)
                temp[j] = temp[j] < t ? 0 : 255;
        }
    }
    
    int main()
    {
        string filename = "autum.jpg";
        cv::Mat src, dst;
        src = cv::imread(filename);
        cv::cvtColor(src, src, cv::COLOR_RGB2GRAY);
        otsu(src, dst);
    
        cv::namedWindow("img", 0);
        cv::imshow("img", src);
        cv::namedWindow("otsu", 0);
        cv::imshow("otsu", dst);
    
        cv::waitKey();
        return  0;
    }
  • 相关阅读:
    Enumerable.Distinct方法去重
    datatable使用lambda
    jQuery获取单选框(复选框)选中的状态
    从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
    SQL Server 中WITH (NOLOCK)浅析
    C#将int型数字转换成3位字符串,不足的时候,前面补0
    window.locatin.href 中特殊字符串问题
    windows下git bash不显示中文问题解决
    python获取文件行数
    自定义异常以及触发异常
  • 原文地址:https://www.cnblogs.com/2Bthebest1/p/11018135.html
Copyright © 2020-2023  润新知