二维ITK连通区域提取

  • 说明
    • 主要函数介绍
    • 细节分析
      • 检测图像
      • 背景色
      • 编号顺序
    • 完整代码

说明

本文介绍2维ITK图像连通区域的提取,对如下图所示的二维图像,进行连通区域提取,并打上不同的标签,染上不同的颜色。这里以按连通区域像素个数大小进行排序,保留前几个最大的连通区域。

提取前:

提取着色后

.
.
.

主要函数介绍

itk::ConnectedComponentImageFilter<ImageType, OutputImageType>;
该filter值检测连通区域,不编号,不排序。

itk::LabelShapeKeepNObjectsImageFilter;
该filter对连通区域进行排序,然后只保留最大的几个连通区域。

itk::LabelImageToShapeLabelMapFilter< OutputImageType, LabelMapType> ;
为保留的每个连通区域打上标签(标号),编号顺序为找到不同区域的顺序.

虽然LabelShapeKeepNObjectsImageFilter调用SetAttribute 之后,按照attribute对连通区域大小进行了排序,但该排序并不反映在label上。即大的label并不一定对应大的size。反映在 SetNumberOfObjects(n) 设定保留区域之后,只保留排序后前n个区域的label。

itk::RescaleIntensityImageFilter<OutputImageType, ImageType>;
上一步图像只有标签,图像上没有直接的区别,本步对保留下来的不同连通区域进行不同的染色,以示区分。

细节分析

检测图像

itk::ConnectedComponentImageFilter,
根据该filter的描述,只对二值图进行检测,零值为背景色,非零值为前景色,即待检测物体。

背景色

labelShapeKeepNObjectsImageFilter->SetBackgroundValue(0);
该函数设置背景色,只影响输出的图像背景色。此处黑色像素视为背景色。
使用该函数需要注意,默认值为该像素值类型的非正最小值NumericTraits::NonpositiveMin(),自定义使用其他值可能造成结果非预期(原因尙未探知,知者望告知),一般设为默认即可。

编号顺序

对上图进行检测,保留5个连通区域,从大到小排序应该是ABCDE,但是编号顺序是按照图像像素遍历顺序进行编号,此处行优先进行遍历,找到的连通区域的编号1->A, 2->B,3->D,4->C,5->E。反映在着色顺序上,按照12345的顺序由深色到白色进行着色。
注意着色时
rescaleFilter->SetOutputMinimum(0);
rescaleFilter->SetOutputMaximum(255);
设置着色的范围,范围设置太广,可能造成部分标签染色与背景色太接近而看不清。

完整代码


