2019-08-23 13:00:42 studyeboy 阅读数 90

灰度图像处理成纯黑白(二值化)图像后,轮廓边缘经常出现毛刺。如下图所示,“工”字的上面一横中,边缘有几个突出点,下边缘有两个凹陷点,在“业”字左侧竖条中有突出点,下面一横中有凹陷点。

在这里插入图片描述
产生毛刺的原因
在扫描或拍摄所生成的原始图像中,轮廓边缘像素点的值其实是介于“白”与“黑”之间的“灰”,所以整个边缘看起来很光滑,不生硬,但变成纯黑白后,像素点非黑即白,不再有中间灰,所以总有那么几个点可能就因为值稍微差了一点,就与周围的不一样了。

解决办法

  • 用高斯模糊来消除毛刺。另外对图像进行放大也会拉出一些模糊空间,一方面也可以减轻毛刺,另一方面可以避免转成纯黑白图像后出现笔画粘连(扫描书籍图像处理)。
  • 数字图像处理中的形态学方法是把孤立点。凹陷点,然后去除或填平。

ScanTailor中就是用形态学方法是把孤立点、凹陷点,然后去除或填平。

原理

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

scanTailor中总结出来的模板共有6个,分别是:
在这里插入图片描述
在模板中共有5种符号:X表示黑点,空格表示白点,问号表示黑点白点均可,减号表示去除点,加好表示填充点。所以上表中前3个模板就表示如果在一排黑点外有孤立点,则孤立点应该去除;后面3个模板则表示如果黑点中间有凹陷,则应该进行填充。

在ScanTailor中,每个模板会在上、下、左、右4个方向分别匹配,以模板1为例,其实在内部会扩充为以下4个模板进行匹配:
在这里插入图片描述
因此,6个模板其实内部要匹配24次,在图像较大时会显得很慢,所以经常用模糊来进行平滑。

整个处理过程的核心是在图像中查找模板的所有匹配点,即需要去除、填充的点,用的是击中-击不中变换(Hit-Miss Transform)。一般都用腐蚀、膨胀等形态学基本操作的组合来实现这个变换。

相关资料

ScanTailor

ScanTailor是一个开源免费的扫描文档后期处理软件主要把DIY Book Scanner拍摄制成的图像后期加工,形成完美的PDF文档。绝大多数功能都可以自动完成,虽然还是需要手动微调和最后校对。处理一本图书的时间大致1个小时。

Adobe Acrobat

Adobe Acrobat有个不受重视但是很有用的功能,叫作Clear Scan,能够批量识别扫描文档,美化文档(包括文字/图片矢量化,纠正歪斜等),并且生成可全文索引,文件更小,而版式和扫描完全一样的PDF文件。
在这里插入图片描述

参考资料

[1] 教程十七:二值化图像去毛刺
[2] 我的书籍、文献电子化全套解决方案

2017-06-14 16:22:02 rabbitbride 阅读数 742

图像毛刺去除是图像处理中的一个重要内容。在图像特征提取的过程中,毛刺会严重影响图像的结构,属于噪声污染。


itk中提供了专门的毛刺去除算法类:itkBinaryPruningImageFilter。
作用:该过滤器能输入图像中移除小于一定长度的“刺”。
输入:二值图像。
该滤波器是一种顺序剪枝算法,计算时间依赖于图像的大小。

该算法用在二维图像,用法很简单:

  typedef itk::BinaryPruningImageFilter <ImageType, ImageType >
          ImageFilterType;
  ImageFilterType::Pointer pruneFilter = ImageFilterType::New();
  pruneFilter->SetInput(image);
  pruneFilter->SetIteration(iteration);
  pruneFilter->Update();
代码分析:
1..h中的私有变量:

unsigned int           m_Iteration; //迭代次数 1
2.准备数据:这里能看到又一种数据初始化方法,开源就是这样,八仙过海,各显神通~

template <class TInputImage,class TOutputImage>
void 
BinaryPruningImageFilter<TInputImage,TOutputImage>
::PrepareData(void) 
{  
  itkDebugMacro(<< "PrepareData Start");
  OutputImagePointer pruneImage = GetPruning();
//开辟内存空间
  InputImagePointer  inputImage  = 
    dynamic_cast<const TInputImage  *>( ProcessObject::GetInput(0) );

  pruneImage->SetBufferedRegion( pruneImage->GetRequestedRegion() );
  pruneImage->Allocate();

  typename OutputImageType::RegionType region  = pruneImage->GetRequestedRegion();

//迭代器
  ImageRegionConstIterator< TInputImage >  it( inputImage,  region );
  ImageRegionIterator< TOutputImage > ot( pruneImage,  region );

  it.GoToBegin();
  ot.GoToBegin();

  itkDebugMacro(<< "PrepareData: Copy input to output");
 
  while( !ot.IsAtEnd() )
      {
	  //数据一一对应
      ot.Set( static_cast< typename OutputImageType::PixelType >( it.Get() ) );
      ++it;
      ++ot;
      }
  itkDebugMacro(<< "PrepareData End");
}
3.起细化作用的后处理方法,是不是感觉和细化算法有什么瓜葛?用的基础结构都差不多。

