【工程应用三】三种不同的文本图像背景漂白/纯化/去除算法。

      文本图像在图像处理的应用中也是占用了一个比较大的比例的,特别是随着现在对基础教育的越来越重视,对学生的一些辅助教育、智能化作业批改等等方面的需求迅速增长。目前是上面也已经有了很多这方面比较专业的软件。在这方面的算法那当中,一个比较重要的过程就是对文本图像背景的纯化,也有叫漂白或者叫背景去除的,因为背景复杂了后,对于后续的二值化、识别等都会带来不利的影响。

  本文结合工程实践,提出三种不同的背景漂白算法,分享给大家。

   一、PhotoCopy算法

  这是Photoshop软件里的一个内嵌算法,中文名字叫影印,PS的帮助文档对其专业的解释为:

  “影印”滤镜模拟影印图像的效果。较大区域的暗度会导致仅在其边缘的周围进行拷贝,并且半调会背离纯黑或纯白。可以设置细节和暗度的色阶。

  看完,不知所云啊。

  经过测试,在PS中影印算法的结果是和背景色和前景色的设置有关的,在文本图像的应用中,前景色设置为黑色(字体的颜色),背景色为白色(纸张的颜色),此时就可以获取一个基本的漂白效果了,如下所示:

  

                   原图                                                                                       影印效果(细节参数10,暗度参数10)

  可以看到,漂白后的图背景部分有不少噪点,这个可以在执行影印前进行一些简单的去噪操作,比如DCT去做,或者其他的一些保边去噪算法(文字较之背景一般都是强边缘的)。

  下面是经过了局部拉普拉斯去燥后的图已经用相同参数执行影印后的效果。

   

              去噪后                                    再次执行影印

  明显,这样处理后黑色的噪点少了很多,整体看起来更为完美。

  关于影印算法的实现,其基础是高斯模糊,通过比较高斯模糊和原图之前的差异,再放大一定的倍数,然后用得到的结果作为权重,在背景和前景之间进行融合。这是个很容易实现和优化的算法。

  在有文字区域,模糊的值和原图的差异较为明显,经过放大后,权重就较大,这个时候就显示为前景色,在其他区域,差异较小,权重小,结果就靠近背景色。

  二、网络上分享的一个背景移除算法

  具体的可以在//www.cnblogs.com/jsxyhelu这个大侠的博客中查找。 这个算法的基础其实也是高斯模糊,一个简答的代码如下所示:

for (int Y = 0; Y < Height * Width; Y++)
{
   if (Blur[Y] != 0)    
  {
    Dest[Y] = IM_ClampToByte(Src[Y] * 255 / Blur[Y]);
  } }

  这里的Blur通常也是取的高斯模糊的结果。

  这是一个非常简单的代码,也是可以很高效的实现的,通常需要一个比较大的模糊,比如100左右。

    

  

                原图                                  处理后的效果

  这个算法在此类图像中能够成功的核心是:在原图中比较黑的文字部分,占用的整体是比较少的,当大半径模糊时,模糊的值是接近纸张之类的颜色的,也就是比较靠近白色,所以结果基本上没什么变化,而纸张那些地方的颜色,因为模糊的值和他们的原始值基本差不多,所以Src/Blur基本接近1,在乘以255,所以结果就变为白色了。

  可以看出,这个算法那其实和PhotoCopy有所类似,都是比较模糊和原图的差异,只是一个用的减法,一个用的是除法。

  但是这个算法有一个好处,他能够很好地保留原始文本图像的一些彩色信息,而不会出现不自然的现象。不过如果直接这个算法出来的结果还是有点对比度不够,后期在适当的增加点对比度效果会很不错。

  比如下图,就是在处理后对比度增加了30的效果,而且红色文字和蓝色的LOGO得到了很好的保留。

      

  三、一个基于局部方差和均值的改进算法

  我们知道,在局部二值算法中,Sauvola二值化一直是个标杆算法,他比opencv自带的自适应二值化有着更为稳定和可靠的效果,而且他也有快速的O(1)算法。其基本的原理和计算公式如下:

  某点(x,y)处的均值和方差表达式为:

            

  则该点的二值化的阈值为:

          

  其中 k为修正系数,有效范围[0,1], R可取定值128。

  如果直接这样写,就成了2值化了,但是现在有很多库其实不是需要二值化的结果的,他需要的是一个比较纯净的图,实际上还是包含了很多边缘信息的。

  我们采用了一种方法,首先阈值确定处理方式为取那些值大于平均值的像素和平均值的方差加上平均值,即为T,然后在提供一可调参数D,当像素值大于T-D,则结果为白色,如果小于T-D,则考虑不能直接设置为黑色,我们根据图像内容计算某一个BaseValue,当像素值小于T-D-BaseValue,则为黑色,如果在他们之间,则进行一个线性的量化,按照大小量化到0和255之间,以便让颜色有一个线性的变化,不会产生特别突兀的效果。

  如果对每个像素都采用上述方式进行处理,则处理的速度会非常的缓慢,因为这个过程不想普通的Sauvola可以剔除前后依赖关系,因此,一种加速的方式就是采用类似CLAHE算法一样,对图像直接分块,分块后单独计算某一个块的参数,然后可采用双线性插值计算出块内其他位置的相关参数。当然还有一种方式就是用这些分块点采用更为复杂的插值或者拟合出一个曲面,然后获取参数,这样做的计算时间也会要稍微复杂一些,但是对于一些边缘你的过渡要稍微好一点。

  通常,块的大小对结果的影响不是很明显,但是还有区别,建议块的大小可取16和32之间。

  我们测试了一些图片,感觉这个算法的效果还是非常不错的,

     

  

  测试一张有着严重影印的图片也能通过调节参数得到不错的结果:

 

  这三个算法应该说各有千秋,PhotoCopy的容错性很不错,但是似乎噪点有点多(不过PhotoCopy还有很多其他的特殊作用),jsxyhelu的那个呢也很不错,速度快,效果也还行,还能完美的保证彩色不丢失。基于方差的在整体的对比度方面有着更为显著的效果,而且对局部阴影也有很不错的过滤作用。

  在我的SSE Demo里也集成了上述三个算法,分别位于Styleize –> PhotoCopy、Detection->Auxliary->RemoveBackGround以及Detection->Auxliary->PureGround菜单下。 PureGround还有一些其他的选项,如下图所示:   

                 

  可在此处下载Demo: //files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar

  国内也有人针对此需求开发一些比较专业的软件,如果有此需求的我推荐此人的博客://www.cnblogs.com/Charltsing/p/PictureCleaner.html,可以直接免费使用,而且支持批处理等等比较实用的功能,如下图所示:  

        

       如果想时刻关注本人的最新文章,也可关注公众号(Imageshop):