#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkConnectedComponentImageFilter.h"
#include "itkLabelShapeKeepNObjectsImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itksys/SystemTools.hxx"
#include <sstream>
#include "itkPNGImageIOFactory.h"
#include "itkLabelImageToShapeLabelMapFilter.h"
#include "itkSimilarity3DTransform.h"
#include "itkResampleImageFilter.h"
# define ENABLE_QUICKVIEW 1#ifdef ENABLE_QUICKVIEW
#  include "QuickView.h"
#endifint
main(int argc, char* argv[])
{itk::PNGImageIOFactory::RegisterOneFactory();constexpr unsigned int Dimension = 2;using PixelType = unsigned short;using ImageType = itk::Image<PixelType, Dimension>;using ReaderType = itk::ImageFileReader<ImageType>;ReaderType::Pointer reader = ReaderType::New();std::string fileName = R"(E:\Yinyang30rotate.png)";reader->SetFileName(fileName);try{reader->Update();}catch (const std::exception& e){std::cout << e.what() << std::endl;}using OutputImageType = itk::Image<unsigned short, Dimension>;using ConnectedComponentImageFilterType = itk::ConnectedComponentImageFilter<ImageType, OutputImageType>;ConnectedComponentImageFilterType::Pointer connected = ConnectedComponentImageFilterType::New();connected->SetInput(reader->GetOutput());connected->Update();std::cout << "Number of objects: " << connected->GetObjectCount() << std::endl;using LabelType =unsigned short;using ShapeLabelObjectType = itk::ShapeLabelObject< LabelType, Dimension >;using LabelMapType = itk::LabelMap< ShapeLabelObjectType >;//标签using LabelShapeKeepNObjectsImageFilterType = itk::LabelShapeKeepNObjectsImageFilter<OutputImageType>;LabelShapeKeepNObjectsImageFilterType::Pointer labelShapeKeepNObjectsImageFilter =LabelShapeKeepNObjectsImageFilterType::New();labelShapeKeepNObjectsImageFilter->SetInput(connected->GetOutput());labelShapeKeepNObjectsImageFilter->SetBackgroundValue(0);labelShapeKeepNObjectsImageFilter->SetNumberOfObjects(5);//labelShapeKeepNObjectsImageFilter->SetReverseOrdering(true);labelShapeKeepNObjectsImageFilter->SetAttribute(LabelShapeKeepNObjectsImageFilterType::LabelObjectType::NUMBER_OF_PIXELS);labelShapeKeepNObjectsImageFilter->Update();//转换maptypedef itk::LabelImageToShapeLabelMapFilter< OutputImageType, LabelMapType> I2LType;I2LType::Pointer i2l = I2LType::New();i2l->SetInput(labelShapeKeepNObjectsImageFilter->GetOutput());i2l->SetComputePerimeter(true);i2l->Update();LabelMapType* labelMap = i2l->GetOutput();std::cout << "File " << "\"" << fileName << "\""<< " has " << labelMap->GetNumberOfLabelObjects() << " labels." << std::endl;// Retrieve all attributesfor (unsigned int n = 0; n < labelMap->GetNumberOfLabelObjects(); ++n){ShapeLabelObjectType* labelObject = labelMap->GetNthLabelObject(n);std::cout << n<<" Label: "<< itk::NumericTraits<LabelMapType::LabelType>::PrintType(labelObject->GetLabel()) << std::endl;       std::cout << "    NumberOfPixels: "<< labelObject->GetNumberOfPixels() << std::endl;std::cout << "    BoundingBox: "<< labelObject->GetBoundingBox() << std::endl;std::cout << "    PhysicalSize: "<< labelObject->GetPhysicalSize() << std::endl;std::cout << "    Centroid: "<< labelObject->GetCentroid() << std::endl;std::cout << "    NumberOfPixelsOnBorder: "<< labelObject->GetNumberOfPixelsOnBorder() << std::endl;std::cout << "    PerimeterOnBorder: "<< labelObject->GetPerimeterOnBorder() << std::endl;std::cout << "    FeretDiameter: "<< labelObject->GetFeretDiameter() << std::endl;std::cout << "    PrincipalMoments: "<< labelObject->GetPrincipalMoments() << std::endl;std::cout << "    PrincipalAxes: "<< labelObject->GetPrincipalAxes() << std::endl;std::cout << "    Elongation: "<< labelObject->GetElongation() << std::endl;std::cout << "    Perimeter: "<< labelObject->GetPerimeter() << std::endl;std::cout << "    Roundness: "<< labelObject->GetRoundness() << std::endl;std::cout << "    EquivalentSphericalRadius: "<< labelObject->GetEquivalentSphericalRadius() << std::endl;std::cout << "    EquivalentSphericalPerimeter: "<< labelObject->GetEquivalentSphericalPerimeter() << std::endl;std::cout << "    EquivalentEllipsoidDiameter: "<< labelObject->GetEquivalentEllipsoidDiameter() << std::endl; std::cout << "    OrientedBoundingBoxOrigin: "<< labelObject->GetOrientedBoundingBoxOrigin() << std::endl;std::cout << "    Flatness: "<< labelObject->GetFlatness() << std::endl;std::cout << "    PerimeterOnBorderRatio: "<< labelObject->GetPerimeterOnBorderRatio() << std::endl<<std::endl<<std::endl;std::cout<< std::endl << std::endl << std::endl;}//查找最大sizeint maxsize = 0;for (unsigned int n = 0; n < 5; ++n)//注意越界{ShapeLabelObjectType* labelObject = labelMap->GetNthLabelObject(n);if (labelObject->GetNumberOfPixels() > maxsize){maxsize = labelObject->GetNumberOfPixels();}}std::cout << "maxsize= " << maxsize << std::endl;//小于0.1倍最大size的丢弃int countToDel = 0;for (unsigned int n = 0; n < 5; ++n)//注意越界{ShapeLabelObjectType* labelObject = labelMap->GetNthLabelObject(n);if (labelObject->GetNumberOfPixels() < 0.1* maxsize){++countToDel;std::cout << "delete..."<<labelObject->GetLabel() << std::endl;}}labelShapeKeepNObjectsImageFilter->SetNumberOfObjects(5-countToDel);//着色using RescaleFilterType = itk::RescaleIntensityImageFilter<OutputImageType, ImageType>;RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();rescaleFilter->SetOutputMinimum(0);rescaleFilter->SetOutputMaximum(255);rescaleFilter->SetInput(labelShapeKeepNObjectsImageFilter->GetOutput());#ifdef ENABLE_QUICKVIEWQuickView viewer;viewer.AddImage(reader->GetOutput(), true, itksys::SystemTools::GetFilenameName(fileName));std::stringstream desc;desc << "Largest object of " << connected->GetObjectCount() << " objects";viewer.AddImage(rescaleFilter->GetOutput(), true, desc.str());viewer.Visualize();#endifreturn EXIT_SUCCESS;
}


