在图像处理应用中二值化操作是一个很常用的处理方式,例如零器件图片的处理、文本图片和验证码图片中字符的提取、车牌识别中的字符分割,以及视频图像中的运动目标检测中的前景分割,等等。

较为常用的图像二值化方法有:1)全局固定阈值;2)局部自适应阈值;3)OTSU等。此篇讲述的是OTSU算法。

OTSU算法也称最大类间差法,有时也称之为大津算法,由大津于1979年提出,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

otsu使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别 来划分。  所以 可以在二值化的时候 采用otsu算法来自动选取阈值进行二值化。otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。因此,使类间方差最大的分割意味着错分概率最小。

使用otsu大津法实现直方图的单阈值分割,可用于图像的分割。大津是用最大类间方差来判读阈值的,也可以用最小类内方差判读,最大类间方差+最小类内方差=总方差

OPENCV的二值化操作中,有一种“大津阈值处理”的方法,使用函数cvThreshold(image,image2,0,255,CV_THRESH_OTSU) 实现,该函数就会使用大律法OTSU得到的全局自适应阈值来进行二值化图片,而参数中的threshold不再起作用。

设t为设定的阈值。

wo: 分开后  前景像素点数占图像的比例

uo:  分开后  前景像素点的平均灰度

w1:分开后  被景像素点数占图像的比例

u1:  分开后  被景像素点的平均灰度

u=w0*u0 + w1*u1 :图像总平均灰度

从L个灰度级遍历t,使得t为某个值的时候,前景和背景的方差最大, 则 这个 t  值便是我们要求得的阈值。

其中,方差的计算公式如下:

g=wo * (uo - u) * (uo - u) + w1 * (u1 - u) * (u1 - u)

[             此公式计算量较大,可以采用:      g = wo * w1 * (uo - u1) * (uo - u1)                ]

由于otsu算法是对图像的灰度级进行聚类,so  在执行otsu算法之前,需要计算该图像的灰度直方图。

【第一套代码】

  1. #include "stdafx.h"
  2. #include "stdio.h"
  3. #include "cv.h"
  4. #include "highgui.h"
  5. #include "Math.h"
  6. int Otsu(IplImage* src);
  7. int _tmain(int argc, _TCHAR* argv[])
  8. {
  9. IplImage* img = cvLoadImage("c:\\aSa.jpg",0);
  10. IplImage* dst = cvCreateImage(cvGetSize(img), 8, 1);
  11. int threshold = Otsu(img);
  12. cvThreshold(img, dst, threshold, 255, CV_THRESH_BINARY);
  13. cvNamedWindow( "img", 1 );
  14. cvShowImage("img", dst);
  15. cvWaitKey(-1);
  16. cvReleaseImage(&img);
  17. cvReleaseImage(&dst);
  18. cvDestroyWindow( "dst" );
  19. return 0;
  20. }
  21. int Otsu(IplImage* src)
  22. {
  23. int height=src->height;
  24. int width=src->width;
  25. long size = height * width;
  26. //histogram
  27. float histogram[256] = {0};
  28. for(int m=0; m < height; m++)
  29. {
  30. unsigned char* p=(unsigned char*)src->imageData + src->widthStep * m;
  31. for(int n = 0; n < width; n++)
  32. {
  33. histogram[int(*p++)]++;
  34. }
  35. }
  36. int threshold;
  37. long sum0 = 0, sum1 = 0; //存储前景的灰度总和和背景灰度总和
  38. long cnt0 = 0, cnt1 = 0; //前景的总个数和背景的总个数
  39. double w0 = 0, w1 = 0; //前景和背景所占整幅图像的比例
  40. double u0 = 0, u1 = 0;  //前景和背景的平均灰度
  41. double variance = 0; //最大类间方差
  42. int i, j;
  43. double u = 0;
  44. double maxVariance = 0;
  45. for(i = 1; i < 256; i++) //一次遍历每个像素
  46. {
  47. sum0 = 0;
  48. sum1 = 0;
  49. cnt0 = 0;
  50. cnt1 = 0;
  51. w0 = 0;
  52. w1 = 0;
  53. for(j = 0; j < i; j++)
  54. {
  55. cnt0 += histogram[j];
  56. sum0 += j * histogram[j];
  57. }
  58. u0 = (double)sum0 /  cnt0;
  59. w0 = (double)cnt0 / size;
  60. for(j = i ; j <= 255; j++)
  61. {
  62. cnt1 += histogram[j];
  63. sum1 += j * histogram[j];
  64. }
  65. u1 = (double)sum1 / cnt1;
  66. w1 = 1 - w0; // (double)cnt1 / size;
  67. u = u0 * w0 + u1 * w1; //图像的平均灰度
  68. printf("u = %f\n", u);
  69. //variance =  w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
  70. variance =  w0 * w1 *  (u0 - u1) * (u0 - u1);
  71. if(variance > maxVariance)
  72. {
  73. maxVariance = variance;
  74. threshold = i;
  75. }
  76. }
  77. printf("threshold = %d\n", threshold);
  78. return threshold;
  79. }

