经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
基于阈值的灰度图像提取法
来源:cnblogs  作者:KenSporger  时间:2019/10/8 9:15:52  对本文有异议

  对于简单的灰度图像,如果目标与背景的灰度存在一定的差异,那么可以用阈值来提取目标。关键是确定阈值,常用方法有:

模态法、P参数法、可变阈值法、大津法和迭代逼近法等。

 

模态法:

  取直方图的波谷作为阈值。适用于目标与背景灰度差异较大,目标与背景的直方图各有一个波峰的灰度图像。

  如果直方图凹凸较激烈,寻找波谷存在困难,可以用领域点平均化处理使直方图相对平滑。

 

P参数法:

  当目标占图像的面积比例已知,且目标最小灰度值大于背景最大灰度值时,可采用P参数法。具体做法是,如果目标灰度接近白色,则在

  直方图右侧开始累计像素,直到累计像素占总像素数比例为P时,将当前的灰度作为阈值(否则从左侧开始累计)。

  例如下图,月亮所占比列为0.45,它最低灰度与背景灰度稍有重合,阈值确定为75,最终基本提取出目标。

        

 

可变阈值法:

  当图像背景灰度多变时,可以为图像不同部位设置不同的阈值,这样可以很好地去除干扰。

  例如提取下图的蒲公英,图像上部光照多,主要为蒲公英的羽毛,下部光照少,且主要为茎,对上中下采取不同阈值的提取效果会好很多。

  

          

 

大津法:

  大津法的应用最广泛,有很好的自适应阈值。适用于批量图像提取或者动态灰度图像提取(然而事实证明,当大津遇到反光时,干扰也会很严重)。

  大津法的原理如下:

  设T为分割阈值,由此划分出区域记为R1和R2

  R1占图像总像素的比例为θ1,R2占图像总像素的比例为θ2

  图像的平均灰度值为μ0,R1的平均灰度为μ1,R2的平均灰度为μ2

  显然有:

    μ01122

  如果阈值选得恰当,则R1与R2的灰度差应该较大,那么μ1与μ0、μ2与μ0的差的绝对值也就较大。

  定义类间方差,来反应灰度差大小:

    σ21(μ1022(μ202

  对于每个选定的阈值T,都有σ对应,而最大σ的阈值T则是最佳阈值。

 

  另外,尽管有化简公式来减少迭代次数的方法(https://www.cnblogs.com/kensporger/p/11270452.html),大津法的过程计算量还是很大的。

 

迭代逼近法:

  此法是大津法的简化版,具体步骤如下:

  取最大灰度与最小灰度平均值(也可以是图像平均灰度)为初始阈值T,由此得两个区域为R1和R2

  计算R1和R2的灰度均值μ1、μ2

  选择新阈值T=(μ12)/2,重复以上步骤,直到T不再变化或变化在一定范围内。

  采用该法的效果如图所示,大概只迭代了五次左右:

  

  但是,该法确定的阈值很粗糙,往往与最佳阈值会有较大偏差,比如提取之前的月亮,表现得就并不是很好了:

  

 

 

以上大部分matlab仿真测试代码罗列如下:

 

  1. %p参数法确定阈值
  2. function thres = pthres(file,p)
  3. imga = imread(file);
  4. %灰度化
  5. imga = rgb2gray(imga);
  6. %获取大小
  7. [sizex,sizey]=size(imga);
  8. %直方图
  9. histogram = zeros(256,1);
  10. for i=1:sizex
  11. for j=1:sizey
  12. histogram(imga(i,j)+1)=histogram(imga(i,j)+1)+1;
  13. end
  14. end
  15. %累计像素
  16. pixels_cnt=0;
  17. thres=256;
  18. while(pixels_cnt<p*sizex*sizey)
  19. pixels_cnt=pixels_cnt+histogram(thres);
  20. thres=thres-1;
  21. end
  22. %根据阈值二值化
  23. mybw=imbinarize(imga,(thres-1)/255);
  24. subplot(1,2,1);
  25. imshow(imga);
  26. title('原图');
  27. subplot(1,2,2);
  28. imshow(mybw);
  29. title('p参数法二值化');
  30. end

 

 

 

 

  1. %多阈值分割实例
  2. imga=imread('multi_thres.jpg');
  3. imga=rgb2gray(imga);
  4. single = imbinarize(a,85/255);
  5. multi(250:300,:) = imbinarize(a(250:300,:),85/255);
  6. multi(150:250,:) = imbinarize(a(150:250,:),150/255);
  7. multi(1:150,:) = imbinarize(a(1:150,:),170/255);
  8. subplot(1,3,1);
  9. imshow(imga);
  10. title('原图');
  11. subplot(1,3,2);
  12. imshow(single);
  13. title('单阈值处理');
  14. subplot(1,3,3);
  15. imshow(multi);
  16. title('多阈值处理');

 

  1. %迭代逼近法
  2. function thres=iterator(file)
  3. imga = imread(file);
  4. %灰度化
  5. imga = rgb2gray(imga);
  6. %获取大小
  7. [sizex,sizey]=size(imga);
  8. %直方图与总灰度统计
  9. gray_sum=0;
  10. histogram = zeros(256,1);
  11. for i=1:sizex
  12. for j=1:sizey
  13. histogram(imga(i,j)+1)=histogram(imga(i,j)+1)+1;
  14. gray_sum= gray_sum+double(imga(i,j)+1);
  15. end
  16. end
  17. %初始阈值
  18. thres=gray_sum/(sizex*sizey);
  19. old_thres=0;
  20. %迭代逼近
  21. while(abs(thres-old_thres)>1)
  22. disp(thres);
  23. u1=0;u2=0;
  24. cnt1=0;cnt2=0;
  25. for i=1:thres
  26. u1=u1+histogram(i)*i; %统计R1区域平均灰度
  27. cnt1=cnt1+histogram(i);
  28. end
  29. for i=256:-1:thres
  30. u2=u2+histogram(i)*i; %统计R2区域平均灰度
  31. cnt2=cnt2+histogram(i);
  32. end
  33. u1=u1/cnt1;
  34. u2=u2/cnt2;
  35. old_thres=thres;
  36. thres=(u1+u2)/2; %新阈值
  37. end
  38. mybw=imbinarize(imga,(thres-1)/256);
  39. subplot(1,2,1);
  40. imshow(imga);
  41. title('原图');
  42. subplot(1,2,2);
  43. imshow(mybw);
  44. title('迭代逼近法二值化');
  45. end

 

 

 

原文链接:http://www.cnblogs.com/kensporger/p/11614619.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号