ITK学习笔记(二)最大圆度连通域提取

ITK学习笔记(二)最大连通域提取

  • 1、代码
    • 1.1 code
    • 1.2、生成的mask图片
    • 1.3、打印信息

关于编译部分可以参考我的:VTK学习笔记(十)基于VTK和ITK程序
最大圆度概念:
圆度计算(Circularity,Roundness)

Roundness = (4 * CV_PI * Area) / (Perimeter * Perimeter )
double getRoundness(std::vector<cv::Point> contour)
{
    double factor = (cv::contourArea(contour) * 4 * CV_PI) / (pow(cv::arcLength(contour, true), 2));
    return factor;
}

1、代码

1.1 code

#include "itkImage.h"
#include 
#include 
#include "itkScalarConnectedComponentImageFilter.h"
#include  
#include 
#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
void CreateImage(itk::Image<unsigned char, 2>* const image)
{
	// Create an image with 2 connected components
	itk::Image<unsigned char, 2>::IndexType start = { {0,0} };
	start[0] = 0;
	start[1] = 0;
 
	itk::Image<unsigned char, 2>::SizeType size;
	unsigned int NumRows = 100;
	unsigned int NumCols = 200;
	size[0] = NumRows;
	size[1] = NumCols;
 
	typename itk::Image<unsigned char, 2>::RegionType region(start, size);
 
	image->SetRegions(region);
	
	image->Allocate(true);// 全0的像素(黑色)
 
	// Make a square
	for (itk::Image<unsigned char, 2>::IndexValueType r = 5; r < 40; r++)
	{
		for (itk::Image<unsigned char, 2>::IndexValueType c = 10; c < 50; c++)
		{
			itk::Image<unsigned char, 2>::IndexType pixelIndex = { {r,c} };
 
			image->SetPixel(pixelIndex, 100);//灰色
		}
	}
 
	// Make another square
	for (typename itk::Image<unsigned char, 2>::IndexValueType r = 50; r < 70; r++)
	{
		for (typename itk::Image<unsigned char, 2>::IndexValueType c = 50; c < 80; c++)
		{
			typename itk::Image<unsigned char, 2>::IndexType pixelIndex = { {r,c} };
 
			image->SetPixel(pixelIndex, 255);//白色
		}
	}
 
}
void print(const std::string& file, itk::Image<unsigned char, 2>* image)
{
	ofstream fout(file);
	auto size = image->GetBufferedRegion().GetSize();
	for (auto i = 0; i < size[0]; i++)
	{
		for (auto j = 0; j < size[1]; j++)
		{
			itk::Image<unsigned char, 2>::IndexType index{ {i,j} };
			auto c = image->GetPixel(index);
			fout << (int)c;
		}
		fout << std::endl;
	}
}

using ImageType = itk::Image<unsigned char, 2>;

ImageType::Pointer CreateMaskImage()
{
	ImageType::Pointer image = ImageType::New();
	ImageType::IndexType start;
	start.Fill(0);

	ImageType::SizeType size;
	size.Fill(128);

	ImageType::RegionType region;
	region.SetSize(size);
	region.SetIndex(start);

	image->SetRegions(region);
	image->Allocate();

	using IteratorType = itk::ImageRegionIteratorWithIndex< ImageType >;
	IteratorType it(image, image->GetRequestedRegion());

	for (it.GoToBegin(); !it.IsAtEnd(); ++it)
	{
		ImageType::IndexType idx = it.GetIndex();

		// 创建空心圆 C=(50,50),R=15,r=5
		if ((idx[0] - 50) * (idx[0] - 50) + (idx[1] - 50) * (idx[1] - 50) < 225 &&
			(idx[0] - 50) * (idx[0] - 50) + (idx[1] - 50) * (idx[1] - 50) > 25)
			it.Set(1);

		// 创建圆 C=(70,80),r=7
		else if ((idx[0] - 70) * (idx[0] - 70) + (idx[1] - 80) * (idx[1] - 80) < 49)
			it.Set(1);

		// 创建矩形 C=(100,100),W(120,110)
		else if (idx[0] >= 100 && idx[0] <= 120 &&
			idx[1] >= 100 && idx[1] <= 110)
			it.Set(1);

		else
			it.Set(0);
	}

	return image;
}