对左边图像提取最大的5个连通区域,并排除size小于0.1最大size的连通区域的结果,只剩下3个连通区域。

二维ITK连通区域提取相关推荐

  1. matlab连通区边界_Matlab图像处理学习笔记(一):二值化、开操作、连通区域提取、重心、ROI...

    本博客主要记录我学习运用matlab进行一些基本的图像处理的一些笔记,如果有不当的地方,欢迎批评指正,一起学习,一起进步. 本篇是第一篇,只涉及到一些基本的操作,涉及到的知识点如下: 1.二值化 2. ...

  2. 【机器视觉学习笔记】二值图像连通区域提取算法(C++)

    目录 原理 二值图像 连通区域(Connected Component) 连通区域分析(Connected Component Analysis,Connected Component Labelin ...

  3. iOS 生成带 logo 的二维码,区域截屏保存至相册(小功能二连发 (一))

    原文链接:http://www.jianshu.com/p/36e9f012ef39 生成带 logo 的二维码 区域截屏相关 -- 由3033分享 开篇 最近项目需要搞了几个相对独立的小功能,今天有 ...

  4. iOS二维码限制区域识别、扫描动画

    AVCaptureDevice //初始化捕捉设备 AVCaptureDeviceInput //创建输入流 input AVCaptureSession //创建会话 AVCaptureVideoP ...

  5. python二维元组元素的提取_如何从元组列表中提取第n个元素?

    我在寻找以最快的方式提取2元组列表的第二个元素时发现了这一点.不是我想要的,但是运行了与第3种方法所示相同的测试,并测试了zip方法 setup = 'elements = [(1,1) for _ ...

  6. matlab二维数组实例(提取数据)

    问题描述:提取 12345 和 67899 这两个五位数的每一位数字,并把他们按要求存储到一个 2*5 的矩阵里. 要求矩阵第一行是 12345 从万位到个位的所有位数字,第二行也为 67899 从万 ...

  7. 【CCL】连通区域提取

    根据朋友给的一份原理写的 感觉还挺清楚 #include "cv.h" #include "highgui.h" #include <stdio.h> ...

  8. ITK学习笔记(四)基于C++和ITK获取3D医学图像的最大连通区域

    ITK学习笔记(四)基于C++和ITK获取3D医学图像的最大连通区域 1.代码 2.效果 3.主要函数介绍 1.代码 #include "itkConnectedComponentImage ...

  9. python头像变二维码_Python 图像处理库 pillow,提取支付宝和微信支付图片二维码...

    下面就是微信支付的收款二维码: 有时候我们仅仅只想要图片中间的方形二维码部分,为了提取出中间部分,我们可以使用图片处理软件,但图片处理软件不利于批处理,且学习也需要一定成本.本文将教你使用 Pytho ...

最新文章

  1. pip更换国内镜像源
  2. IName 与 IQueryName2
  3. 武汉大学计算机学院 曹老师,关于校园网吧建设的计算机网络综合设计.doc
  4. Vector容器与Iterator迭加器
  5. Swing组件集合的事件处理(二)
  6. 如何成为一名受欢迎的程序员直播者?
  7. linux 划ext4,linux – 有没有像ext4这样的’快速’格式?
  8. 共享内存 传一个类指针_大神是如何学习 Go 语言之为什么使用通信来共享内存...
  9. 279. 完全平方数(JavaScript)
  10. 免费在线PHP加密、解密、混淆源代码工具-toolfk.com
  11. 类的自动转换和强制类型转换
  12. linux每日命令(20):find命令概览
  13. 比亚迪半导体IPO再生波折:又被中止审核 红杉小米是股东
  14. 纯css实现3D立体六面体照片墙
  15. minigui[基础篇][11]—— 图标
  16. linux 关闭防火墙
  17. 期货行业首批信创试点单位转型实践|信创专题
  18. 数极客发布第10大用户行为数据分析模型-间隔分析
  19. 前端校验还是后端校验
  20. MACE源码解析【ARM卷积篇(一) 】1*N和N*1卷积实现

热门文章

  1. 优思学院|中质协绿带考试具体是要什么流程才能拿证呢?
  2. ES6中的for...in/of的使用
  3. PHP程序员要想在北京买房你得狠
  4. 请简述静态地图与动态地图之间的区别,如何在前端页面中选择使用哪种地图?...
  5. java集合操作-----求两个集合的交集和并集
  6. 关于计算机软件的英语视频,英语配音秀电脑版
  7. Unity3D vuforia SDK 预制物体各组件功能说明
  8. CV未来,路在何方?李飞飞指路
  9. 实验室功放三极,669,649,TIP122,127,5551,5401引脚和NE5532
  10. Linux中环境变量