【第二套代码】

  1. #include "stdafx.h"
  2. #include "stdio.h"
  3. #include "cv.h"
  4. #include "highgui.h"
  5. #include "Math.h"
  6. int Otsu(IplImage* src);
  7. int _tmain(int argc, _TCHAR* argv[])
  8. {
  9. IplImage* img = cvLoadImage("c:\\aSa.jpg",0);
  10. IplImage* dst = cvCreateImage(cvGetSize(img), 8, 1);
  11. int threshold = Otsu(img);
  12. printf("threshold = %d\n", threshold);
  13. cvThreshold(img, dst, threshold, 255, CV_THRESH_BINARY);
  14. cvNamedWindow( "img", 1 );
  15. cvShowImage("img", dst);
  16. cvWaitKey(-1);
  17. cvReleaseImage(&img);
  18. cvReleaseImage(&dst);
  19. cvDestroyWindow( "dst" );
  20. return 0;
  21. }
  22. int Otsu(IplImage* src)
  23. {
  24. int height=src->height;
  25. int width=src->width;
  26. //histogram
  27. float histogram[256] = {0};
  28. for(int i=0; i < height; i++)
  29. {
  30. unsigned char* p=(unsigned char*)src->imageData + src->widthStep * i;
  31. for(int j = 0; j < width; j++)
  32. {
  33. histogram[*p++]++;
  34. }
  35. }
  36. //normalize histogram
  37. int size = height * width;
  38. for(int i = 0; i < 256; i++)
  39. {
  40. histogram[i] = histogram[i] / size;
  41. }
  42. //average pixel value
  43. float avgValue=0;
  44. for(int i=0; i < 256; i++)
  45. {
  46. avgValue += i * histogram[i];  //整幅图像的平均灰度
  47. }
  48. int threshold;
  49. float maxVariance=0;
  50. float w = 0, u = 0;
  51. for(int i = 0; i < 256; i++)
  52. {
  53. w += histogram[i];  //假设当前灰度i为阈值, 0~i 灰度的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例
  54. u += i * histogram[i];  // 灰度i 之前的像素(0~i)的平均灰度值: 前景像素的平均灰度值
  55. float t = avgValue * w - u;
  56. float variance = t * t / (w * (1 - w) );
  57. if(variance > maxVariance)
  58. {
  59. maxVariance = variance;
  60. threshold = i;
  61. }
  62. }
  63. return threshold;
  64. }

