【ITK库学习】使用itk库进行图像分割(四):水平集分割

目录

  • 1、水平集
  • 2、itkFastMarchingImageFilter 快速步进分割
  • 3、itkShapeDetectionLevelSetImageFilter 快速步进分割

1、水平集

水平集是跟踪轮廓和表面运动的一种数字化方法。基于图像的亮度均值、梯度、边缘特征的微分计算,进行水平集分割。在itk中,所有基于分割滤波器水平集必须用浮点精度来进行操作,输出的数字化类型默认为浮点型,也可以被转换为双精度,但是不能使用整型或者无符号数据类型。

2、itkFastMarchingImageFilter 快速步进分割

该类使用快速行进求解Eikonal方程,其中速度始终为非负且仅取决于位置。

使用熵满足方案执行更新,其中仅使用“逆风”邻域。 Fast Marching 的此实现使用 std::priority_queue 来定位下一个要更新的正确网格位置。快速行进以 (N log N) 步扫描 N 个网格点,以获得锋面传播通过网格时的到达时间值。

当图像梯度很高时前面的传播速率很慢而梯度很低的区域传播速率快。此方法可是轮廓不断传播直到图像中的解剖结构边缘在那写边缘前将速率降低下来。

此类基于水平集图像类型和速度图像类型进行模板化,初始前沿由两个容器指定:一个包含已知点,另一个包含试验点。 活动点是那些已经是对象一部分的点,并且考虑包含试验点。 为了使过滤器不断发展,至少必须指定一些试验点。 例如,可以将它们指定为活动点周围的像素层。

速度函数可以指定为速度图像或速度常数,速度图像使用 SetInput() 方法设置。 如果速度图像为nullptr,则使用恒速函数,并使用SetSpeedConstant()方法指定。

如果速度函数恒定且值为1,则快速行进会产生距初始活动点的近似距离函数。FastMarchingImageFilterReinitializeLevelSetImageFilter 对象中使用,以创建距零水平集的有符号距离函数。

通过设置适当的停止值可以提前终止算法,当处理时间大于停止值时,算法终止。

FastMarchingImageFilter输出的是一个时间交叉图,对每一个像素,表达了到达这个像素位置之前所花费的时间。有两种方法可以指定输出图像信息(LargestPossibleRegionSpacingOrigin):(a) 直接从输入速度图像复制 (b) 由用户指定,如果用户未指定所有信息,则使用默认值。

输出信息计算如下。 如果速度图像为 nullptrOverrideOutputInformation 设置为 true,则根据用户指定的参数设置输出信息。 这些参数可以使用 SetOutputRegion()SetOutputSpacing()SetOutputDirection()SetOutputOrigin() 方法指定。 否则,如果速度图像不为nullptr,则从输入速度图像复制输出信息。

可能的改进:在当前的实现中,std::priority_queue只允许从前面取出节点并从后面放入节点,要更新堆上已有的值,需要将新节点添加到堆中,失效的旧节点留在堆上,当它从顶部移除时,它将被识别为无效并且不被使用,未来的实现可以以不同的方式实现堆,从而允许更新值,这通常需要一些上移和下移函数以及从图像到堆的反向指针图像,以便找到要更新的节点。

常用的成员函数

  • Set/GetStoppingValue():设置/获取快速行进算法停止值,当最小尝试点的值大于停止值时,算法终止
  • Set/GetSpeedConstant():设置/获取速度常数,如果速度图像为nullptr,则SpeedConstant值将用于整个级别集,默认情况下,SpeedConstant`设置为 1.0
  • Set/GetTrialPoints():设置/获取代表初始前沿的试验点容器,试验点表示为 LevelSetNodesVectorContainer`
  • SetOutsidePoints():设置不打算评估的点的容器
  • Set/GetOutputRegion/Size/Spacing/Origin/Direction():设置/获取输出的最大可能值、大小、间距、原点、方向计算,如果速度图像为nullptrOverrideOutputInformationtrue,则根据用户指定的参数设置输出信息,如果速度图像不为nullptr`,则从输入速度图像复制输出信息
  • Set/GetOverrideOutputInformation():同上
  • Set/GetCollectPoints():设置/获取收集点标志,检测算法以收集其访问过的所有节点的容器,对于为支持窄带的水平集算法创建窄带很有用
  • Set/GetAlivePoints():设置/获取代表初始前沿的活动点容器,活动点表示为LevelSetNodesVectorContainer`
  • Set/GetNormalizationFactor():设置/获取速度图像的标准化因子,速度图像中的值除以该因子,这允许使用具有整数像素类型的图像来表示速度
  • GetProcessedPoints():获取已处理点的容器,如果设置了 CollectPoints 标志,算法将收集所有已处理节点的容器,这对于定义支持窄带的水平集算法创建窄带非常有用
  • GetLabelImage():获取点型标签图像
  • GetLargeValue():获得巨大价值,该值用于表示分配给尚未访问的像素的时间无穷大的概念,该值默认设置为用于表示时间交叉图的像素类型max()的一半

示例代码

#include "itkImage.h"
#include "itkFastMarchingImageFilter.h"
typedef itk::Image<float, 3> FloatImageType;

bool fastMarchingImageFilter(FloatImageType* image, FloatImageType* outImage)
{
    typedef itk::FastMarchingImageFilter<FloatImageType, FloatImageType> FastMarchingFilterType;
	typename FastMarchingFilterType::Pointer fastMarching = FastMarchingFilterType::New();
	using NodeContainer = FastMarchingFilterType::NodeContainer;
	using NodeType = FastMarchingFilterType::NodeType;

	auto seeds = NodeContainer::New();

	FloatImageType::IndexType seedPosition;
	seedPosition[0] = 256;
	seedPosition[1] = 256;
	seedPosition[2] = 100;

	constexpr double initialDistance = 1.0;

	const double seedValue = -initialDistance;

	NodeType node;                   //创建节点作为堆栈变量,并初始化
	node.SetValue(seedValue);
	node.SetIndex(seedPosition);     
	seeds->Initialize();             //初始化
	seeds->InsertElement(0, node);   //插入每个节点

    FloatImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();
    //double stopTime = 100;
	fastMarching->SetInput(image);
	fastMarching->SetTrialPoints(seeds);
	fastMarching->SetSpeedConstant(1.0);
	fastMarching->SetOutputSize(size);
	//fastMarching->SetStoppingValue(stopTime);
	try
	{
		fastMarching->Update();
	}
	catch (itk::ExceptionObject& ex)
	{
		//读取过程发生错误
		std::cerr << "Error: " << ex << std::endl;
		return false;
	}

	outImage = fastMarching->GetOutput();
	return true;
}

3、itkShapeDetectionLevelSetImageFilter 快速步进分割

该类根据用户提供的边缘电位图分割图像中的结构。

SegmentationLevelSetImageFilter 类和 ShapeDetectionLevelSetFunction 类包含充分了解如何使用此过滤器所需的附加信息。

概述
此类是水平集方法分段滤波器,初始轮廓向外(或向内)传播,直到它“粘住”形状边界,这是通过使用基于用户提供的边缘电位图的水平集速度函数来完成的,这种分割方法遵循 Malladi 等人 (1995) 的方法。

输入
该过滤器需要两个输入。
第一个输入是初始水平集,初始水平集是包含初始轮廓/表面作为零水平集的真实图像,例如,通常使用距初始轮廓/表面的带符号距离函数,请注意,对于此算法,初始轮廓必须完全位于要分割的结构内部(或完全外部)。
第二个输入是特征图像,对于该滤波器,这是边缘电位图,边缘势图的一般特征是,它在边缘附近的区域中具有接近于零的值,并且在形状本身内部具有接近于1的值。 通常,边缘势图是根据图像梯度计算的,例如:
在这里插入图片描述
其中: I 是图像强度,(∇*G) 是高斯算子的导数。

参数
PropagationScaling 参数可用于在向外传播(正缩放参数)与向内传播(负缩放参数)之间切换。
可以使用PropagationScalingCurvatureScaling参数的组合来调整生成的轮廓/表面的平滑度。CurvatureScaling参数越大,生成的轮廓越平滑,为了使该算法正确运行,CurvatureScaling 参数应为非负数。 为了遵循 Malladi 等人论文中的实现,将 PropagationScaling 设置为 ±1.0,将 CurvatureScaling设置为 ϵ。

请注意,此过滤器没有平流项,设置平流缩放不会产生任何效果。

输出
滤波器输出单个标量实值图像,输出图像中的负值表示分割区域的内部,图像中的正值表示分割区域的外部,图像的零交叉点对应于传播前沿的位置。
有关详细信息,请参阅 SparseFieldLevelSetImageFilterSegmentationLevelSetImageFilter

常用的成员函数

  • SetInput():设置初始水平集
  • SetFeatureImage():设置特征图像