int main(int argc, char *argv[])
{
	// 1、创建二值图像
	ImageType::Pointer image = CreateMaskImage();// 

	//将itk图片转换成vtk图片
	auto imageToVtkImage = itk::ImageToVTKImageFilter<itk::Image<unsigned char, 2>>::New();
	imageToVtkImage->SetInput(image.GetPointer());
	imageToVtkImage->Update();// 只有更新之后,后续使用者才可以拿到真正的数据

	//保存vtk图片为png文件
	vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
	writer->SetFileName("D:/documents/vs2019/itk_tutorial/connectcompent/build/RelWithDebInfo/1CreateImage.png");
	writer->SetInputData(imageToVtkImage->GetOutput());
	writer->Write();
	//保存vtk图片像素值到文本文件
	print("D:/documents/vs2019/itk_tutorial/connectcompent/build/RelWithDebInfo/1CreateImage.txt", image.GetPointer());

	// 2、过滤连通区域
	typedef unsigned long LabelType;
	typedef itk::ShapeLabelObject< LabelType, 2 >	LabelObjectType;
	typedef itk::LabelMap< LabelObjectType >	LabelMapType;
	typedef itk::BinaryImageToShapeLabelMapFilter< ImageType, LabelMapType >	I2LType;
	I2LType::Pointer i2l = I2LType::New();
	i2l->SetInput(image);
	i2l->SetFullyConnected(false);
	i2l->SetInputForegroundValue(1);
	i2l->SetOutputBackgroundValue(0);
	i2l->Update();

	LabelMapType::Pointer labelMap = i2l->GetOutput();
	for (unsigned int label = 1; label <= labelMap->GetNumberOfLabelObjects(); label++)
	{
		const LabelObjectType* labelObject = labelMap->GetLabelObject(label);
		labelObject->Print(std::cout);
		std::cout << "----------------------------------------" << std::endl;
	}

	std::vector< LabelObjectType::Pointer > filtered_label_objects;
	for (LabelMapType::Iterator it(labelMap); !it.IsAtEnd(); ++it)
	{
		// 过滤条件
		if (it.GetLabelObject()->GetRoundness() < 0.95)
			filtered_label_objects.push_back(it.GetLabelObject());
	}

	for (int i = 0; i < filtered_label_objects.size(); i++)
	{
		labelMap->RemoveLabelObject(filtered_label_objects[i]);
	}

	typedef itk::LabelMapToBinaryImageFilter< LabelMapType, ImageType> L2IType;
	L2IType::Pointer l2i = L2IType::New();
	l2i->SetInput(labelMap);
	l2i->Update();

	using WriterType = itk::ImageFileWriter<ImageType>;
	WriterType::Pointer writer1 = WriterType::New();
	writer1->SetFileName("mask.mha");
	writer1->SetInput(l2i->GetOutput());
	writer1->SetImageIO(itk::MetaImageIO::New());
	writer1->Update();
 
	return EXIT_SUCCESS;
}

1.2、生成的mask图片

因为是二值图,像素值只有0和1,直接查看颜色是黑色的,导入slicer中查看。
直接查看:
ITK学习笔记(二)最大圆度连通域提取_第1张图片
slicer中查看:
ITK学习笔记(二)最大圆度连通域提取_第2张图片
最终保留的圆度最大文件mask.mha,使用slicer打开:

ITK学习笔记(二)最大圆度连通域提取_第3张图片

1.3、打印信息

ShapeLabelObject (0000022C062D43F0)
  RTTI typeinfo:   class itk::ShapeLabelObject<unsigned long,2>
  Reference Count: 1
  LineContainer: 0000022C062D4400
  Label: 1
  NumberOfPixels: 616
  PhysicalSize: 616
  Perimeter: 127.254
  NumberOfPixelsOnBorder: 0
  PerimeterOnBorder: 0
  PerimeterOnBorderRatio: 0
  Elongation: 1
  Flatness: 1
  Roundness: 0.691393
  Centroid: [50, 50]
  BoundingBox:   ImageRegion (0000022C062D4430)
    Dimension: 2
    Index: [36, 36]
    Size: [29, 29]
  EquivalentSphericalRadius: 14.0028
  EquivalentSphericalPerimeter: 87.9823
  EquivalentEllipsoidDiameter: [28.0056, 28.0056]
  PrincipalMoments: [61.9156, 61.9156]
  PrincipalAxes:
1 0
0 1
  FeretDiameter: 0
  m_OrientedBoundingBoxSize: [0, 0]
  m_OrientedBoundingBoxOrigin: [0, 0]
----------------------------------------
ShapeLabelObject (0000022C062D3630)
  RTTI typeinfo:   class itk::ShapeLabelObject<unsigned long,2>
  Reference Count: 1
  LineContainer: 0000022C062D3640
  Label: 2
  NumberOfPixels: 145
  PhysicalSize: 145
  Perimeter: 41.524
  NumberOfPixelsOnBorder: 0
  PerimeterOnBorder: 0
  PerimeterOnBorderRatio: 0
  Elongation: 1
  Flatness: 1
  Roundness: 1.02799
  Centroid: [70, 80]
  BoundingBox:   ImageRegion (0000022C062D3670)
    Dimension: 2
    Index: [64, 74]
    Size: [13, 13]
  EquivalentSphericalRadius: 6.79374
  EquivalentSphericalPerimeter: 42.6863
  EquivalentEllipsoidDiameter: [13.5875, 13.5875]
  PrincipalMoments: [11.5172, 11.5172]
  PrincipalAxes:
1 0
0 1
  FeretDiameter: 0
  m_OrientedBoundingBoxSize: [0, 0]
  m_OrientedBoundingBoxOrigin: [0, 0]
----------------------------------------
ShapeLabelObject (0000022C062D4170)
  RTTI typeinfo:   class itk::ShapeLabelObject<unsigned long,2>
  Reference Count: 1
  LineContainer: 0000022C062D4180
  Label: 3
  NumberOfPixels: 231
  PhysicalSize: 231
  Perimeter: 59.5651
  NumberOfPixelsOnBorder: 0
  PerimeterOnBorder: 0
  PerimeterOnBorderRatio: 0
  Elongation: 1.91485
  Flatness: 1.91485
  Roundness: 0.904522
  Centroid: [110, 105]
  BoundingBox:   ImageRegion (0000022C062D41B0)
    Dimension: 2
    Index: [100, 100]
    Size: [21, 11]
  EquivalentSphericalRadius: 8.57494
  EquivalentSphericalPerimeter: 53.8779
  EquivalentEllipsoidDiameter: [12.3935, 23.7317]
  PrincipalMoments: [10, 36.6667]
  PrincipalAxes:
0 1
-1 -0
  FeretDiameter: 0
  m_OrientedBoundingBoxSize: [0, 0]
  m_OrientedBoundingBoxOrigin: [0, 0]
----------------------------------------

TK还提供了itk::BinaryImageToStatisticsLabelMapFilter类,可以提供原图区域的统计信息。

itk::ShapeLabelObject提供的形状信息包括:


NumberOfPixels 像素数
PhysicalSize 物理尺寸
Perimeter 周长
NumberOfPixelsOnBorder 边界像素数
PerimeterOnBorder 边界周长
PerimeterOnBorderRatio 边界周长比
Elongation 伸长率
Flatness 平整度
Roundness 圆度
Centroid 质心
BoundingBox 包围盒
EquivalentSphericalRadius 等效球面半径
EquivalentSphericalPerimeter 等效球面周长
EquivalentEllipsoidDiameter 等效椭球直径
PrincipalMoments 主力矩
PrincipalAxes 主轴
FeretDiameter

itk::StatisticsLabelObject提供的统计信息包括:

Minimum
Maximum
Mean
Sum
StandardDeviation 标准差
Variance 方差
Median
Skewness 偏态
Kurtosis 峰度
WeightedElongation 加权伸长率
WeightedFlatness 加权平面度
MaximumIndex
MinimumIndex
CenterOfGravity 重心
WeightedPrincipalMoments 加权主力矩
WeightedPrincipalAxes 加权主轴

参考:ITK连通域分析

参考:

你可能感兴趣的:(ITK,ITK)