OTSU阈值化

被刻印的时光 ゝ 提交于 2019-12-06 08:44:18

OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。如下是C++实现opencv OTSU阈值化的代码(opencv版本是3.0):

头文件:

#include <stdio.h>

#include <string>

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/opencv.hpp"

using namespace std;

using namespace cv;

大津法函数:

int OTSU(cv::Mat srcImage)

{

    int nCols = srcImage.cols;

    int nRows = srcImage.rows;

    int threshold = 0;

    // 初始化统计参数

    int nSumPix[256];

    float nProDis[256];

    for (int i = 0; i < 256; i++)

    {

        nSumPix[i] = 0;

        nProDis[i] = 0;

    }

    // 统计灰度级中每个像素在整幅图像中的个数 

    for (int i = 0; i < nCols; i++)

    {

        for (int j = 0; j < nRows; j++)

        {

            nSumPix[(int)srcImage.at<uchar>(i, j)]++;

        }

    }

    // 计算每个灰度级占图像中的概率分布

    for (int i = 0; i < 256; i++)

    {

        nProDis[i] = (float)nSumPix[i] / (nCols * nRows);

    }

    // 遍历灰度级[0,255],计算出最大类间方差下的阈值  

    float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp;

    double delta_max = 0.0;

    for (int i = 0; i < 256; i++)

    {

        // 初始化相关参数

        w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;

        for (int j = 0; j < 256; j++)

        {

            //背景部分 

            if (j <= i)

            {

                // 当前i为分割阈值,第一类总的概率  

                w0 += nProDis[j];

                u0_temp += j * nProDis[j];

            }

            //前景部分   

            else

            {

                // 当前i为分割阈值,第一类总的概率

                w1 += nProDis[j];

                u1_temp += j * nProDis[j];

            }

        }

        // 分别计算各类的平均灰度 

        u0 = u0_temp / w0;

        u1 = u1_temp / w1;

        delta_temp = (float)(w0 *w1* pow((u0 - u1), 2));

        // 依次找到最大类间方差下的阈值    

        if (delta_temp > delta_max)

        {

            delta_max = delta_temp;

            threshold = i;

        }

    }

    return threshold;

}

调用大津法函数:

int main()

{

    // 图像读取及判断

    cv::Mat srcImage = cv::imread("SrcImage.jpg");

    if (!srcImage.data)

        return 1;

    // 灰度转换

    cv::Mat srcGray;

    cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);

    cv::imshow("srcGray", srcGray);

    // 调用OTSU二值化算法得到阈值

    int  ostuThreshold = OTSU(srcGray);

    std::cout << ostuThreshold << std::endl;

    // 定义输出结果图像

    cv::Mat otsuResultImage =

        cv::Mat::zeros(srcGray.rows, srcGray.cols, CV_8UC1);

    // 利用得到的阈值实现二值化操作

    for (int i = 0; i < srcGray.rows; i++)

    {

        for (int j = 0; j < srcGray.cols; j++)

        {

            // 满足大于阈值ostuThreshold置255

            if (srcGray.at<uchar>(i, j) > ostuThreshold)

                otsuResultImage.at<uchar>(i, j) = 255;

            else

                otsuResultImage.at<uchar>(i, j) = 0;

        }

    }

    cv::imshow("ResultImage", otsuResultImage);

    cv::waitKey(0);

    return 0;

}

运行结果:

人工智能之OpenCV高级视频教程:点击观看

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!