template <class TInputImage,class TOutputImage>
void 
BinaryPruningImageFilter<TInputImage,TOutputImage>
::ComputePruneImage() 
{
  itkDebugMacro( << "ComputeThinImage Start");
  OutputImagePointer    pruneImage          =  GetPruning();

  typename OutputImageType::RegionType region  = pruneImage->GetRequestedRegion();
//NeighborhoodIterator 这个迭代器设计的帅啊
  typename NeighborhoodIteratorType::RadiusType radius;
  radius.Fill(1);//邻域半径设为1
  NeighborhoodIteratorType ot( radius, pruneImage, region );//参数1:半径;参数2:图像;参数3:区域
//二维8邻域
  typename NeighborhoodIteratorType::OffsetType offset1 = {{-1,-1}};
  typename NeighborhoodIteratorType::OffsetType offset2 = {{-1,0}};
  typename NeighborhoodIteratorType::OffsetType offset3 = {{-1,1 }};
  typename NeighborhoodIteratorType::OffsetType offset4 = {{0,1}};
  typename NeighborhoodIteratorType::OffsetType offset5 = {{1,1}};
  typename NeighborhoodIteratorType::OffsetType offset6 = {{1,0}};
  typename NeighborhoodIteratorType::OffsetType offset7 = {{1,-1}};
  typename NeighborhoodIteratorType::OffsetType offset8 = {{0,-1}};
  
  unsigned int count = 0;
  while(count < m_Iteration)//m_Iteration:迭代次数,默认3次
  {
    ot.GoToBegin();//迭代开始
    while( ! ot.IsAtEnd() )//不止不休
    {
      if (ot.GetCenterPixel())
       {
         PixelType genus;
         genus  = ot.GetPixel(offset1) + ot.GetPixel(offset2);
         genus += ot.GetPixel(offset3) + ot.GetPixel(offset4);
         genus += ot.GetPixel(offset5) + ot.GetPixel(offset6);
         genus += ot.GetPixel(offset7) + ot.GetPixel(offset8);
         if (genus < 2)//如果8邻域的灰度值小于2,则把该点抹掉
           {
             genus = 0;
             ot.SetCenterPixel( genus );
           }
       }

      ++ot;//下一个
	}
    ++count;
  }  
    itkDebugMacro( << "ComputeThinImage End");
}
4.#include "itkNeighborhoodIterator.h"
注意这里用到一个很帅的迭代器:itkNeighborhoodIterator,用法看上面代码中的注释,比起自己写的函数好用多了。
5.最后,看下算法设计的作者:
 * Rafael C. Gonzales and Richard E. Woods. 
 * Digital Image Processing. 
 * Addison Wesley, 491-494, (1993).
又见冈萨雷斯 and 伍兹~ 什么叫经典?他俩几乎把数字图像处理领域的基础方法都写完了!膜拜吧!

参考文献:
1.http://www.vtk.org/Wiki/ITK/Examples/Morphology/BinaryPruningImageFilter
2.http://blog.chinaunix.net/uid-25510439-id-3126204.html
3.http://blog.163.com/zhoumhan_0351/blog/static/3995422720084190493758/

2017-04-14 20:58:33 u010368556 阅读数 325

形态学,即数学形态学(mathematical Morphology),是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-most discriminative)的形状特征,如边界和连通区域等。同时像细化、像素化和修剪毛刺等技术也常应用于图像的预处理和后处理中,成为图像增强技术的有力补充。

本文主要包括以下内容

  • 二值图像的基本形态学运算, 包括腐蚀、膨胀、开和闭。
  • 二值形态学的经典应用, 包括击中击不中变换、边界提取和跟踪、区域填充、提取连通分量、细化和像素化, 以及凸壳
  • 灰度图像的形态学运算, 包括灰度腐蚀、灰度膨胀、灰度开和灰度闭
  • 本章的典型案例分析
    • 在人脸局部图像中定位嘴的中心
    • 显微镜下图像的细菌计数
    • 利用顶帽变换(top-hat)技术解决光照不均问题
2019-06-08 20:35:03 qq_43660987 阅读数 82

1,图像形态学概念
形态学,即数学形态学(mathematical Morphology),,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-most discriminative)的形状特征,如边界和连通区域等。同时像细化、像素化和修剪毛刺等技术也常应用于图像的预处理和后处理中,成为图像增强技术的有力补充。
在这里插入图片描述

2,形态学图像处理操作
按照处理对象不同,分为对二值图像处理和对灰度图像处理,处理函数大部分都是相同的,除了击中或击不中变换(仅适用于二值图像)。
2.1 二值图像
(1)膨胀:
膨胀是图像中的目标“生长”或“变粗”的操作
(2)腐蚀:
腐蚀是图像中的目标“收缩”或“变细”的操作。
(3)开操作:
先腐蚀,再膨胀 。开操作可以去除所有不能包含结构元的部分,平滑目标的轮廓,断开了细的连接部分。
(4)闭操作:
先膨胀,再腐蚀 。闭操作可以平滑目标的轮廓,并且连接窄的断裂并填满细长的“港湾”,填满闭结构元小的洞。
(5)击中或击不中变换:
结构元是一对儿结构元,A被B1腐蚀 ∩ A的补集被B2腐蚀
(6)标记连通分量:
连通分量就是前景图像内部单个元素之间的关系,是通过连通得到的像素集合。连通分为4连通和8连通。
(8)形态学重建:
重建是一种形态学变换,包括一幅原图像G(模板),一幅标记图像F(标记),一个结构元B。其中F被包含于G。有一些重建和其他操作结合的方法并能取得很好的效果。

2.2 灰度图像
(1)膨胀和腐蚀:
从膨胀结果中减去腐蚀的结果,可产生形态学梯度,这是图像局部灰度变化的一种度量。
(2)开操作和闭操作:
开操作可以去除小的亮点细节,同时保留所有的灰度并保证较大的亮区特征不受干扰。闭操作去除比结构元校的黑暗结构。

两者组合可以平滑图像并去除噪声;交替顺序滤波;开操作可以用来补偿非均匀照明的背景(就是图像背景的亮度不一样,有暗有亮);顶帽操作,原图像减去图像开操作结果;底帽操作,原图像减去图像闭操作结果(这两个操作配合可以增强图像的对比度)
(3)重建:
抑制小的灰度峰值;用重建移去复杂的背景(结合腐蚀,重建的开操作,并选择合适的结构元)
3,总结:
膨胀和腐蚀常用于边界的提取。边界的提取是通过对目标图像进行腐蚀或膨胀处理,比较结果图像和原图像的差别来实现的。内边界的提取利用图像的腐蚀处理得到原图像的一个收缩,再将收缩结果和目标图像进行异或运算。外边界的提取对目标图像进行膨胀处理,然后利用膨胀结果与原目标图像进行异或运算。
开操作和闭操作:开运算用来图像进行消噪处理,同时,图像的开运算可以选择性地保留目标图像中符合结构原色几何性质的部分,而过滤掉相对结构元素而言残损的部分。闭运算用来对目标图像分开的区域进行连接及对图像中细小缝隙进行填补,通过适当地选择结构元素,图像的闭运算可以令图像的填补结果具有一点的几何特征,适当地对图像进行闭运算有时可以使图像变得更加清晰连贯,同时可以避免原图像中线条加粗。

3,结构元
结构元本质上和掩膜比较相似,也是0-1矩阵,不过进行的是集合运算而不是卷积运算。除了自己写结构元,也有特定的函数来产生结构元。
在这里插入图片描述

2017-11-27 14:15:16 rosefun96 阅读数 165

1、形态学运算

1.1腐蚀:
matlab指令,

I=imerode(I,se);%se为结构元素。

MATLAB构造结构元素:
se=strel(shape,parameters)

1.2膨胀
I=imdilate(I,se)

1.3开运算
相当于,先腐蚀后膨胀处理;
使图像变得光滑,断开狭窄处连接和消除毛刺。

I=imopen(I,se);

1.4闭运算
相当于,先膨胀后腐蚀。
使图像光滑,弥合狭窄的间断。
I=imclose(I,se)

2、区域填充

在区域内,放一个种子(一个像素),通过十字架进行扩充,同时限制在区域内(和区域的补空间求交);不断重复这一步骤。

图像平滑

阅读数 2827

没有更多推荐了,返回首页