OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104833663
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)

OpenCV开发专栏(点击传送门)

上一篇:《OpenCV开发笔记(二十九):带你学习图像识别之自适应阈值》

下一篇:《OpenCV开发笔记(三十一):红胖子8分钟带你深入了解双阈值化(图文并貌+浅显易懂+程序源码)》

 

前言

      本篇继续讲解阈值化,本篇章有点特殊是需要手码算法的OTSU阈值化。

 

Demo

      (注意:左上为原图,右上为灰度图,左下角为threshold做otsu算法阈值化,中下为代码的otsu算法,右下为threshold做三角形算法)

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第1张图片

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第2张图片

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第3张图片

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第4张图片

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第5张图片

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第6张图片

 

OTSU阈值化

概述

      OTSU是经典常用的阈值化算法,是由日本学者OTSU1979年提出的一种对图像进行二值化的高效算法,是一种自适应的阈值确定的方法,又称大津阈值分割法,是最小二乘法意义下的最优分割是一种寻找图像阈值的最大类间方差的算法。

      OTSU算法的具体步骤如下:

  • 步骤一:计算灰度级中每个像素在整幅图像中的个数;
  • 步骤二:计算每个像素在整幅图像的概率分布;
  • 步骤三:对灰度级进行遍历搜索,计算当前灰度值下前景背景类间概率;
  • 步骤四:通过目标函数计算出类内与类间方差下对应的阈值。

阈值化函数原型

double threshold( InputArray src,
               OutputArray dst,
               double thresh,
               double maxval,
               int type );
  • 参数一:InputArray类型,一般是cv::Mat,且可以处理多通道,8或者32位浮点(注意:当使用THRESH_BINARY处理多通道的时候,每个通道都会进行阈值化,比如RGB三通道,那么可能R比G,B大,当阈值设置为大于G、B小于R时,则R为最大是,显示红色,其他类型的阈值形式类推)。
  • 参数二;OutputArray类型,输出的目标图像,需要和原图片有一样的尺寸和类型。
  • 参数三:double类型的thresh,阈值。
  • 参数四:double类型的maxval,与“THRESH_BINARY”枚举和“THRESH_BINARY_INV”枚举一起使用才有效果,其他枚举忽略。
  • 参数五:int类型的type,阈值类型。

OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化_第7张图片

 

Demo源码

void OpenCVManager::testOtsu()
{
    QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
    cv::Mat srcMat = cv::imread(fileName1.toStdString());

    int width = 300;
    int height = 200;
    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    if(!srcMat.data)
    {
        qDebug() << __FILE__ << __LINE__
                 << "Failed to load image:" << fileName1;
        return;
    }

    // 灰度化图像
    cv::Mat grayMat;
    cv::cvtColor(srcMat, grayMat, cv::COLOR_BGR2GRAY);

    // 传入otsm算法获取计算的阈值
    int thresh = otsuAlgorithm(grayMat);
    qDebug() << __FILE__ << __LINE__ <(row, col)]++;
#if 0
            // 整数行设置成白色
            if(row % 10 == 0)
            {
                srcMat.at(row, col) = 255;
            }
            // 整数列设置成黑色
            if(col % 10 == 0)
            {
                srcMat.at(row, col) = 0;
            }
#endif
        }
    }
    // 步骤二:计算每个像素在整幅图像的概率分布;
    int pixSum =  srcMat.rows * srcMat.cols;
    for(int index = 0; index < 256; index++)
    {
        grayPro[index] = (float)grayScale[index] / pixSum;
    }
    // 步骤三:便利所有灰度级的阈值分割条件,测试哪一个的类间方差最大
    // 注意:方差公式 g = w0 * w1 * (u1 - u2)^2
    double deltaMax = 0;
    double w0 = 0.0f;
    double w1 = 0.0f;
    double u0 = 0.0f;
    double u1 = 0.0f;
    double u0Temp = 0.0f;
    double u1Temp = 0.0f;
    double deltaTemp = 0.0f;
    for(int i = 0; i < 256; i++)
    {
        w0 = 0.0f;
        w1 = 0.0f;
        u0 = 0.0f;
        u1 = 0.0f;
        u0Temp = 0.0f;
        u1Temp = 0.0f;
        deltaTemp = 0.0f;
        // 步骤三:对灰度级进行遍历搜索,计算当前灰度值下前景背景类间概率;
        for(int j = 0; j < 256; j++)
        {
            // 背景
            if(j <= i)
            {
                w0 += grayPro[j];
                u0Temp += j * grayPro[j];
            }else   // 前景
            {
                w1 += grayPro[j];
                u1Temp += j * grayPro[j];
            }
        }
        u0 = u0Temp / w0;
        u1 = u1Temp / w1;
        // 方差公式 g = w0 * w1 * (u1 - u2)^2
        deltaTemp = (float)(w0 * w1 * pow((u0 - u1), 2));
        qDebug() << __FILE__ <<__LINE__
                 << w0  << w1 << u0  << u1;
        // 步骤四:通过目标函数计算出类内与类间方差下对应的阈值。
        if(deltaTemp > deltaMax)
        {
            deltaMax = deltaTemp;
            threshold = i;
        }
    }
    return threshold;
}

 

工程模板:对应版本号v1.25.0

      对应版本号v1.25.0

 

上一篇:《OpenCV开发笔记(二十九):带你学习图像识别之自适应阈值》

下一篇:《OpenCV开发笔记(三十一):红胖子8分钟带你深入了解双阈值化(图文并貌+浅显易懂+程序源码)》

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104833663

你可能感兴趣的:(#,OpenCV,图形图像处理)