分水岭分割对图像特征基于梯度下降法和沿区域边界分析弱点将像素进行分类。
该类可从标量值图像输入自动生成分段、标记图像的层次结构。
概述和术语
该过滤器实现了图像分割算法的非流版本,通常称为“分水岭分割”。 分水岭分割因其算法将区域分割为流域盆地的方式而得名。 如果函数 f 是在图像域上定义的连续高度函数,则集水盆地定义为其最陡下降路径终止于 f 的相同局部最小值的点集。
高度函数(输入)的选择取决于应用,并且基本分水岭算法的运行独立于该选择。 对于基于强度的图像数据,通常可以使用某种梯度幅度计算作为输入。
分水岭算法步骤:
首先,通过沿着每个点的最陡下降路径追踪到局部最小值,将所有点初步分类为集水盆地区域;
然后,根据某些显着性度量(例如最小边界高度)分析相邻区域及其之间的边界,以生成相邻区域之间的合并树, 这些合并发生在不同的最大显着性值处,达到指定显着性“洪水级别”的所有可能合并的集合在本文档中被称为“合并树”。
打个比方,洪水位是反映流入集水盆地的降水量的值。 随着洪水水位上升,相邻路段之间的边界被侵蚀,这些路段合并, 洪水级别的最小值为零,最大值为输入图像中最高值和最低值之间的差。
请注意,一旦完成初始分析和分割以生成合并树,在恒定时间内生成标记图像的层次结构就很简单了,该算法的复杂性在于合并树的计算,创建该树后,可以通过简单地从树中识别分段合并的子集来重新标记初始分段图像,以反映在树中找到的任何最大显着性值。
实施细节
该过滤器是几个较低级别流程对象(名称空间“watershed”中的分水岭算法组件)的包装器,组件类被设计为在数据流或非数据流模式下运行,在此类的GenerateData()方法中构造的管道不支持流式传输。
输入
该过滤器的输入是任意维度的标量itk::Image
,假设该输入图像表示某种基于要分割的原始图像的高度函数或边缘图(例如由 itk::GradientMagnitudeImageFilter
生成的图像),除了阈值步骤之外,该过滤器不会对其输入进行任何预处理,该算法没有明确要求输入为任何特定数据类型,但建议使用浮点或双精度数据。
建议对输入到该算法的标量图像进行预处理是使用 itk::AnisotropicDiffusionImageFilter
子类之一来平滑原始图像,然后基于梯度或曲率执行某种边缘计算。
输出
该过滤器将生成 IdentifierType
整数类型且与输入图像具有相同维度的 itk::Image
, IdentifierType
输出图像在本文档中称为“标记图像”,图像中的每个像素都分配有一个IdentifierType
整数标签,将其分组在连接区域内。
注意事项
有两个参数控制该滤波器的输出:阈值Threshold 和水平Level ,两个参数的单位都是输入中最大高度值的百分比。
**Threshold **用于设置处理过程中使用的绝对最小高度值,,假设阈值去除的浅层区域不太重要,提高这个阈值百分比可以有效地减少输入中局部最小值的数量,从而产生具有更少区域的初始分割。
Level参数控制图像隐喻泛滥的深度,也就是说,它设置了结果中感兴趣的最大显着性值,升高和降低级别会影响基本分段中合并以产生最终输出的分段数量,级别 1.0 类似于将图像淹没到图像中最大值的 100% 的深度, 0.0 级别产生基本分割,通常会过度分割,感兴趣的级别值通常较低(即小于约 0.40 或 40%),因为较高的值很快就会开始对图像进行欠分割。
初始分割完成后,Level
参数可用于在恒定时间内创建输出图像的层次结构,典型场景可能如下所示:对于过滤器的初始执行,将级别设置为预计可能感兴趣的最大显着性值,一旦该过程对象的初始 Update()
完成,就可以在低于初始设置的任何位置操作 Level
,而不会触发分段微型管道的完整更新,现在生成新输出所需要做的就是对输出图像进行简单的重新标记。
Threshold
和 Level
参数通过类的 Get/SetThreshold()
和 Get/SetLevel()
方法进行控制。
常用的成员函数:
SetInput()
:设置输入图像Set/GetThreshold()
:设置/获取输入阈值参数,单位是图像中最大深度的百分比Set/GetLevel()
:设置/获取从初始分段生成合并树的洪水级别GetSegmentTree()
:从 TreeGenerator 成员过滤器获取分割树GetBasicSegmentation()
:从Segmenter成员过滤器中获取基本分段示例代码:
#include "itkImage.h"
#include "itkWaterShedImageFilter.h"
typedef itk::Image<float, 3> FloatImageType;
bool watershedImageFilter(FloatImageType* image, double threshold, double level)
{
typedef itk::WatershedImageFilter<FloatImageType> WatershedFilterType;
typename WatershedFilterType::Pointer watershedFilter = WatershedFilterType::New();
watershedFilter->SetInput(image);
//Level 控制分水岭深度;Threshold控制输入的下阈值
//两个参数均设置为输入图像中最大深度的百分比 (0.0 - 1.0)
watershedFilter->SetThreshold(threshold);
watershedFilter->SetLevel(level);
try
{
watershedFilter->Update();
}
catch (itk::ExceptionObject& ex)
{
//读取过程发生错误
std::cerr << "Error: " << ex << std::endl;
return false;
}
return true;
}
该类使用形态学算子实现分水岭分割。
分水岭像素标记为 0,TOutputImage 应该是整数类型,输出图像的标签没有特定的顺序。 可以通过将此过滤器的输出传递给 RelabelComponentImageFilter
来重新排序标签,使对象标签连续并根据对象大小进行排序。
常用的成员函数:
Set/GetFullyConnected()
:设置/获取连通分量是严格通过面连通性还是通过面+边+顶点连通性定义, 默认为完全连接关闭,对于1像素宽的对象,请使用 ExcellentConnectedOn
,函数FullyConnectedOn/Off()
功能相同Set/GetLevel()
:设置/获取分水岭深度级别Set/GetMarkWatershedLine()
:设置/获取是否必须标记分水岭像素,默认为 true
,设置为 false
不仅可以避免写入分水岭像素,还可以降低算法复杂度#include "itkImage.h"
#include "itkMorphologicalWatershedImageFilter.h"
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<short, 3> ShortImageType;
bool morphologicalWatershedImageFilter(FloatImageType* image, ShortImageType* outImage, double level)
{
typedef itk::MorphologicalWatershedImageFilter<FloatImageType, ShortImageType> MorphWatershedFilterType;
typename MorphWatershedFilterType::Pointer watershedFilter = MorphWatershedFilterType::New();
watershedFilter->SetInput(image);
watershedFilter->SetLevel(level);
//watershedFilter->SetFullyConnected(true);
try
{
watershedFilter->Update();
}
catch (itk::ExceptionObject& ex)
{
//读取过程发生错误
std::cerr << "Error: " << ex << std::endl;
return false;
}
outImage = watershedFilter->GetOutput();
return true;
}
该类使用两个种子点隔离流域盆地。
IndependentWatershedImageFilter
使用 ReplaceValue1
标记与 Seed1
位于同一流域盆地且与 Seed2
不同的像素,滤波器调节水位,直到两个种子在不同的盆中, 用户可以置分水岭阈值,该算法使用二分搜索来调整上水位,从 UpperValueLimit
开始。
常用的成员函数:
#include "itkImage.h"
#include "itkIsolatedWatershedImageFilter.h"
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<short, 3> ShortImageType;
bool isolatedWatershedImageFilter(FloatImageType* image, ShortImageType* outImage)
{
FloatImageType::IndexType seed1 = { 5,5,5 };
FloatImageType::IndexType seed2 = { 10,10,10 };
short replaceValue1 = 255;
short replaceValue2 = 0;
double threshold = 0.0;
typedef itk::IsolatedWatershedImageFilter<FloatImageType, ShortImageType> IsolatedWatershedFilterType;
typename IsolatedWatershedFilterType::Pointer isolateWaterShedFilter = IsolatedWatershedFilterType::New();
isolateWaterShedFilter->SetInput(image);
isolateWaterShedFilter->SetSeed1(seed1);
isolateWaterShedFilter->SetSeed2(seed2);
isolateWaterShedFilter->SetReplaceValue1(replaceValue1); //替换seed1的连通区域值,即包含seed1盆地内的像素值
isolateWaterShedFilter->SetReplaceValue2(replaceValue2); //替换seed2的连通区域值,即包含seed2盆地内的像素值
isolateWaterShedFilter->SetThreshold(threshold); //设置分水岭阈值
try
{
isolateWaterShedFilter->Update();
}
catch (itk::ExceptionObject& ex)
{
//读取过程发生错误
std::cerr << "Error: " << ex << std::endl;
return false;
}
outImage = isolateWaterShedFilter->GetOutput();
return true;
}