细化算法一般都对二值图像的骨架提取,这是一个从面变成线,还要保持原有图像形态的过程。是一个渐变的过程,少不了的迭代,就像对一棵树一层一层的剥皮,最后就剩下芯(sorry,我这里的说法有错误,也有一次产生骨架的算法,不迭代,之前的认知是错误的!)。
细化算法的差异在于迭代的方法,理论知识大家自行搜索,都是基础算法。这里,itk中的类叫做itkBinaryThinningImageFilter(这类只是针对2D图像用的,还有一个3D升级版叫做:itkBinaryThinningImageFilter3D),用法依然很easy,如下:
typedef itk::BinaryThinningImageFilter <ImageType, ImageType> ImageFilterType;
ImageFilterType::Pointer binaryThinningImageFilter = ImageFilterType::New();
binaryThinningImageFilter->SetInput(input_data);
binaryThinningImageFilter->Update();
接下来看下itk官方是怎么写的细化算法,所有的算法都在一个叫做“ComputeThinImage”的函数中,150行就搞定了~
1.代码段1:
typedef typename NeighborhoodIteratorType::OffsetType OffsetType;
OffsetType o2 = {{0,-1}};
OffsetType o3 = {{1,-1}};
OffsetType o4 = {{1,0}};
OffsetType o5 = {{1,1}};
OffsetType o6 = {{0,1}};
OffsetType o7 = {{-1,1 }};
OffsetType o8 = {{-1,0}};
OffsetType o9 = {{-1,-1}};
看到了么,是不是很熟悉的8邻域?(几乎所有的基础图像算法都是从这里开始的)
2.代码段2:
// These tests correspond to the conditions listed in Gonzalez and Woods
bool testA;
bool testB;
bool testC;
bool testD;
看注释!ABCD分别是在 Gonzalez and Woods 中列出的四种条件,是不是很熟悉?觉得不熟悉的人请回去重新读大一,谢谢~ 冈萨雷斯认识不?
这四种条件的详细解释请看
这里。
最终经过多次迭代,就得到了细化结果,说了这么多,其实原型就是传说中的"快速zhang并行算法"。
以上是迭代细化,接下来研究下直接细化方法。
1. 欧几里得距离变换,将二值图像变成灰度图像。反复对原图进行“减细”,将减细结果与中间结果做算术“叠加”,其终止条件是:“若对原图再减细,则将成为全零矩阵”:
itkApproximateSignedDistanceMapImageFilter
itkSignedMaurerDistanceMapImageFilter
itkDanielssonDistanceMapImageFilter
itkSignedDanielssonDistanceMapImageFilter:distanceMap,voronoiMap,distanceVectors
itkFastChamferDistanceImageFilter
itkIsoContourDistanceImageFilter
typedef itk::ApproximateSignedDistanceMapImageFilter< ImageType, FloatImageType > ImageFilterType;
ImageFilterType::Pointer ImageFilter = ImageFilter ::New();
ImageFilter ->SetInput(image);
ImageFilter ->SetInsideValue(255);
ImageFilter ->SetOutsideValue(0);
ImageFilter ->Update();
2. 骨架图就是从变换图中提取出具有相对最大灰度值的那些像素所组成的图像:
itkValuedRegionalMaximaImageFilter
itkMinimumMaximumImageCalculator
itkRegionalMaximaImageFilter
typedef itk::RegionalMaximaImageFilter <ImageType, ImageType > ImageFilter;
ImageFilter::Pointer filter = ImageFilter::New ();
filter->SetInput(image);