作者:马健
邮箱:stronghorse_mj@hotmail.com
主页:http://www.comicer.com/stronghorse/
发布:2017.07.23

教程十七:二值化图像去毛刺

在灰度图像处理成纯黑白(二值化)图像以后,经常出现的一个问题是轮廓边缘出现毛刺。如下面这个图像:

为了看得更清楚,放大到800%并加网格线:

可以看出在“工”字的上面一横中,上边缘有几个突出点,下边缘有两个凹陷点,而在“业”字左侧竖条中有突出点,下面一横中有凹陷点。

产生毛刺的原因是:在扫描或拍摄所生成的原始图像中,轮廓边缘像素点的值其实是介于“白”与“黑”之间的“灰”,所以整个边缘看起来很光滑、不生硬,但变成纯黑白后,像素点非黑即白,不再有中间灰,所以总有那么几个点可能就因为值稍微差了一点,就与周围的不一样了。
具体可以参见本系列教程“后记”中“常见问题之二:扫描图像中的黑、白、灰”部分。

所以解决的办法就是:

  1. 让模糊来得更猛烈一些吧!如果模糊得更均匀一些,这种毛刺现象其实会更少一点。所以在本系列教程的其它部分给出的处理参数中,经常会看到在选择纯黑白后,用高斯模糊来消毛刺。另外对图像进行放大也会拉出一些模糊空间,一方面可以减轻毛刺,另一方面可以避免转成纯黑白图像后出现笔画粘连——所以我一直觉得在
    针对扫描书籍的图像处理教程中,如果只提二值化却不提放大,就是在骗鬼。
  2. 用数字图像处理中的形态学方法识别孤立点、凹陷点,然后去除或填平。

在ScanTailor(以下简称ST)中用的就是第2种方法,在CEP
v4.13中被引进:在“色彩设置”界面中如果在“色彩数”中选择“纯黑白”,再勾选“边缘去毛刺”,即可使用这种方法。

这种方法的原理是:

  1. 先总结常见的边缘毛刺形状(孤立点或凹陷点)及修正方法(去除或填平),并以字符串的形式定义成模板。
  2. 用形态学中的击中-击不中变换(Hit-Miss
    Transform),在整张图像中查找能与模板匹配的像素点,然后按照模板对像素进行去除或填充。

在ST中总结出来的模板共有6个,分别是:

1 2 3 4 5 6
"XXX"
" - "
"  "
"X ?"
"X "
"X- "
"X- "
"X "
"X ?"
"X ?"
"X ?"
"X "
"X- "
"X- "
"X- "
"X "
"X ?"
"X ?"
"XX?"
"XX?"
"XX "
"X+ "
"X+ "
"X+ "
"XX "
"XX?"
"XX?"
"XX?"
"XX "
"X+ "
"X+ "
"XX "
"XX?"
"  "
"X+X"
"XXX"

在模板中共有5种符号:X表示黑点,空格表示白点,问号表示黑点白点均可,减号表示去除点,加号表示填充点。所以上表中的前3个模板就表示如果在一排黑点外有孤立点,则孤立点应去除,如上面示例图中“工”字上面一横中的几个孤立点;后3个模板则表示如果黑点中间有凹陷点,则应该进行填充,如上面示例图中“业”字底下一横中的几个凹陷点。

在ST中,每个模板会在上、下、左、右4个方向分别匹配,以模板1为例,其实在内部会扩充为以下4个模板进行匹配:

"XXX"
" - "
"  "
"  "
" - "
"XXX"
"X "
"X- "
"X "
" X"
" -X"
" X"

因此6个模板其实内部要匹配24次,在图像较大时就会显得很慢,这也是我平时更喜欢用模糊来进行平滑的原因:CEP中的高斯模糊还是很快的。

整个处理过程的核心是在图像中查找模板的所有匹配点,即需要去除、填充的点,用的是击中-击不中变换(Hit-Miss
Transform)。在我看过的教科书中包括ST的源代码本身,都是用腐蚀、膨胀等形态学基本操作的组合来实现这个变换,但我个人认为多次双循环会拖累代码的整体执行速度,所以在实现时我是按照这个变换最原始的定义实现的,一次双循环周游整个图像就找出所有匹配点,速度比ST略快,但内存消耗比ST大。

上面示例图用CEP去除毛刺后的效果:

放大到800%并加网格线的效果:

可以看出,横线、竖线上的孤立点都被去除,凹陷点也被填平,文字看起来干净了许多。

