在图像处理中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

Otsu算法原理及实现相关推荐

  1. otsu算法原理及C++代码实现-寻找灰度图片中最佳阈值

    otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰 ...

  2. 详细及易读懂的 大津法(OTSU)原理 和 算法实现

    OTSU算法原理简述: 最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出,是一种自适应的阈值确定方法.算法假设图像像素能够根据阈值,被分成背景[background]和目标[ ...

  3. OTSU算法对图像二值化

    出处:http://blog.csdn.net/WuHaibing_CVer OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法. 1. OTSU算法原理简介 对于一幅图 ...

  4. otsu阈值分割算法原理_大津二值化算法OTSU的理解

    otsu 大津算法介绍: OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法. 利用阈值将原图像分成前景,背景两个图象. 前景:用n1,csum,m1来表示在当前阈值下的 ...

  5. OTSU算法的原理介绍及C++和Python实现

    前言: 最近由于在做图像处理方面的工作,需要自己编写提取图像中对象边缘的算法,我目前所采用的事最简单的阈值分割算法,在此算法中最重要的一个参数就是用于分割前景和背景的阈值.刚开始做的时候阈值都是通过手 ...

  6. MATLAB--数字图像处理 Otsu算法(MATLAB原理验证)

    概念 OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法.(大津算法) Otsu原理 对于图像 t (x,y),前景(即目标)和背景的分割阈值记作 T,属于前景的像素点数 ...

  7. otsu阈值分割算法原理_OTSU_图像二值化分割阈值的算法

    简介: 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出.从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景 ...

  8. otsu阈值分割算法原理_大津法---OTSU算法

    简介: 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出.从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景 ...

  9. 二维Otsu算法的原理与实现

    1.简介: 一维Otsu算法有计算简洁.稳定.自适应强等优点,被广泛用于图像分割中.但一维Otsu算法没有考虑图像像素点之间的关系,当图像中有噪声时,会导致分割的效果不理想.因此,刘健庄等人在1993 ...

  10. C++实现otsu算法

    类间方差最大化阈值分割算法 (Otsu)可以自动计算图像二值化时的阈值,otsu的中心思想是阈值T应使目标与背景两类的类间方差最大.具体原理如下: otsu是按图像的灰度特性,将图像分成背景和目标两部 ...

最新文章

  1. 【工具篇】利用DBExportDoc V1.0 For MySQL自动生成数据库表结构文档(转
  2. java鼠标样式设置,设置Echarts鼠标悬浮样式
  3. Google 的 Java 编码规范,参考学习!
  4. 机器学习——文件的读取
  5. 完美实现类似QQ的自拍头像、上传头像功能!(Demo 源码)
  6. django上课笔记6-MVC,MTV架构-中间件-初识Form组件
  7. LPDDR4协议规范之 (六)刷新
  8. C# 绘制矩形方框读写内存类 cs1.6人物透视例子
  9. 基本共射放大电路的动态分析
  10. 家谱范例模板:一本完整的家谱,一定需要这几部分内容
  11. 3D游戏编程与设计作业五
  12. 如何用计算机画函数图像,用Excel绘制函数图像的技巧
  13. 如何缩减XFS分区格式的根目录
  14. License之外,社区的规则与潜规则
  15. OpenGL导入3DMax模型(.3DS)
  16. 安全狗“老用户推荐新用户”有奖活动进行中 最高IPhone 4S手机
  17. 立方体图片的在线绘制与制作
  18. 《SiamMask:Fast Online Object Tracking and Segmentation:A Unifying Approach》论文笔记
  19. 用户界面测试(来源于百度百科)
  20. 编译,发版,链接库问题

热门文章

  1. python del 函数
  2. eclipse设置Tomcat超级详细
  3. 多线程总结之旅(1):线程VS进程
  4. EditDistance,求两个字符串最小编辑距离,动态规划
  5. 如何打开chrome中flash debug player
  6. ZOJ 3511 Cake Robbery
  7. Java简历模板(三十个模板随意选)
  8. [C#] DBNull、Null和String.Empty的区别
  9. MySQL 随机获得一条数据的方法
  10. 链表最小结构(C++版本)