当前位置:   article > 正文

图像处理阈值分割之OTSU/大津阈值原理及其实现_otsu 阈值分割算法

otsu 阈值分割算法

图像处理阈值分割之最大类间方差法/大津法/OTSU

3、说一下大津阈值/OTSU阈值(最大类间方差法)。

简介:

        最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

         对于大小为 M×N 的图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。
图像中像素的灰度值小于阈值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)

 

1、算法原理

OTSU的公式如下,如果当前阈值为t,

      w0:前景点所占比例

      w1:背景点所占比例,w1 = 1- w0

      u0:前景灰度均值

      u1:背景灰度均值

       u:全局灰度均值,u = w0*u0 + w1*u1

      g:类间最大方差,g = w0(u0-u)*(u0-u) + w1(u1-u)*(u1-u) = w0*(1 – w0)*(u0 - u1)* (u0 - u1)

      目标函数为 g,g 越大,t 就是越好的阈值。为什么采用这个函数作为判别依据,直观是这个函数反映了前景和背景的差值,

差值越大,前景与背景差别越大,阈值越好。

2、算法实现伪代码(C/C++/Python实现)

3、算法实现代码(C/C++/Python实现)

(1)C/C++实现OTSU/大津阈值,代码:

  1. /// <summary>
  2. /// 返回OTSU阈值
  3. /// </summary>
  4. /// <param name="src"></单通道灰度图像>
  5. /// <param name="width"></图像的宽>
  6. /// <param name="height"></图像的高>
  7. /// <returns></returns>
  8. int Otsu_byte(const uchar* src, const int width, const int height)
  9. {
  10. int i = 0;
  11. float histogram[256];
  12. //unsigned char* temp=new uchar[width*height];
  13. for (i = 0; i < 256; i++)
  14. {
  15. histogram[i] = 0;
  16. }
  17. //histogram
  18. for (int i = 0; i < height; i++)
  19. {
  20. for (int j = 0; j < width; j++)
  21. {
  22. histogram[src[i * width + j]]++;//统计灰度直方图.
  23. }
  24. }
  25. //normalize histogram
  26. int size = height * width;
  27. for (int i = 0; i < 256; i++)
  28. {
  29. histogram[i] = histogram[i] / size;//直方图归一化.
  30. }
  31. //average pixel value
  32. float avgValue = 0;
  33. for (int i = 0; i < 256; i++)
  34. {
  35. avgValue += i * histogram[i];//整幅图像的平均灰度.
  36. }
  37. int threshold;
  38. float maxVariance = 0;
  39. float w = 0, u = 0;
  40. for (int i = 0; i < 256; i++)
  41. {
  42. w += histogram[i];//假设当前灰度i为阈值, 0~i 灰度的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例.
  43. u += i * histogram[i];// 灰度i 之前的像素(0~i)的平均灰度值:前景像素的平均灰度值.
  44. float t = avgValue * w - u;
  45. float variance = t * t / (w * (1 - w));
  46. if (variance > maxVariance)
  47. {
  48. maxVariance = variance;
  49. threshold = i;
  50. }
  51. }
  52. //delete temp;
  53. return threshold;
  54. }

(2)基于OpenCV实现OTSU/大津阈值

基于OpenCV 的IplImage:

  1. //OTSU阈值
  2. int Otsu(IplImage* src)
  3. {
  4. int height=src->height;
  5. int width=src->width;
  6. //histogram
  7. float histogram[256] = {0};
  8. for(int i=0; i < height; i++)
  9. {
  10. unsigned char* p=(unsigned char*)src->imageData + src->widthStep * i;
  11. for(int j = 0; j < width; j++)
  12. {
  13. histogram[*p++]++;//统计灰度直方图.
  14. }
  15. }
  16. //normalize histogram
  17. int size = height * width;
  18. for(int i = 0; i < 256; i++)
  19. {
  20. histogram[i] = histogram[i] / size;//直方图归一化.
  21. }
  22. //average pixel value
  23. float avgValue=0;
  24. for(int i=0; i < 256; i++)
  25. {
  26. avgValue += i * histogram[i];//整幅图像的平均灰度.
  27. }
  28. int threshold;
  29. float maxVariance=0;
  30. float w = 0, u = 0;
  31. for(int i = 0; i < 256; i++)
  32. {
  33. w += histogram[i];//假设当前灰度i为阈值, 0~i 灰度的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例.
  34. u += i * histogram[i];// 灰度i 之前的像素(0~i)的平均灰度值:前景像素的平均灰度值.
  35. float t = avgValue * w - u;
  36. float variance = t * t / (w * (1 - w) );
  37. if(variance > maxVariance)
  38. {
  39. maxVariance = variance;
  40. threshold = i;
  41. }
  42. }
  43. return threshold;
  44. }