示例代码

#include "itkImage.h"
#include "itkShapeDetectionLevelSetImageFilter.h"

typedef itk::Image<float, 3> FloatImageType;

bool shapeDetectionLevelSetImageFilter(FloatImageType* image, FloatImageType* featureImage, FloatImageType* outImage)
{
    typedef itk::ShapeDetectionLevelSetImageFilter<FloatImageType, FloatImageType> ShapeDetectionLevelSetFilterType;
	typename ShapeDetectionLevelSetFilterType::Pointer shapeDetection = ShapeDetectionLevelSetFilterType::New();
	shapeDetection->SetInput(image);                         //初始水平集
	shapeDetection->SetFeatureImage(featureImage);           //特征图像,一个边缘潜在图像
	try
	{
		shapeDetection->Update();
	}
	catch (itk::ExceptionObject& ex)
	{
		//读取过程发生错误
		std::cerr << "Error: " << ex << std::endl;
		return false;
	}

	outImage = shapeDetection->GetOutput();
	return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/311069.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.10 Unity中的数据存储 JSON

一、介绍 Json是最常用也是目前用的比较多的一种&#xff0c;超轻量级&#xff0c;可便捷性使用&#xff0c;平时用到比较多的都是解析Json和往Json中添加数据、修改数据等等JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式&#xff0c;它基于ECMAScr…

git 使用 submodule 如何指定分支

写在前面, 作为一个前端我是不喜欢使用 submodule的, 我更喜欢 npm 包的管理方式。 首次添加子模块 git submodule add -b <branch> <remote> <path> 不指定分支就不传 -b <branch> <branch> 分支名<remote> 仓库地址<path> 子模块…

Unity中URP下抓屏的 开启 和 使用

文章目录 前言一、抓屏开启1、Unity下开启抓屏2、Shader中开启抓屏 二、抓屏使用1、设置为半透明渲染队列&#xff0c;关闭深度写入2、申明纹理和采样器3、在片元着色器使用请添加图片描述 三、测试代码 前言 我们在这篇文章中看一下&#xff0c;URP下怎么开启抓屏。 一、抓屏…

兴业证券分布式数据库云应用实践

数据库技术作为信息技术应用创新过程中的一项重要技术&#xff0c;其面临的难题也是亟需解决的关键问题。兴业证券在《集团五年金融科技规划》中提出&#xff0c;要以信息技术应用创新架构评审为抓手&#xff0c;制定信息技术应用创新规划和建设方案&#xff0c;以高可用性、开…

LeetCode+ 56 - 60

合并区间 双指针算法、位运算、离散化、区间合并_小雪菜本菜的博客-CSDN博客 class Solution { public:vector<vector<int>> merge(vector<vector<int>>& a) {vector<vector<int>> res;if(a.empty()) return res;sort(a.begin(),a.en…

10款强大的iPhone微信恢复软件:轻松恢复丢失的微信数据

微信已成为近年来最受欢迎的消息和社交媒体平台之一。它在全球拥有数百万用户&#xff0c;让人们能够联系、分享时刻并进行各种交易。随着微信的普及&#xff0c;对全面恢复解决方案的需求从未如此之大。本文探讨了专为 iPhone 用户设计的十款顶级微信恢复软件选项。每个软件都…

别不信,搭建企业知识库后真的效率翻倍了

在当今信息时代&#xff0c;知识是最宝贵的财富。一个企业要想越办越大&#xff0c;就需要保证信息的透明度和流通率。而搭建一套企业知识库&#xff0c;就能实现这个目标。今天我们就来聊聊为什么建立企业知识库后&#xff0c;你的工作效率会大大提高。同时&#xff0c;我们会…

智慧医院之定位导航解决方案

移动端LBS应用 通过绘制院方各楼栋各层平面图,利用无线/蓝牙技术可对终端进行实时定位,方便病人、家属等就医,提高就医体验,减少工作人员工作量,减少医患冲突,打造智慧医院。 移动端的LBS位置应用,可分为医院的室内地图展现、室内地图搜索、室内导航、室内定位、室内位…

x-cmd pkg | agg - asciinema gif 生成器

目录 简介首次用户功能特点竞品和相关作品进一步阅读 简介 由 asciinema 团队开发的 asciinema gif 生成器&#xff0c;用于将 asciinema 生成的 asciicast 文件转化为 GIF 文件&#xff0c;具有精确的帧定时&#xff0c;且支持指定字体和颜色主题&#xff0c;能生成更为精美的…

JavaScript系列——闭包

文章目录 闭包定义词法作用域闭包示例使用场景创建私有变量ES5 中&#xff0c;解决循环变量的作用域问题 小结 闭包定义 闭包&#xff0c;是函数及其关联的周边环境的引用的组合&#xff0c;在闭包里面&#xff0c;内部函数可以访问外部函数的作用域&#xff0c;而外部函数不能…

江山易改本性难移之ZYNQ SDK QSPI固化bug及其解决方法

之前在Vivado2018.3通过QSPI方式固化程序时出现问题&#xff0c;显示flash擦除成功&#xff0c;但最后总是不能写入到flash中。 查资料发现从VIVADO 2017.3版本开始&#xff0c;Xilinx官方为了使Zynq-7000和Zynq UltraScale 实现流程相同&#xff0c;在QSPI FLASH使用上做了变化…

【数模百科】一篇文章讲清楚层次分析法的原理和解法步骤

本文节选自 层次分析法原理 - 数模百科&#xff0c;如果你想了解更多关于层次分析法的信息&#xff0c;请移步数模百科。 层次分析法&#xff08;Analytic Hierarchy Process&#xff0c;简称AHP&#xff09;是一种解决复杂决策问题的方法。这个方法是由美国运筹学家托马斯萨蒂…

Java 常见缓存详解以及解决方案

一. 演示Mybatis 一级缓存 首先我们准备一个接口 两个实现的方法&#xff0c; 当我们调用这个queryAll&#xff08;&#xff09;方法时我们需要调用selectAll&#xff08;&#xff09;方法来查询数据 调用此接口实现效果 这个时候我们就可以发现了问题&#xff0c;我们调用方法…

发起人自选-钉钉审批

场景描述 配置一个审批流程&#xff0c;在某些审批节点&#xff0c;不能确定谁具体来审批&#xff0c;所以需要手工选择一个人或者多个人保证流程能得以顺利通过。有些审批流程的做法是&#xff0c;上一个节点来选择指定的人&#xff0c;而钉钉的做法是发起人来指定。 钉钉设…

软件测试|探索Python中获取最高数值的几种方法

前言 在数据分析、统计和编程领域&#xff0c;经常会遇到需要从一组数值中找出最高数值的情况。Python 作为一门功能丰富的编程语言&#xff0c;提供了多种方法来实现这一目标。在本文中&#xff0c;我们将探索几种获取最高数值的方法&#xff0c;帮助大家在不同情况下选择最适…

EasyMR:为 AI 未来赋能,打造弹性大数据引擎的革命

如果要评一个2023科技圈的热搜榜&#xff0c;那么以人工智能聊天机器人 ChatGPT 为代表的 AI大模型 绝对会霸榜整个2023。 ChatGPT 于2022年11月30日发布。产品发布5日&#xff0c;注册用户数就超过100万。推出仅两个月后&#xff0c;它在2023年1月末的月活用户已经突破了1亿&…

Qt QSpinBox微调框控件

文章目录 1 属性和方法1.1 值1.2 步长1.3 循环1.4 加速1.5 前缀和后缀1.6 信号和槽 2 实例2.1 布局2.2 代码实现 微调框&#xff0c;允许用户按照一定的步长&#xff0c;来增加或减少其中显示的数值 修改微调框数值的方式包括&#xff1a; 单击右侧的向上/向下按钮按键盘的向上…

C语言 - 最简单,最易懂的指针、引用讲解

一、变量、地址、变量值 二、直接上代码&#xff0c;一边看上图&#xff0c;一边讲解 #include <stdio.h>struct Hello {int a;int b; };int main() {struct Hello h;h.a 10;h.b 20;struct Hello *hp;hp &h;printf("1: h的地址是%d&#xff0c;hp地址是%d \…

18.标题统计*

题目 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);String str sc.nextLine();int res 0;for(int i0;i<str.length();i) {char c str.charAt(i);if(c! && c!\n) {res;}}System.o…

LabVIEW在金属铜大气腐蚀预测评价系统中的应用

为了应对电子设备和仪器中金属铜因大气腐蚀带来的挑战&#xff0c;开发一种基于LabVIEW平台的先进预测评价系统。这个系统的设计宗旨是准确预测并评估在不同室内外环境中金属铜的腐蚀状况。我们团队在LabVIEW的强大数据处理和图形化编程支持下&#xff0c;结合实际的大气腐蚀数…
最新文章