织梦CMS - 轻松建站从此开始!

罗索

大津法 OTSU的算法

落鹤生 发布于 2010-04-25 16:16 点击:次 
大津法(OTSU法) 大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。
TAG:

 大津法(OTSU法)

大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,当t使得值g=w0*(u0-u)2+w1*(u1-u)2 最大时t即为分割的最佳阈值。对大津法可作如下理解:该式实际上就是类间方差值,阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1,总均值为u,根据方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。

直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0-u1)2。部分计算过程如下:

  1. //遍历所有灰度值求Max g。 
  2. for intCurrentLevel:=0 to intArrLen do 
  3.   begin 
  4.     if intSclGrayLevel[intCurrentLevel]=0 then 
  5.       continue 
  6.     else 
  7.       begin 
  8.               // 计算当阈值为intCurrentLevel时的g 
  9.         intCount:=0; 
  10.         intSumPels:=0; 
  11.  
  12.         for intLoop:=0 to intCurrentLevel do 
  13.           begin 
  14.             intCount:=intCount+intSclGrayLevel[intLoop]; 
  15.             intSumPels:=intSumPels+intSumPelsArr[intLoop]; 
  16.           end; 
  17.         w0:=intCount/intSize; 
  18.         u0:=intSumPels/intCount; 
  19.         w1:=1-w0; 
  20.         if intSize-intCount<>0 then 
  21.           u1:=(intTotalPels-intSumPels)/(intSize-intCount) 
  22.         else 
  23.           u1:=0; 
  24.  
  25.         RlTempO:=w0*w1*(u0-u1)*(u0-u1); 
  26.         if RlTempO>RlMaxO then 
  27.         begin 
  28.           RlMaxO:=RlTempO; 
  29.           Result:=intCurrentLevel; 
  30.         end; 
  31.       end; 


我们在测试中发现:大津法选取出来的阈值非常理想,对各种情况的表现都较为良好。虽然它在很多情况下都不是最佳的分割,但分割质量通常都有一定的保障,可以说是最稳定的分割。由上可知,大津算法是一种较为通用的分割算法。在它的思想的启迪下,人们进一步提出了多种类似的评估阈值的算法,具体可参加【5】、【6】等。

 

 OTSU的算法,很好用,好不容易才找到的。

  1. /* 
  2. OTSU 算法可以说是自适应计算单阈值(用来转换灰度图像为二值图像)的简单高效方法。 
  3.  
  4. 下面的代码最早由 Ryan Dibble提供,此后经过多人Joerg.Schulenburg, R.Z.Liu 等修改,补正。 
  5.  
  6. 算法对输入的灰度图像的直方图进行分析,将直方图分成两个部分,使得两部分之间的距离最大。 
  7. 划分点就是求得的阈值。 
  8.  
  9. parameter: *image --- buffer for image 
  10. rows, cols --- size of image 
  11. x0, y0, dx, dy --- region of vector used for computing threshold 
  12. vvv --- debug option, is 0, no debug information outputed 
  13. */ 
  14. /*======================================================================*/ 
  15. /* OTSU global thresholding routine */ 
  16. /* takes a 2D unsigned char array pointer, number of rows, and */ 
  17. /* number of cols in the array. returns the value of the threshold */ 
  18. /*======================================================================*/ 
  19. int otsu (unsigned char *image, int rows, int cols, int x0, int y0, int dx, int dy, int vvv) 
  20. unsigned char *np; // 图像指针 
  21. int thresholdValue=1; // 阈值 
  22. int ihist[256]; // 图像直方图,256个点 
  23.  
  24. int i, j, k; // various counters 
  25. int n, n1, n2, gmin, gmax; 
  26. double m1, m2, sum, csum, fmax, sb; 
  27.  
  28. // 对直方图置零... 
  29. memset(ihist, 0, sizeof(ihist)); 
  30.  
  31. gmin=255; gmax=0; 
  32. // 生成直方图 
  33. for (i = y0 + 1; i < y0 + dy - 1; i++) { 
  34. np = [i*cols+x0+1]; 
  35. for (j = x0 + 1; j < x0 + dx - 1; j++) { 
  36. ihist[*np]++; 
  37. if(*np > gmax) gmax=*np; 
  38. if(*np < gmin) gmin=*np; 
  39. np++; /* next pixel */ 
  40.  
  41. // set up everything 
  42. sum = csum = 0.0; 
  43. n = 0; 
  44.  
  45. for (k = 0; k <= 255; k++) { 
  46. sum += (double) k * (double) ihist[k]; /* x*f(x) 质量矩*/ 
  47. n += ihist[k]; /* f(x) 质量 */ 
  48.  
  49. if (!n) { 
  50. // if n has no value, there is problems... 
  51. fprintf (stderr, "NOT NORMAL thresholdValue = 160\n"); 
  52. return (160); 
  53.  
  54. // do the otsu global thresholding method 
  55. fmax = -1.0; 
  56. n1 = 0; 
  57. for (k = 0; k < 255; k++) { 
  58. n1 += ihist[k]; 
  59. if (!n1) { continue; } 
  60. n2 = n - n1; 
  61. if (n2 == 0) { break; } 
  62. csum += (double) k *ihist[k]; 
  63. m1 = csum / n1; 
  64. m2 = (sum - csum) / n2; 
  65. sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2); 
  66. /* bbg: note: can be optimized. */ 
  67. if (sb > fmax) { 
  68. fmax = sb; 
  69. thresholdValue = k; 
  70.  
  71. // at this point we have our thresholding value 
  72.  
  73. // debug code to display thresholding values 
  74. if ( vvv & 1 ) 
  75. fprintf(stderr,"# OTSU: thresholdValue = %d gmin=%d gmax=%d\n"
  76. thresholdValue, gmin, gmax); 
  77.  
  78. return(thresholdValue); 
(Ryan Dibble)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201004/9254.html]
本文出处:网络博客 作者:Ryan Dibble
顶一下
(8)
88.9%
踩一下
(1)
11.1%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容