OTSU算法(也称最大类间差法,有时也称之为大津算法)相关推荐

  1. 图像二值化----otsu(最大类间方差法、大津算法)(二)

    转自:http://blog.stevenwang.name/ostu-threshold-56002.html OTSU算法也称最大类间差法,有时也称之为大津算法,被认为是图像分割中阈值选取的最佳算 ...

  2. 大津算法的matlab实现

    大津算法详解 一.算法功能 ​ 图像分割就是把图像分成若干个特定的.具有独特性质的区域并提出感兴趣目标的技术和过程.它是由图像处理到图像分析的关键步骤. ​ 大津算法也称最大类间差法,由大津于1979 ...

  3. 图像二值化(Image Binarization):平均值法、双峰法、大津算法(OTSU)

    图像二值化(Image Binarization):平均值法.双峰法.大津算法(OTSU) 编程实现图像的二值化,分析不同的阈值对二值化图像的影响. 问题描述 传统的机器视觉通常包括两个步骤:预处理和 ...

  4. CV8 OpenCV环境下实现大津算法

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

  5. 【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)

    目录 概念 C++源码 OtsuThreshold 主函数 效果 完整源码 平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文所用源码修改自C+ ...

  6. opencv-qt大津算法(Otsu)

    opencv-qt大津算法(Otsu) 1 简介 2 算法原理 3 代码 4 局限性 5 参考 1 简介 Otsu算法,即大津算法,最大类间方差算法,由日本人大津展之提出.大津二值化法用来自动对基于聚 ...

  7. CUDA精进之路(五):图像处理——OTSU二值算法(最大类间方差法、大津法)

    引言 最近在做医疗设备相关的项目,故在项目中大量用到了各类图像分割的算法,为了在图像中分割出特定目标,用到的算法可以有很多,比如阈值分割,多通道分割,边缘分割以及一些前沿的组合分割.而对大多数图像来说 ...

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

    OTSU是阈值分割中一种常用的算法,它可以根据图像自动生成最佳分割阈值.OTSU的核心思想是类间方差最大化. import cv2 import numpy as np from matplotlib ...

  9. 【图像分割】基于迭代阙值选择、最大类间差、区域生长多种算法实现图像分割含Matlab源码

    1 简介 重点讨论了图像分割法中的阈值研究法,包括迭代阙值选择.最大类间差.区域生长进行了重点分析,用Matlab进行实现并给出了实验结果. 2 部分代码 function varargout = I ...

最新文章

  1. 2021年全国大学生智能汽车竞赛山东赛区比赛顺利进行
  2. 关于update set from where
  3. 为什么我启动哪一个tomcat都是启动同一个tomcat(tomcat7)
  4. H5中canvas和svg绘图方式介绍
  5. Pytorch实现基本循环神经网络RNN (3)
  6. 排序千万级数据_从千万级房产成交量排名,窥探中国城市的真实家底
  7. (62)FPGA一维数组(reg)
  8. 如何区分常见 USB 接口类型
  9. amoeba安装与简单使用(一)
  10. 超人气新书《SEO实战密码——60天网站流量提高20倍》火爆热销
  11. 【转】解决IE8无法加载webplayer流媒体播放器的方法
  12. 如何将屏幕截图保存到桌面以外的自定义文件夹?
  13. HDUOJ-------1753大明A+B(大数之小数加法)
  14. JavaScript继承方式详解
  15. ting56 下载 有声小说 超禁忌游戏
  16. 相比REG007 不仅免费还好用 的手机号绑定查询工具
  17. 计算机科学有科研,计算机科学领域科研合著网演化分析
  18. 2018年第16周-ZooKeeper基本概念(配搭建过程和Master-Workers例子)
  19. 计算机网络知识点(四) 介质访问控制子层
  20. 身体这些部位不舒服的时候,你知道意味着什么吗?

热门文章

  1. Kafka设计解析(八)- Kafka事务机制与Exactly Once语义实现原理
  2. spring源码分析之spring-jms模块详解
  3. spring beans源码解读之--XmlBeanFactory
  4. cache 的设计与实现--转载
  5. 移动金融业务风控框架及设备风险识别的意义(上)
  6. 本周看代码找bug总结
  7. 基于若依框架的二次开发_浅谈若依框架
  8. 阿里高级算法专家公开10大思考
  9. 灰度图像--图像增强 Robert算子、Sobel算子
  10. 传统产业已死,新的产业在何方?