基于OpenCV的Mat:

  1. #include <opencv2/opencv.hpp>
  2. #include <cv.h>
  3. #include <highgui.h>
  4. #include <cxcore.h>
  5. using namespace std;
  6. using namespace cv;
  7. int otsuGray(const Mat src)
  8. {
  9. Mat img = src;
  10. int c = img.cols; //图像列数
  11. int r = img.rows; //图像行数
  12. int T = 0; //阈值
  13. uchar* data = img.data; //数据指针
  14. int ftNum = 0; //前景像素个数
  15. int bgNum = 0; //背景像素个数
  16. int N = c*r; //总像素个数
  17. int ftSum = 0; //前景总灰度值
  18. int bgSum = 0; //背景总灰度值
  19. int graySum = 0;
  20. double w0 = 0; //前景像素个数占比
  21. double w1 = 0; //背景像素个数占比
  22. double u0 = 0; //前景平均灰度
  23. double u1 = 0; //背景平均灰度
  24. double Histogram[256] = {0}; //灰度直方图
  25. double temp = 0; //临时类间方差
  26. double g = 0; //类间方差
  27. //灰度直方图
  28. for(int i = 0; i < r ; i ++)
  29. {
  30. for(int j = 0; j <c; j ++)
  31. {
  32. Histogram[img.at<uchar>(i,j)]++;
  33. }
  34. }
  35. //求总灰度值
  36. for(int i = 0; i < 256; i ++)
  37. {
  38. graySum += Histogram[i]*i;
  39. }
  40. for(int i = 0; i < 256; i ++)
  41. {
  42. ftNum += Histogram[i]; //阈值为i时前景个数
  43. bgNum = N - ftNum; //阈值为i时背景个数
  44. w0 = (double)ftNum/N; //前景像素占总数比
  45. w1 = (double)bgNum/N; //背景像素占总数比
  46. if(ftNum == 0) continue;
  47. if(bgNum == 0) break;
  48. //前景平均灰度
  49. ftSum += i*Histogram[i];
  50. u0 = ftSum/ftNum;
  51. //背景平均灰度
  52. bgSum = graySum - ftSum;
  53. u1 = bgSum/bgNum;
  54. g = w0*w1*(u0-u1)*(u0-u1);
  55. if(g > temp)
  56. {
  57. temp = g;
  58. T = i;
  59. }
  60. }
  61. return T
  62. /* for(int i=0; i<img.rows; i++)
  63. {
  64. for(int j=0; j<img.cols; j++)
  65. {
  66. if((int)img.at<uchar>(i,j)>T)
  67. img.at<uchar>(i,j) = 255;
  68. else
  69. img.at<uchar>(i,j) = 0;
  70. }
  71. }
  72. return img;*/
  73. }
  74. //【此处代码来自:https://blog.csdn.net/a153375250/article/details/50970104?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-1&spm=1001.2101.3001.4242】

OpenCV中已有实现该算法,亦可直接调用。

  1. int value1 = 0;
  2. cv::Mat dst;
  3. cv::Mat src = cv::imread("..\\testPicture\\001.jpg", cv::IMREAD_GRAYSCALE);
  4. value1 = cv::threshold(src, dst, 0,255, CV_THRESH_OTSU);//返回OTSU阈值

4、关于最大类间方差法(otsu)的性能:

类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。

当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。

【逆水行舟用力撑,一篙松劲退千寻。】

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/481142
推荐阅读
  

闽ICP备14008679号