前言
区域生长算法已被证明是一种有效的图像分割方法。区域生长算法的基本思想是从一个或多个种子区域(该种子区域被认为在要分割的对象内部)开始,评估与该区域相邻的像素,以确定它们是否也应被视为对象的一部分。如果邻域像素满足要求,则它们被添加到该区域,并且只要有新像素被添加到该区域,区域生长过程就继续。区域增长算法根据用于决定像素是否应包含在区域中的标准、用于确定邻居的连通性类型以及用于访问相邻像素的策略而变化。
开发环境
windows10、VS2017 、VTK8.2、ITK5.0.1
运行结果
使用方法
按住ctrl键,用鼠标左键拾取种子点。区域生长默认的范围是[226,3071],若鼠标点选的像素值在该范围之外,则不做任何处理;若像素值在该范围内,则进行区域生长,并将分割后的图像进行彩色映射和原始图像叠加。
代码
//有些头文件用不到
#pragma once
#include "pch.h"
#include <iostream>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include <vtkImageData.h>
#include <vtkProperty.h>
#include <vtkDataSetMapper.h>
#include <vtkRendererCollection.h>
#include <itkImageToVTKImageFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkDICOMImageReader.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkAxesActor.h>
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkMarchingCubes.h"
#include "vtkStripper.h"
#include "vtkActor.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkPolyDataNormals.h"
#include "vtkImageShrink3D.h"
#include "vtkDecimatePro.h"
#include "vtkProperty.h"
#include <vtkInteractorStyleImage.h>
#include <vector>
#include <string>
#include <vtkSmartPointer.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageViewer2.h>
#include <vtkImageSliceMapper.h>
#include <vtkPNGReader.h>
#include <vtkSTLReader.h>
#include <vtkTexture.h>
#include <vtkTextureMapToCylinder.h>
#include <vtkImageFlip.h>
#include <vtkImageGradient.h>
#include <vtkImageGradient.h>
#include <vtkImageMagnitude.h>
#include <vtkImageShiftScale.h>
#include <vtkImageHybridMedian2D.h>
#include <vtkSphereSource.h>
#include <vtkTextProperty.h>
#include <vtkProperty2D.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkSliderWidget.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkCommand.h>
#include <vtkWidgetEvent.h>
#include <vtkCallbackCommand.h>
#include <vtkWidgetEventTranslator.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkSliderWidget.h>
#include <vtkSliderRepresentation2D.h>
#include <vtkProperty.h>
#include "itkImageToVTKImageFilter.h"
#include "itkJPEGImageIOFactory.h"
#include "itkRGBPixel.h"
#include "itkImage.h"
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkVTKImageToImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkImageSeriesReader.h"
#include "itkImageSeriesWriter.h"
#include "itkCurvatureFlowImageFilter.h"
#include "itkConnectedThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkCastImageFilter.h"
#include "itkPNGImageIOFactory.h"
#include "itksys/SystemTools.hxx"
#include "itkImageRegionIterator.h"
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkPNGImageIOFactory.h>
#include <itkConnectedThresholdImageFilter.h>
#include <itkImageSeriesReader.h>
#include <itkGDCMImageIO.h>
#include <itkImageToVTKImageFilter.h>
#include <vtkLookupTable.h>
#include <vtkImageProperty.h>
#include <vtkImageMapToColors.h>
#include "vtkImageViewer2.h"
using namespace std;
typedef short PixelType;
const unsigned int Dimension = 2;
typedef itk::Image< PixelType, Dimension > Input2dImageType;
typedef itk::GDCMImageIO ImageIOType;//GDCMImageIO读DICOM
ImageIOType::Pointer gdcmImageIO = ImageIOType::New();
typedef itk::ImageFileReader< Input2dImageType > ReaderType2d;
ReaderType2d::Pointer reader2d = ReaderType2d::New();
vtkSmartPointer<vtkImageViewer2> viewer = vtkSmartPointer<vtkImageViewer2>::New();
vtkSmartPointer<vtkImageData> itkToVtk(Input2dImageType::Pointer image)
{
typedef itk::ImageToVTKImageFilter< Input2dImageType> itkTovtkFilterType;
itkTovtkFilterType::Pointer itkTovtkImageFilter = itkTovtkFilterType::New();
itkTovtkImageFilter->SetInput(image);//设置图像数据从ITK转向VTK
itkTovtkImageFilter->Update();
return itkTovtkImageFilter->GetOutput();
}
Input2dImageType::Pointer connectedThreshold(int range[2], Input2dImageType::Pointer itkImage, Input2dImageType::IndexType seed)
{
typedef itk::ConnectedThresholdImageFilter< Input2dImageType, Input2dImageType > ConnectedFilterType;
ConnectedFilterType::Pointer connectedThres = ConnectedFilterType::New();
connectedThres->SetInput(itkImage);
connectedThres->SetLower(range[0]);
connectedThres->SetUpper(range[1]);
connectedThres->SetReplaceValue(3071);
connectedThres->AddSeed(seed);
connectedThres->Update();
return connectedThres->GetOutput();
}
class LineInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static LineInteractorStyle* New();
vtkTypeMacro(LineInteractorStyle, vtkInteractorStyleTrackballCamera);
~LineInteractorStyle();
virtual void OnLeftButtonDown();
virtual void OnRightButtonDown();
Input2dImageType::Pointer itkImage = nullptr;
private:
};
vtkStandardNewMacro(LineInteractorStyle);
LineInteractorStyle::~LineInteractorStyle()
{
}
void LineInteractorStyle::OnLeftButtonDown()
{
if (this->Interactor->GetControlKey()) {
//视口坐标
int *clickPos;
clickPos = this->GetInteractor()->GetEventPosition();
double point1[3]{ 0 };
point1[0] = clickPos[0];
point1[1] = clickPos[1];
//世界坐标
double worldPoint[3]{ 0 };
this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->SetDisplayPoint(point1[0], point1[1], 0);
this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->DisplayToWorld();
worldPoint[0] = (this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetWorldPoint())[0];
worldPoint[1] = (this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetWorldPoint())[1];
worldPoint[2] = (this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetWorldPoint())[2];
typedef itk::Point< double, 2 > PointType;
PointType point;
point[0] = worldPoint[0];
point[1] = worldPoint[1];
Input2dImageType::IndexType pixelIndex;
bool isInside = this->itkImage->TransformPhysicalPointToIndex(point, pixelIndex);
if (!isInside)
return;
int range[2] = { 226,3071 };
Input2dImageType::PixelType value = this->itkImage->GetPixel(pixelIndex);
if (value<range[0] || value>range[1])
return;
Input2dImageType::Pointer image1 = connectedThreshold(range, this->itkImage, pixelIndex);
vtkSmartPointer<vtkImageData> image2 = itkToVtk(image1);
vtkSmartPointer<vtkLookupTable> pColorTable = vtkSmartPointer<vtkLookupTable>::New();
pColorTable->SetNumberOfColors(2);
pColorTable->SetTableRange(0, 3071);
pColorTable->SetTableValue(0, 0.0, 0.0, 0.0, 0.0);
static bool flag = true;
if (flag)
pColorTable->SetTableValue(1, 0, 1, 0, 1.0);
else
pColorTable->SetTableValue(1, 0, 0, 1, 1.0);
flag = !flag;
pColorTable->Build();
vtkSmartPointer<vtkImageMapToColors> colorMap =
vtkSmartPointer<vtkImageMapToColors>::New();
colorMap->SetInputData(image2);
colorMap->SetLookupTable(pColorTable);
colorMap->Update();
vtkSmartPointer<vtkImageActor> colorActor =
vtkSmartPointer<vtkImageActor>::New();
colorActor->SetInputData(colorMap->GetOutput());
colorActor->SetInterpolate(false);
viewer->GetRenderer()->AddActor(colorActor);
viewer->Render();
}
else {
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}
}
void LineInteractorStyle::OnRightButtonDown()
{
vtkInteractorStyleTrackballCamera::OnRightButtonDown();
}
Input2dImageType::Pointer read2dImage(const char * path)
{
reader2d->SetFileName(path);
reader2d->SetImageIO(gdcmImageIO);
reader2d->Update();
return reader2d->GetOutput();
}
void showImage(Input2dImageType::Pointer itkImage)
{
viewer->SetInputData(itkToVtk(itkImage));
viewer->SetSliceOrientationToXY();
viewer->Render();
viewer->GetRenderer()->SetBackground(0.5, 0.5, 0.5);
vtkSmartPointer<LineInteractorStyle> style = vtkSmartPointer<LineInteractorStyle>::New();
style->itkImage = itkImage;
vtkSmartPointer<vtkRenderWindowInteractor> rwi =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
//设置交互属性
viewer->SetupInteractor(rwi);
viewer->GetRenderer()->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style);
rwi->Start();
viewer->Render();
}
int main()
{
Input2dImageType::Pointer itkImage = read2dImage("C:\\Users\\Desktop\\segment\\IM12");
showImage(itkImage);
return 0;
}