一. 图像形态学处理 —— 膨胀和腐蚀

halcon 开运算和闭运算_halcon 开运算和闭运算

图解图像腐蚀和膨胀


二. 开运算与闭运算:

    开运算:先腐蚀后膨胀,能够消除图像区域外的小白点(噪声)。

    闭运算:先膨胀后腐蚀,能够消除图像区域内的小黑点(噪声)。


halcon 开运算和闭运算_邻域_02

图解图像开运算与闭运算

       为什么有了膨胀、腐蚀还要开运算闭运算呢?其实开闭运算最重要的一点就是,可以保持物体原有大小。然后一个是消除物体外部噪声(开运算)的另一个是增强物体之间连接点(闭运算)的。


        


        数学形态学操作通过对每个输入像素的邻域应用一个操作来实现。规则和邻域的结合被称为构造成员。尽管一些规则已经成为图像处理的实际标准,但是使用什么类型的算法规则应用于邻域还是有很大的选择自由的。


        在 ITK 中是在最小化腐蚀和最大化膨胀的典型规则下实现的。构造成员是作为一个 NeighborhoodOperator 来实现的。事实上,默认的构造成员是itk::BinaryBallStructuringElement 类。这个类是使用像素类型和输入图像维来进行实例化的。


        构造成员不是一个引用记数类。因此它是作为一个 C++ 堆栈而不是使用 New( ) 和 SmartPointers 来创建的。使用 SetRadius( ) 方式来定义和构造成员相关的邻域半径并调用CreateStructuringElement( )方式以便于初始化操作符。如下面所阐述的那样,使用 SetKernel( )方式将构造成员的结果传递给数学形态学滤波器。


#include "itkImageFileReader.h"//读取头文件
#include "itkImageFileWriter.h"//写入头文件
#include "itkGDCMImageIO.h"//ImageIo头文件
#include "itkIntensityWindowingImageFilter.h"//调窗处理头文件
#include "itkBinaryThresholdImageFilter.h"//二值门限处理头文件
#include "itkBinaryBallStructuringElement.h"//基本球形
#include "itkBinaryErodeImageFilter.h"
#include "itkBinaryDilateImageFilter.h"

int main(int argc, char* argv[])
{
    typedef  signed short  PixelType; // signed short 数据类型
    typedef itk::Image< PixelType, 2 >   ImageType;//image类型

    typedef itk::ImageFileReader< ImageType >  ReaderType;
    typedef itk::ImageFileWriter< ImageType >  WriterType;
    ReaderType::Pointer reader = ReaderType::New();//reader
    WriterType::Pointer writer = WriterType::New();//writer

    typedef itk::GDCMImageIO ImageIOType;
    ImageIOType::Pointer gdcmImageIO = ImageIOType::New();//gdcmImageIO

    reader->SetFileName("D:/leg_dcm/IM70.dcm");//读取文件
    reader->SetImageIO(gdcmImageIO);
    reader->Update();

    //调窗处理
    typedef itk::IntensityWindowingImageFilter<ImageType, ImageType >  IntensityFilterType;
    IntensityFilterType::Pointer intensityWindowing = IntensityFilterType::New();
    intensityWindowing->SetWindowMinimum(124);//最小窗值
    intensityWindowing->SetWindowMaximum(126);//最大窗值
    intensityWindowing->SetOutputMinimum(0);//
    intensityWindowing->SetOutputMaximum(255); // 
    intensityWindowing->SetInput(reader->GetOutput());//
    intensityWindowing->Update();

    //二值门限
    typedef itk::BinaryThresholdImageFilter<ImageType, ImageType > ThresholdingFilterType;
    ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();
    thresholder->SetInput(intensityWindowing->GetOutput());
    thresholder->SetUpperThreshold(255);//上下阈值参数设定
    thresholder->SetLowerThreshold(250);
    thresholder->SetOutsideValue(0);//输出值设定,背景为0,前景为255
    thresholder->SetInsideValue(255);
    thresholder->Update();

    //用于二值图像的构造成员
    typedef itk::BinaryBallStructuringElement< PixelType, 2  > StructuringElementType;
    //模板参数为<像素类型,输入图像维度>
    StructuringElementType  structuringElement;
    structuringElement.SetRadius(1);   //领域大小为3*3,设定邻域半径
    structuringElement.CreateStructuringElement();

    //先膨胀再腐蚀
    typedef itk::BinaryErodeImageFilter <ImageType, ImageType, StructuringElementType >  ErodeFilterType;// 腐蚀,需要用输入、输出图像类型和构造成员实例化
    typedef itk::BinaryDilateImageFilter <ImageType, ImageType, StructuringElementType >  DilateFilterType;// 膨胀,需要用输入、输出图像类型和构造成员实例化

    DilateFilterType::Pointer binaryDilate = DilateFilterType::New();
    binaryDilate->SetInput(thresholder->GetOutput());
    binaryDilate->SetKernel(structuringElement);
    binaryDilate->SetDilateValue(255);//膨胀后新像素像素值
    binaryDilate->Update();

    ErodeFilterType::Pointer  binaryErode = ErodeFilterType::New();
    binaryErode->SetInput(binaryDilate->GetOutput());
    binaryErode->SetKernel(structuringElement);
    binaryErode->SetErodeValue(255);//腐蚀后新像素像素值
    binaryErode->Update();

    //开运算(腐蚀)后二值门限处理
    typedef itk::BinaryThresholdImageFilter<ImageType, ImageType > ThresholdingFilterType;
    ThresholdingFilterType::Pointer thresholder1 = ThresholdingFilterType::New();
    thresholder1->SetInput(binaryErode->GetOutput());
    thresholder1->SetUpperThreshold(255);//上下阈值参数设定
    thresholder1->SetLowerThreshold(250);
    thresholder1->SetOutsideValue(0);//输出值设定,背景为0,前景为255
    thresholder1->SetInsideValue(255);
    thresholder1->Update();

    writer->SetInput(thresholder1->GetOutput());
    writer->SetFileName("D:/004.dcm");
    writer->SetImageIO(gdcmImageIO);
    writer->Update();

    return EXIT_SUCCESS;
}