Otsu算法原理及实现

article/2025/8/18 23:08:37

在图像处理中Otsu方法,是以 Nobuyuki otsu 的名字命名的(日本人,大津展之),常用于基于图像分割的聚类。该算法的理论依据是:假定图像包含两类像素(前景像素和背景像素)直方图为双峰直方图,然后计算使得两类像素能分开的最佳阈值(类内方差),或等价的间类间方差最大。

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) 
采用遍历的方法使得类间方差g最大的阈值T,即为所求。Ostu方法可以形象地理解为:求取直方图有两个峰值的图像中那两个峰值之间的低谷值 T

Otsu算法实现:

matlab函数:

matlab中有现成的函数实现,函数名为: graythresh, 该函数便是用Ostu方法求分割阈值T。用法如下:

imgScr=imread('..');
T = graythresh(imgScr);
BW = im2bw(imgScr,T);

我这里po下源码,方便理解:

function [level em] = graythresh(I)
%GRAYTHRESH Global image threshold using Otsu's method.
%   LEVEL = GRAYTHRESH(I) computes a global threshold (LEVEL) that can be
%   used to convert an intensity image to a binary image with IM2BW. LEVEL
%   is a normalized intensity value that lies in the range [0, 1].
%   GRAYTHRESH uses Otsu's method, which chooses the threshold to minimize
%   the intraclass variance of the thresholded black and white pixels.
%
%   [LEVEL EM] = GRAYTHRESH(I) returns effectiveness metric, EM, as the
%   second output argument. It indicates the effectiveness of thresholding
%   of the input image and it is in the range [0, 1]. The lower bound is
%   attainable only by images having a single gray level, and the upper
%   bound is attainable only by two-valued images.
%
%   Class Support
%   -------------
%   The input image I can be uint8, uint16, int16, single, or double, and it
%   must be nonsparse.  LEVEL and EM are double scalars. 
%
%   Example
%   -------
%       I = imread('coins.png');
%       level = graythresh(I);
%       BW = im2bw(I,level);
%       figure, imshow(BW)
%
narginchk(1,1);
validateattributes(I,{'uint8','uint16','double','single','int16'},{'nonsparse'}, ...mfilename,'I',1);if ~isempty(I)% Convert all N-D arrays into a single column.  Convert to uint8 for% fastest histogram computation.I = im2uint8(I(:));num_bins = 256;counts = imhist(I,num_bins);% Variables names are chosen to be similar to the formulas in% the Otsu paper.p = counts / sum(counts);omega = cumsum(p);mu = cumsum(p .* (1:num_bins)');mu_t = mu(end);sigma_b_squared = (mu_t * omega - mu).^2 ./ (omega .* (1 - omega));% Find the location of the maximum value of sigma_b_squared.% The maximum may extend over several bins, so average together the% locations.  If maxval is NaN, meaning that sigma_b_squared is all NaN,% then return 0.maxval = max(sigma_b_squared);isfinite_maxval = isfinite(maxval);if isfinite_maxvalidx = mean(find(sigma_b_squared == maxval));% Normalize the threshold to the range [0, 1].level = (idx - 1) / (num_bins - 1);elselevel = 0.0;end
elselevel = 0.0;isfinite_maxval = false;
end% compute the effectiveness metric
if nargout > 1if isfinite_maxvalem = maxval/(sum(p.*((1:num_bins).^2)') - mu_t^2);elseem = 0;end
end
我试了两幅图像,效果如下:



opencv函数实现:

po下opencv的源码:

    getThreshVal_Otsu_8u( const Mat& _src )  {  Size size = _src.size();  if( _src.isContinuous() )  {  size.width *= size.height;  size.height = 1;  }  const int N = 256;  int i, j, h[N] = {0};  for( i = 0; i < size.height; i++ )  {  const uchar* src = _src.data + _src.step*i;  j = 0;  #if CV_ENABLE_UNROLLED  for( ; j <= size.width - 4; j += 4 )  {  int v0 = src[j], v1 = src[j+1];  h[v0]++; h[v1]++;  v0 = src[j+2]; v1 = src[j+3];  h[v0]++; h[v1]++;  }  #endif  for( ; j < size.width; j++ )  h[src[j]]++;  }  double mu = 0, scale = 1./(size.width*size.height);  for( i = 0; i < N; i++ )  mu += i*(double)h[i];  mu *= scale;  double mu1 = 0, q1 = 0;  double max_sigma = 0, max_val = 0;  for( i = 0; i < N; i++ )  {  double p_i, q2, mu2, sigma;  p_i = h[i]*scale;  mu1 *= q1;  q1 += p_i;  q2 = 1. - q1;  if( std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. - FLT_EPSILON )  continue;  mu1 = (mu1 + i*p_i)/q1;  mu2 = (mu - q1*mu1)/q2;  sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);  if( sigma > max_sigma )  {  max_sigma = sigma;  max_val = i;  }  }  return max_val;  }  
上面的应该是opencv 2以后的版本,之前的版本更好理解一些,这里也po一下,

int otsuThreshold(IplImage *frame)
{const int GrayScale = 256;int width = frame->width;int height = frame->height;int pixelCount[GrayScale];float pixelPro[GrayScale];int i, j, pixelSum = width * height, threshold = 0;uchar* data = (uchar*)frame->imageData;for (i = 0; i < GrayScale; i++){pixelCount[i] = 0;pixelPro[i] = 0;}//统计灰度级中每个像素在整幅图像中的个数  for (i = 0; i < height; i++){for (j = 0; j < width; j++){pixelCount[(int)data[i * width + j]]++; }}//计算每个像素在整幅图像中的比例  float maxPro = 0.0;int kk = 0;for (i = 0; i < GrayScale; i++){pixelPro[i] = (float)pixelCount[i] / pixelSum;if (pixelPro[i] > maxPro){maxPro = pixelPro[i];kk = i;}}//遍历灰度级[0,255], i作为阈值  float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;for (i = 0; i < GrayScale; i++)    {w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;for (j = 0; j < GrayScale; j++){if (j <= i)   //背景部分  {w0 += pixelPro[j];u0tmp += j * pixelPro[j];}else        //前景部分  {w1 += pixelPro[j];u1tmp += j * pixelPro[j];}}u0 = u0tmp / w0;u1 = u1tmp / w1;u = u0tmp + u1tmp;deltaTmp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);if (deltaTmp > deltaMax){deltaMax = deltaTmp;threshold = i;}}return threshold;
}

参考:

https://en.wikipedia.org/wiki/Otsu%27s_method

http://www.cnblogs.com/ranjiewen/p/6385564.html

http://blog.csdn.net/glouds/article/details/38976573


http://chatgpt.dhexx.cn/article/8vy0luk6.shtml

相关文章

10 Otsu 算法

文章目录 前言一、Otsu 是什么&#xff1f;二、算法实验1.使用第三方库2.不使用第三方库 前言 Otsu 是一种利用图像的灰度特征自动计算二值化阈值的方法&#xff0c;常被称为 Otsu 自动阈值法。 使用 Otsu 方法可以避免主观性和繁琐性的阈值选取操作&#xff0c;并能够在一定…

OTSU(最大类间方差法、大津算法)

OTSU是阈值分割中一种常用的算法&#xff0c;它可以根据图像自动生成最佳分割阈值。OTSU的核心思想是类间方差最大化。 import cv2 import numpy as np from matplotlib import pyplot as pltimage cv2.imread("2.bmp") gray cv2.cvtColor(image, cv2.COLOR_BGR2G…

Bootstrap模态框里 再弹模态框

Bootstrap模态框里 再弹模态框 后端代码点击编辑 按钮 将参数赋值隐藏 input 中 , 便于修改 获取对应id修改模态框详情模态框 后端代码 /*** 财务审核使用详情** param request* param id* return*/RequestMapping(params "getUseDatil")ResponseBodypublic JSONAr…

新增模态框

平时我们在VS中也常常会用到模态框&#xff0c;今天我们就来聊聊模态框&#xff0c;但是我要说的是新增模态框&#xff0c;而不是修改模态框喔。在书写模态框代码时&#xff0c;我们还要引用一个插件: 然后就可以进行对代码进行书写了。 我们先说说模态框插件的用法&#xff0c…

html模态框常见问题,模态框无法弹出的问题

问题起因&#xff1a; 昨晚写到了一个模态框&#xff0c;用到了bootstrap和jquery&#xff0c;依赖的js已经复制到项目中&#xff0c;并在Jsp页面上进行了引用&#xff0c;最初的引用如下&#xff1a; 问题描述&#xff1a; 模态框无法正常弹出&#xff0c;使用浏览器查看资源看…

Vue模态框的封装

一、模态框 1、模态框&#xff1a;若对话框不关闭&#xff0c;不能操作其父窗口 2、非模态框&#xff1a;对话框不关闭&#xff0c;可以操作其窗口 二、Vue组件实现模态框的功能 1、模态框是一个子组件 2、显示和隐藏由父组件决定 3、对话框的标题也是由父组件传递的 4、对话框…

Bootstrap之模态框

前言 模态框&#xff08;Modal&#xff09;是覆盖在父窗体上的子窗体。通常&#xff0c;目的是显示来自一个单独的源的内容&#xff0c;可以在不离开父窗体的情况下有一些互动。子窗体可提供信息、交互等。 用法 您可以切换模态框&#xff08;Modal&#xff09;插件的隐藏内…

php什么是模态框,bootstrap模态框有什么用

Bootstrap Modals(模态框)是使用定制的Jquery 插件创建的。 它可以用来创建模态窗口丰富用户体验&#xff0c;或者为用户添加实用功能。您可以在 Modals(模态框)中使用 Popover(弹出框)和 Tooltip(工具提示插件)。(推荐学习&#xff1a;Bootstrap视频教程) 将通过一些实例和解释…

弹出模态框

想必大家都知道弹出层的重要性&#xff0c;在很多的地方都能用到这个方法&#xff0c;所以说这种是非常的普遍的实用性&#xff0c;在大家编写过程中也是很常见的模态框以及弹出层&#xff0c;基本也是一个概念。 插件不可缺少 1.多窗口模式 层叠置顶 Esc 关闭 为什么是说多窗…

模态框动态赋值

模态框动态赋值&#xff0c;可以有多种方式&#xff1a;1、每次一个个填充&#xff1b;2、直接针对模态框中的ID赋值。。。 今天说下同事犯的错误&#xff0c;大家引以为鉴&#xff1a; 首先如图&#xff1a; 他在点击详情链接时&#xff0c;是能拿到相关参数的&#xff0c;进…

html 自定义模态框,自定义对话框、模态框

致敬iphoneX的小刘海....自定义模态框 body{ text-align: center; } #modalBg{ position: absolute; left: 0; top: 0; background-color: rgba(0,0,0,0.2); width: 100%; height: 100%; margin: auto; display: none; } #modal{ min-width: 30%; background-color: white; bor…

html怎么自动弹出模态框,纯CSS实现带点击模态框外部自动关闭的模态框

在网页中我们经常会用到模态框,一般会用于显示表单或者是提示信息。由于模态框涉及到页面上比较多的交互效果,最简单的交互就是打开以及关闭两个操作,而关闭又会涉及是否需要在打开状态下点击模态框外部能够关闭这样的功能,因为这些交互问题,所以一般都会首先考虑到使用Ja…

模态框拖拽

1、点击弹出层&#xff0c;回弹出模态框&#xff0c;并且显示半透明的遮挡层 2、点击关闭按钮&#xff0c;可以关闭模态框&#xff0c;并且同时关闭灰色半透明遮挡层 3、鼠标放到模态框最上面一行&#xff0c;可以按住鼠标拖拽模态框在页面中移动 4、鼠标松开&#xff0c;可…

模态框案例

模态框 模态框在很多网站是很常见的&#xff0c;比如网易云音乐登录&#xff0c;百度登录等网站。 网易云音乐如图&#xff1a; 让我们来看看代码吧&#xff01;&#xff01;注意&#xff1a;这里为了更好的演示效果&#xff0c;增加了遮挡层。 HTML部分&#xff1a; <!-- …

零基础Bootstrap入门教程(16)--模态框

点此查看 所有教程、项目、源码导航 本文目录 1. 概述2. 模态框样式3. 按钮直接关联模态框4. 通过JS方法打开/关闭模态框5. 调整大小6. 动画效果7. 小结 1. 概述 模态框这个名字有点高雅了&#xff0c;其实就是对话框&#xff0c;用来弹出一个新的界面。 模态框的使用非常的场…

模态框

模态对话框&#xff08;Modal Dialogue Box&#xff0c;又叫做模式对话框&#xff09;&#xff0c;是指在用户想要对对话框以外的应用程序进行操作时&#xff0c;必须首先对该对话框进行响应 摘自百度百科 先放上效果图&#xff1a; 基本功能为点击窗口中间的发光按钮&#xff…

HTML+CSS+JavaScript实现模态框(可拖拽)

前言 模态框是指覆盖在父窗口上的子窗口&#xff0c;但在HTML网页中&#xff0c;并没有父窗口和子窗口的概念。这里是通过可隐藏的遮罩层和一个可隐藏的盒子来实现模态框的效果。 效果演示&#xff1a; 下面开始详细介绍如何实现一个可拖拽的模态框。只对 JS 部分详解&#x…

Bootstrap系列之模态框(Modal)

文章の目录 1、工作原理2、示例2.1、Modal组件2.2、在线演示2.3、静态背景2.4、滚动内容2.5、垂直居中2.6、提示和弹窗2.7、使用网格2.8、不同模态框的内容2.9、改变动画2.10、移除动画2.11、动态高度2.12、Accessibility2.13、嵌入YouTube视频 3、Optional sizes4、用法4.1、通…

Oracle数据迁移

本文主要提及使用exp,imp以及Oracle数据泵等工具如何进行数据迁移&#xff1a; 一、数据迁移工具 1、数据迁移工具 &#xff08;1&#xff09;数据泵 &#xff08;2&#xff09;外部表&#xff1a;external table &#xff08;3&#xff09;数据加载工具&#xff1a;sqllo…

MySQL数据库- 几种数据迁移的方法详解都在这了!看完必懂

数据迁移的几种方式 - MySQL数据库 本文关键字&#xff1a;MySQL、数据库、数据迁移、导入、导出 文章目录 数据迁移的几种方式 - MySQL数据库 一、数据迁移 1. 数据的生命周期2. 数据迁移的发生二、数据导出 1. 命令方式2. 软件方式三、数据导入 1. 命令方式2. 软件方式四、…