ComicEnhancerPro 系列教程十七:二值化图像去毛刺的更多相关文章

  1. opencv 删除二值化图像中面积较小的连通域

    对于上图的二值化图像,要去除左下角和右上角的噪点,方法:使用opencv去掉黑色面积较小的连通域. 代码 CvSeq* contour = NULL; double minarea = 100.0; ...

  2. (Opencv4)二值化图像

    (Opencv4)二值化图像  ret, dst = cv2.threshold(src, thresh, maxval, type) threshold : 极限,临界值,阈值 ret: 一个数 s ...

  3. C# 指针操作图像 二值化处理

    /// <summary> /// 二值化图像 /// </summary> /// <param name="bmp"></param& ...

  4. OpenCV---超大图像二值化和空白区域过滤

    超大图像的二值化方法 1.可以采用分块方法, 2.先缩放处理就行二值化,然后还原大小 一:分块处理超大图像的二值化问题 def big_image_binary(image): print(image ...

  5. 10、OpenCV Python 图像二值化

    __author__ = "WSX" import cv2 as cv import numpy as np #-----------二值化(黑0和白 255)---------- ...

  6. python实现超大图像的二值化方法

    一,分块处理超大图像的二值化问题   (1) 全局阈值处理  (2) 局部阈值 二,空白区域过滤 三,先缩放进行二值化,然后还原大小 np.mean() 返回数组元素的平均值 np.std() 返回数 ...

  7. [转载+原创]Emgu CV on C# (四) —— Emgu CV on 全局固定阈值二值化

    重点介绍了全局二值化原理及数学实现,并利用emgucv方法编程实现. 一.理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数)  1.概述 图像二值化是图像处理中的一项基本技术,也 ...

  8. 灰度图像二值化-----c++实现

    前天闲着没事干,就写了写BMP图像处理,感觉大家还比较感兴趣..所以现在没事,继续更新..这次简单的写了灰度图像二值化..这是什么概念呢? 图像的二值化的基本原理 图像的二值化处理就是将图像上的点的灰 ...

  9. Wellner 自适应阈值二值化算法

    参考文档: Adaptive Thresholding for the DigitalDesk.pdf       Adaptive Thresholding Using the Integral I ...

随机推荐

  1. CAN总线位仲裁技术

    CAN总线位仲裁技术 只要总线空闲,任何单元都可以开始发送报文. 要对数据进行实时处理,就必须将数据快速传送,这就要求数据的物理传输通路有较高的速度.在几个站同时需要发送数据时,要求快速地进行总线分配 ...

  2. contiki学习心路历程【转】xukai871105 大神

    https://blog.csdn.net/xukai871105/article/details/9072993

  3. juc线程池原理(三):ThreadFactory、拒绝策略、提交任务、关闭线程池

    概要 (一) ThreadFactory 线程池中的ThreadFactory是一个线程工厂,线程池创建线程都是通过线程工厂对象(threadFactory)来完成的. 类图如下: 上面所说的thre ...

  4. Oracle redo与undo

    Undo and redo Oracle最重要的两部分数据,undo 与redo,redo(重做信息)是oracle在线(或归档)重做日志文件中记录的信息,可以利用redo重放事务信息,undo(撤销 ...

  5. 海外开发者推荐:10个顶级2D游戏资源站

    转自:http://www.gamelook.com.cn/2015/12/239038 Gamelook报道/随着手游市场的持续增长,HTML5的发展以及大型发行商的支持,2D游戏的数量变得越来越多 ...

  6. C# 面向切面编程--监控日志记录方案

    背景:现在公司整体在做监控平台,要求把各个部分的细节都记录下来,在前台页面上有所显示,所以现在需要做的就是一个监控日志的记录工作,今天讲的就是渲染监控日志的例子. 现状:当前的渲染程序没有为监控日志记 ...

  7. Apache rewrite 出现 400 Bad Request 的解决方法

    <VirtualHost *:80 *:81>         ServerAdmin deng5765@163.com         DocumentRoot /active/www/ ...

  8. el表达式动态拼接变量_c:set的用法

    转自:https://blog.csdn.net/xb12369/article/details/39581955如 何在${}中使用${},例:${user.name_${user.id}},use ...

  9. 10 个你需要了解的 Linux 网络和监控命令

    我下面列出来的10个基础的每个linux用户都应该知道的网络和监控命令.网络和监控命令类似于这些: hostname, ping, ifconfig, iwconfig, netstat, nsloo ...

  10. c# 程序调用cmd执行命令如SVN.exe

    c# 程序调用cmd执行命令如SVN.exe string str = Console.ReadLine(); System.Diagnostics.Process p = new System.Di ...