Wellner 1993快速自适应的图像二值化方法的提高 (Derek Bradley and Gerhard Roth 2007)

本文主要是介绍Wellner 1993快速自适应的图像二值化方法的提高 (Derek Bradley and Gerhard Roth 2007),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前面一种方案实际上还是存在一定的问题的, 就是这个避重就轻的初始g(n)值127*s(127表示0-255之间的中间值), 这个东西带来的最直接的问题就是边缘的效果在这个算法下是不咋地的。 其实从这个所谓的"Wellner 1993", 后人又做了很多的改进, 使之效率更高, 效果更好。比方说这个Derek Bradley和Gerhard Roth搞的这个所谓 Adaptive Thresholding Using the Integral Image 在这个网页

http://www.scs.carleton.ca/~roth/iit-publications-iti/docs/gerh-50002.pdf 可以看到一些他的踪迹。

 

这个算法的基本思想是这样的,为了打破原来算法的初始值问题以及扫描顺序的问题, 这里的像素二值化的时候, 直接使用周围矩形像素的颜色作比较,这样来判断像素值更科学。我们对算法的介绍从求和面积表(Summed-Area Table)开始. 这个求和面积表简单点说就是维护一张表, 表中的元素值就是它左上位置的所有像素的像素值和。(数学公式在这里编辑简直是噩梦!只能放图了无图无真相:))

示意图

左边就是原始像素值, 右边的就是累加得到的表, 比方说这个表里面的(2,2)位置的8就是通过2+3+3+0得到的, 而这个最大值28就是所有像素的累加和。得到这个和和我们的二值化有什么关联呢?前面我们提到了在新的这个算法里面像素的值以来于周围像素的颜色, 那周围像素的颜色如何表示呢? 我们可以通过这个表轻松获得, 且看下面一张图:

示意图2

这里的UL, LL, UR, LR表示的就是前面这个求和表里面的值, 如果我们要判断绿色区域中这个+号位置的值, 我们就要计算整个绿色区域的平均像素值, 如何计算呢? 有了新的表就方便了,右边其实给出了这个公式,这里的LR-UR-LL+UL就是整个绿色区域的像素值和。这个什么道理其实已经自己可以推断出来了, 如果还嫌这里不清楚的话,我们就给个更清楚的图:

示意图2

这个图和前面一样,但是如果还是用LR-UR-LL+UL来表示的话,这里就可以写成:

LR-UR-LL+UL = (A+B+C+D)-(A+B)-(A+C)+A = D, 这样就清楚很多了吧。 得到的这个值D就是D这个区域的像素值和, 那D中最中心的像素的颜色就可以用D/(widith*height)来做比较了。 所以算法的流程就是首先得到这个求和面积表, 其次遍历所有的像素, 然后以这些像素为中心点, 计算S*S大小的矩形的平均颜色, 用来和当前像素比较即可。这个流程可以说是相当精炼啊!这里依然用到了原来的S, T, 还保持了一致S是宽度的八分之一, 而T则是15,下面有一段我改过的实现代码:

[cpp]  view plain copy
  1. void adaptiveThreshold(unsigned char* input, unsigned char*& bin, int width, int height)  
  2. {  
  3.     int S = width >> 3;  
  4.     int T = 15;  
  5.       
  6.     unsigned long* integralImg = 0;  
  7.     int i, j;  
  8.     long sum=0;  
  9.     int count=0;  
  10.     int index;  
  11.     int x1, y1, x2, y2;  
  12.     int s2 = S/2;  
  13.       
  14.     bin = new unsigned char[width*height];  
  15.     // create the integral image  
  16.     integralImg = (unsigned long*)malloc(width*height*sizeof(unsigned long*));  
  17.     for (i=0; i<width; i++)  
  18.     {  
  19.         // reset this column sum  
  20.         sum = 0;  
  21.         for (j=0; j<height; j++)  
  22.         {  
  23.             index = j*width+i;  
  24.             sum += input[index];  
  25.             if (i==0)  
  26.                 integralImg[index] = sum;  
  27.             else  
  28.                 integralImg[index] = integralImg[index-1] + sum;  
  29.         }  
  30.     }  
  31.     // perform thresholding  
  32.     for (i=0; i<width; i++)  
  33.     {  
  34.         for (j=0; j<height; j++)  
  35.         {  
  36.             index = j*width+i;  
  37.             // set the SxS region  
  38.             x1=i-s2; x2=i+s2;  
  39.             y1=j-s2; y2=j+s2;  
  40.             // check the border  
  41.             if (x1 < 0) x1 = 0;  
  42.             if (x2 >= width) x2 = width-1;  
  43.             if (y1 < 0) y1 = 0;  
  44.             if (y2 >= height) y2 = height-1;  
  45.             count = (x2-x1)*(y2-y1);  
  46.             // I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)  
  47.             sum = integralImg[y2*width+x2] -  
  48.                 integralImg[y1*width+x2] -  
  49.                 integralImg[y2*width+x1] +  
  50.                 integralImg[y1*width+x1];  
  51.             if ((long)(input[index]*count) < (long)(sum*(100-T)/100))  
  52.                 bin[index] = 0;  
  53.             else  
  54.                 bin[index] = 255;  
  55.         }  
  56.     }  
  57.     free (integralImg);  
  58. }  

这里也有一点效果图可以看看, 同时有和前面一个算法的比较:

 

原始1                                      wellnar算法                            最新

原始图1 wellnar 最新dm

 

 

还有一组:

ez_raw

wellnar:

wellnar

最新算法:

 

new

 

 

这些个贴图其实还不是特别的具体, 其实这个算法特别适用于光照强度变化很大的像素, 这里有些网页也给出了鲜明的对比:http://www.derekbradley.ca/AdaptiveThresholding/index.html 效果的差距还是很明显的。 总的来说这个算法实现简单, 效率很高,确实是不错的选择。 而且还很新!在07年的杂志上发表的,现在记录下来与君共勉之!

这篇关于Wellner 1993快速自适应的图像二值化方法的提高 (Derek Bradley and Gerhard Roth 2007)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702277

相关文章

Java 方法重载Overload常见误区及注意事项

《Java方法重载Overload常见误区及注意事项》Java方法重载允许同一类中同名方法通过参数类型、数量、顺序差异实现功能扩展,提升代码灵活性,核心条件为参数列表不同,不涉及返回类型、访问修饰符... 目录Java 方法重载(Overload)详解一、方法重载的核心条件二、构成方法重载的具体情况三、不构

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()