自适应阈值大津法(OTSU)介绍及代码实现

2024-08-27 00:32

本文主要是介绍自适应阈值大津法(OTSU)介绍及代码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://blog.csdn.net/a153375250/article/details/50970104

算法原理
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定法,又叫大津法,简称OTSU。

我用最简单的方式解释一下算法原理:

这个算法的思想就是假设阈值T将图像分成了前景和背景两个部分。

求出这两个部分的类间方差:

前景像素个数占比x(前景平均灰度 - 全图平均灰度)2 + 背景像素个数占比x(背景平均灰度 - 全图平均灰度)2

将阈值从0~255遍历一次,使上述类间方差最大的阈值T即为所求。

类间方差计算
我们接下来将算法原理中的类间方差化简为一个比较简单的形式,下面的过程也是代码实现的过程。

定义变量:

总像素数:N
前景像素数:fN
背景像素数:bN
前景像素灰度和:fSum
背景像素灰度和:bSum
前景像素平均灰度:fu
背景像素平均灰度:bu
图像总灰度值:Sum
图像平均灰度:u
前景像素占比:fw
背景图像占比:bw
类间方差:g
1
2
3
4
5
6
7
8
9
10
11
12
前景、背景占比:

前景像素占比:fw = fN/N
背景像素占比:bw = bN/N
1
2
前景、背景占比满足:

fw + bw =1  (1)
1
图片平均灰度值:

图片灰度直方图 : Histogram[256]
图片总灰度值 Sum : for(i=0; i<N; i++){ Sum += Histogram[i];}
图片平均灰度值 u : Sum/N
1
2
3
阈值为T时前景平均灰度:

阈值为T时前景像素数 fN : for(i=0; i<=T; i ++) { fN += Histogram[i];}
阈值为T时前景像素灰度和 fSum : for(i=0; i<=T; i++) { fSum += Histogram[i]*i;}
阈值为T时前景平均灰度 fu : fSum/fN
1
2
3
阈值为T时背景平均灰度:

阈值为T时背景像素数 bN : N-fN
阈值为T时背景像素灰度和 bSum : Sum-fSum
阈值为T时背景平均灰度 bu : bSum/bN    
1
2
3
平均灰度满足:

u = fu*fw + bu*bw  (2)
1
类间方差:

类间方差 g:fw*(fu-u)^2+bw*(bu-u)^2  (3)
1
将(1)(2)带入(3)式:

g = bw*fw*(fu-bu)^2
1
代码实现
假设读入图片为单通道Mat型灰度图,我们可以用以下代码实现:

#include <opencv2/opencv.hpp>  
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>

using namespace std;
using namespace cv;

Mat otsuGray(const Mat src) {
    Mat img = src;
    int c = img.cols; //图像列数
    int r = img.rows; //图像行数
    int T = 0; //阈值
    uchar* data = img.data; //数据指针
    int ftNum = 0; //前景像素个数
    int bgNum = 0; //背景像素个数
    int N = c*r; //总像素个数
    int ftSum = 0; //前景总灰度值
    int bgSum = 0; //背景总灰度值
    int graySum = 0;
    double w0 = 0; //前景像素个数占比
    double w1 = 0; //背景像素个数占比
    double u0 = 0; //前景平均灰度
    double u1 = 0; //背景平均灰度
    double Histogram[256] = {0}; //灰度直方图
    double temp = 0; //临时类间方差
    double g = 0; //类间方差

    //灰度直方图
    for(int i = 0; i < r ; i ++) {
        for(int j = 0; j <c; j ++) {
            Histogram[img.at<uchar>(i,j)]++;
        }
    }
    //求总灰度值
    for(int i = 0; i < 256; i ++) {
        graySum += Histogram[i]*i;
    }

    for(int i = 0; i < 256; i ++) {
        ftNum += Histogram[i];  //阈值为i时前景个数
        bgNum = N - ftNum;      //阈值为i时背景个数
        w0 = (double)ftNum/N; //前景像素占总数比
        w1 = (double)bgNum/N; //背景像素占总数比
        if(ftNum == 0) continue;
        if(bgNum == 0) break;
        //前景平均灰度
        ftSum += i*Histogram[i];
        u0 = ftSum/ftNum;

        //背景平均灰度
        bgSum = graySum - ftSum;
        u1 = bgSum/bgNum;

        g = w0*w1*(u0-u1)*(u0-u1);
        if(g > temp) {
            temp = g;
            T = i;
        }
    }

    for(int i=0; i<img.rows; i++)
    {
        for(int j=0; j<img.cols; j++)
        {
            if((int)img.at<uchar>(i,j)>T)
                img.at<uchar>(i,j) = 255;
            else
                img.at<uchar>(i,j) = 0;
        }
    }
    return img;
}
--------------------- 
作者:Easy-Sir 
来源:CSDN 
原文:https://blog.csdn.net/a153375250/article/details/50970104 
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇关于自适应阈值大津法(OTSU)介绍及代码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1110119

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin