本文要写的是TopHat算法,这个算法属于形态学变换,主要应用在解决当光照不均等条件引起的背景灰度不均问题(敲黑板,TopHat是应用在灰度图像的,不是二值图像!)。TopHat算法本质是形态学变换中开闭运算的组合。开运算能消除灰度图像中较亮的细节,闭运算则能消除较暗的细节,(如果对应到坐标系,亮对应波峰,暗对应波谷)。
WhiteTopHat:原图像-开运算结果

BlackTopHat:闭运算结果-原图像

黑白格机器学习 黑白算法_模版

itk中提供的类名叫做:itkWhiteTopHatImageFilter;itkBlackTopHatImageFilter


使用方法:

typedef itk::BinaryBallStructuringElement<PixelType, ImageDimension > SRType;
SRType kernel;
kernel.SetRadius( 22 );
kernel.CreateStructuringElement();

//typedef itk::WhiteTopHatImageFilter<ImageType,ImageType,SRType > TopHatFilterType;
typedef itk::BlackTopHatImageFilter<ImageType,ImageType,SRType > TopHatFilterType;
TopHatFilterType::Pointer topHatFilter = TopHatFilterType::New();
topHatFilter->SetInput( intput_data );
topHatFilter->SetSafeBorder( false);
topHatFilter->SetKernel( kernel );
topHatFilter->Update();



源码分析,看下之前的理论和实际能不能对得上。这里只看WhiteTopHatImageFilter,Black反过来就好了:


1.数据生成


template <class TInputImage, class TOutputImage, class TKernel>
void 
WhiteTopHatImageFilter<TInputImage, TOutputImage, TKernel>
::GenerateData()
{
  // Create a process accumulator for tracking the progress of this minipipeline 创建了一个能跟踪算法步骤的管道?
  ProgressAccumulator::Pointer progress = ProgressAccumulator::New();
  progress->SetMiniPipelineFilter(this);

  // Allocate the output 初始化输出数据
  this->AllocateOutputs();
  
  // Delegate to an opening filter.对灰度图像做开运算 
  typename GrayscaleMorphologicalOpeningImageFilter<TInputImage, TInputImage, TKernel>::Pointer
    open = GrayscaleMorphologicalOpeningImageFilter<TInputImage, TInputImage, TKernel>::New();

  open->SetInput( this->GetInput() );//输入图像
  open->SetKernel( this->GetKernel() );//输入模版
  open->SetSafeBorder( m_SafeBorder );//设置安全边界
  
  // Need to subtract the opened image from the input 两图像做相减
  typename SubtractImageFilter<TInputImage, TInputImage, TOutputImage>::Pointer
    subtract=SubtractImageFilter<TInputImage,TInputImage,TOutputImage>::New();

  subtract->SetInput1( this->GetInput() );//输入原图像
  subtract->SetInput2( open->GetOutput() );//输入开运算结果

  // graft our output to the subtract filter to force the proper regions
  // to be generated 按照输出数据的大小设置减法滤波器的结果
  subtract->GraftOutput( this->GetOutput() );

  // run the algorithm
  progress->RegisterInternalFilter(open,.9f);
  progress->RegisterInternalFilter(subtract,.1f);

  subtract->Update();

  // graft the output of the subtract filter back onto this filter's
  // output. this is needed to get the appropriate regions passed
  // back.刷新输出数据
  this->GraftOutput( subtract->GetOutput() );

}


挺简单的算法,是不是自己写一个也差不多呢?官方也是这么写的,再次说明图像处理不是黑魔法,只要弄清楚原理,你也可以的。

这里有个需要注意的点,在TopHat中,需要预设模版,模版的尺寸会影响滤波的结果。模版应该比目标大一点,刚好能覆盖过目标的细节。对应代码中的itkBinaryBallStructuringElement设置。实际上,这也是TopHat算法的优势,可以灵活的设置模版来适应不同的情况。

感谢网友分享,下面的解释很明朗,贴一下:
图像f 的顶帽变换h定义为图像f与图像f的开运算之差, 可表示为:  h = f -(f*s) 

黑白格机器学习 黑白算法_灰度图像_02

黑白格机器学习 黑白算法_模版_03

有一次去莫干山玩,路上居然遇到一只狐狸,这可太稀奇了。心血来潮,我远远地冲它大喝一声:“孽畜!还不快快现出原形?!”狐狸愣了一下,居然开口说话了:“这本来就是原形啊!”“妈呀有妖怪!”我大叫一声,撒丫子就跑,狐狸嗷地一声跟在我后面跑,边跑边叫:“哪儿,哪儿有妖怪啊?别丢下我!吓死我了!”

黑白格机器学习 黑白算法_模版_04