0


【OpenCv • c++】 大津法(OTSU)阈值处理

  • 🚀 个人简介:CSDN「博客新星」TOP 10 , C/C++ 领域新星创作者
  • 💟 作 者:锡兰_CC ❣️
  • 📝 专 栏:【OpenCV • c++】计算机视觉
  • 🌈 若有帮助,还请关注➕点赞➕收藏,不行的话我再努努力💪💪💪

文章目录

前言

通过上文的介绍,我们了解了三种图像,二值图像、灰度图像、彩色图像。三种图像的介绍。
在图像处理中,对于同样的操作,处理灰度图像的计算量要远远小于处理彩色图像,而二值图像(只含灰度值0或1)的计算量比前两者更小。因此,二值化操作在图像处理中有着很大的作用。

二值化图像的实现方法有很多。用的最多的方法是利用图像像素点分布规律,设置阈值进行像素点分割,从而得到二值化图像。

一、大津法(OTSU)阈值化

在阈值处理中,最常用的方法就是大津法,因为其计算简单,不受图像亮度和对比度的影响。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。

1.大津法算法步骤

1)计算图像的直方图,统计每个像素在整幅图像中的个数。

//统计灰度级中每个像素在整幅图像中的个数for(int i =0; i < nCols; i++){for(int j =0; j < nRows; j++){
            nSumPix[(int)Image.at<uchar>(i, j)]++;}}

2)计算每个像素在整幅图像中的占比

//计算每个灰度级占图像中的概率分布for(int i =0; i <256; i++){
        nProDis[i]=(float)nSumPix[i]/(nCols * nRows);}

3)对灰度值进行遍历,统计前景像素)所占整幅图像的比例,平均灰度,背景像素所占整幅图像的比例,背景像素的平均灰度。

//遍历灰度级[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{
                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));}

4)计算图像的全局阈值

//依次找到最大类间方差下的阈值if(delta_temp > delta_max){
            delta_max = delta_temp;
            threshold = i;}

2、代码演示

整体代码演示:

#include<stdio.h>#include<string>#include<opencv2/highgui/highgui.hpp>#include<opencv2/opencv.hpp>#include<opencv2/imgproc/types_c.h>usingnamespace cv;usingnamespace std;intOTSU(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 < nRows; i++){for(int j =0; j < nCols; 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;}intmain(){
    cv::Mat srcImage = cv::imread("...c.webp");if(!srcImage.data)return1;
    cv::Mat srcGray;
    cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
    cv::imshow("srcGray", srcGray);//利用 OTSU 二值化算法得到阈值int ostuThreshold =OTSU(srcGray);
    std::cout << ostuThreshold << 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++){if(srcGray.at<uchar>(i, j)> ostuThreshold){
                otsuResultImage.at<uchar>(i, j)=255;}else{
                otsuResultImage.at<uchar>(i, j)=0;}}}
    cv::imshow("otsuResultImage", otsuResultImage);
    cv::waitKey(0);return0;}

3、运行效果

PS: 处理的有点吓人

其他:

更多专栏订阅:

  • 👍 【开卷数据结构】
  • 💛 【备战蓝桥,冲击省一】
  • 💕 从零开始的 c++ 之旅
  • 💖 【OpenCV • c++】计算机视觉

本文转载自: https://blog.csdn.net/Ceylan__/article/details/129596742
版权归原作者 锡兰_CC 所有, 如有侵权,请联系我们删除。

“【OpenCv • c++】 大津法(OTSU)阈值处理”的评论:

还没有评论