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