n维数字图像欧氏距离变换算法

算法简介

该算法主要用于在三维图像中计算有效体素之间的最短欧几里得距离。

算法出处:NEW ALGORITHMS FOR EUCLIDEAN DISTANCE TRANSFORMATION OF AN n-DIMENSIONAL DIGITIZED PICTURE WITH APPLICATIONS
算法在体渲染加速中的应用:Accelerated Volume Rendering with Chebyshev Distance Maps

算法过程

公式表示

符号说明
图像维度: L × M × N L \times M \times N L×M×N,其中 1 ≤ i ≤ L , 1 ≤ j ≤ M , 1 ≤ k ≤ N 1\leq i \leq L,1\leq j \leq M, 1\leq k \leq N 1iL,1jM,1kN
输入图像: F = { f i j k } F=\{f_{ijk}\} F={fijk}
中间图像: G = { g i j k } G=\{g_{ijk}\} G={gijk} H = { h i j k } H=\{h_{ijk}\} H={hijk}
输出图像: S = { s i j k } S=\{s_{ijk}\} S={sijk}

步骤1

输入:F
输出:G
公式:当 f x j k = 0 , 1 ≤ x ≤ L f_{xjk}=0, 1 \leq x \leq L fxjk=0,1xL,求 g i j k = m i n { ( i − x ) 2 } g_{ijk}=min \{ (i-x)^2 \} gijk=min{(ix)2}

f x j k = 0 f_{xjk}=0 fxjk=0 表示在图像中体素值为0是有效体素

计算示例图:
在这里插入图片描述

步骤2

输入:G
输出:H
公式:当 1 ≤ y ≤ M 1 \leq y \leq M 1yM,求 h i j k = m i n { g i j k + ( j − y ) 2 } h_{ijk}=min\{ g_{ijk} + (j-y)^2 \} hijk=min{gijk+(jy)2}

计算示例图:
在这里插入图片描述

步骤3

输入:H
输出:S
公式:当 1 ≤ z ≤ N 1 \leq z \leq N 1zN,求 s i j k = m i n { h i j k + ( k − z ) 2 } s_{ijk}=min\{ h_{ijk} + (k-z)^2 \} sijk=min{hijk+(kz)2}

计算过程和步骤2类似,只是换了维度,因此不再赘述

算法示例

为了描述方便,这里使用二维图像作为操作目标,且每个像素是二值的。由于是二维的,所以步骤会少一步,即无步骤3,最终的输出结果是H

原始图像F,值为0表示有效像素
在这里插入图片描述

中间图像G,因为最后一行无有效像素,所以保持默认值
在这里插入图片描述

最终图像H,像素内存储最近有效像素的距离的平方
在这里插入图片描述


我们将图像H中的值开方,即可得到每个像素的最近有效像素的欧式距离
在这里插入图片描述

代码实现

在计算机上实现

步骤1

前向扫描
输入:F
输出:G’
g 0 j k ′ = L 2 g'_{0jk}=L^2 g0jk=L2
要求 i i i 1 1 1 L L L,如果 f i j k ≠ 0 f_{ijk} \neq 0 fijk=0,则 g i j k ′ = ( g ( i − 1 ) j k ′ + 1 ) 2 g'_{ijk} = ( \sqrt {g'_{(i-1)jk}} + 1)^2 gijk=(g(i1)jk +1)2;否则 g i j k ′ = 0 g'_{ijk}=0 gijk=0

反向扫描
输入:G’
输出:G
g ( L + 1 ) j k = L 2 g_{(L+1)jk}=L^2 g(L+1)jk=L2
要求 i i i L L L 1 1 1,如果 g i j k ′ ≠ 0 g'_{ijk} \neq 0 gijk=0,则 g i j k = m i n { ( g ( i + 1 ) j k + 1 ) 2 , g i j k ′ } g_{ijk} = min \{ ( \sqrt { g_{(i+1)jk} } + 1)^2 , g'_{ijk}\} gijk=min{(g(i+1)jk +1)2,gijk};否则 g i j k = 0 g_{ijk}=0 gijk=0

步骤2

输入:G
输出:H

要求 n n n − r 1 -r_1 r1 r 2 r_2 r2,其中 r 1 ≤ r , r 2 ≤ r , r = g i j k r_1 \leq r, r_2 \leq r, r=\sqrt {g_{ijk}} r1r,r2r,r=gijk ,求 h i j k = m i n { g i ( j + n ) k + n 2 } h_{ijk}=min\{ g_{i(j+n)k} + n^2 \} hijk=min{gi(j+n)k+n2}
注意 1 ≤ j + n ≤ M 1 \leq j+n \leq M 1j+nM,所以要保证 j − r 1 ≥ 1 , j + r 2 ≤ M j-r_1 \geq 1,j+r_2 \leq M jr11,j+r2M,从而 r 1 ≤ j − 1 , r 2 ≤ M − j r_1 \leq j-1, r_2 \leq M-j r1j1,r2Mj
所以 r 1 = m i n { r , j − 1 } , r 2 = m i n { r , M − j } r_1 = min \{ r, j-1 \},r_2 = min\{ r,M-j \} r1=min{r,j1},r2=min{r,Mj}

步骤3

输入:H
输出:S

要求 n n n − r -r r r r r,其中 r = h i j k r=\sqrt {h_{ijk}} r=hijk ,求 s i j k = m i n { h i j ( k + n ) + n 2 } s_{ijk}=min\{ h_{ij(k+n)}+ n^2 \} sijk=min{hij(k+n)+n2}
注意 1 ≤ k + n ≤ N 1 \leq k+n \leq N 1k+nN,所以要保证 k − r 1 ≥ 1 , k + r 2 ≤ N k-r_1 \geq 1,k+r_2 \leq N kr11,k+r2N,从而 r 1 ≤ k − 1 , r 2 ≤ M − k r_1 \leq k-1, r_2 \leq M-k r1k1,r2Mk
所以 r 1 = m i n { r , k − 1 } , r 2 = m i n { r , M − k } r_1 = min \{ r, k-1 \},r_2 = min\{ r,M-k \} r1=min{r,k1},r2=min{r,Mk}

编写C++代码

输入数据是三维向量

void edt(vector<vector<vector<float>>>& f)
{
	int N = f.size();
	int M = f[0].size();
	int L = f[0][0].size();

	///步骤1
	///前向扫描
	for (int k = 0; k < N; k++)
	{
		for (int j = 0; j < M; j++)
		{
			float df = L;
			for (int i = 0; i < L; i++)
			{
				if (f[k][j][i] != 0)
				{
					df = df + 1;
				}
				else
				{
					df = 0;
				}
				f[k][j][i] = df * df;
			}
		}
		///反向扫描
		for (int j = 0; j < M; j++)
		{
			float db = L;
			for (int i = L - 1; i >= 0; i--)
			{
				if (f[k][j][i] != 0)
				{
					db = db + 1;
				}
				else
				{
					db = 0;
				}
				f[k][j][i] = std::fmin(f[k][j][i], db * db);
			}
		}
	}
	

	///步骤2
	for (int k = 0; k < N; k++)
	{		
		for (int i = 0; i < L; i++)
		{
			vector<float> buff(M);
			for (int j = 0; j < M; j++)
			{
				buff[j] = f[k][j][i];
			}

			for (int j = 0; j < M; j++)
			{
				float d = buff[j];
				if (d != 0)
				{
					float rMax = int(std::sqrt(d)) + 1;
					float rStart = std::min(rMax, float(j));
					float rEnd = std::min(rMax, float(M - 1 - j));

					for (int n = -rStart; n < rEnd; n++)
					{
						float w = buff[j + n] + n * n;
						if (w < d)
						{
							d = w;
						}
					}
				}
				f[k][j][i] = d;
			}
		}
	}
	
	///步骤3,与步骤2类似
	for (int j = 0; j < M; j++)
	{
		for (int i = 0; i < L; i++)
		{
			vector<float> buff(N);
			for (int k = 0; k < N; k++)
			{
				buff[k] = f[k][j][i];
			}

			for (int k = 0; k < N; k++)
			{
				float d = buff[k];
				if (d != 0)
				{
					float rMax = int(std::sqrt(d)) + 1;
					float rStart = std::min(rMax, float(k));
					float rEnd = std::min(rMax, float(N - 1 - k));

					for (int n = -rStart; n < rEnd; n++)
					{
						float w = buff[k + n] + n * n;
						if (w < d)
						{
							d = w;
						}
					}
				}
				f[k][j][i] = d;
			}
		}
	}
}

测试代码

#include<iostream>
#include<cmath>
#include<vector>
using namespace std;

int main(int argc, char *argv[])
{
	//图像维度4x4x1
	vector<vector<vector<float>>> F(1, vector<vector<float>>(4, vector<float>(4)));
	
	//输入图像数据
	F[0][0][0] = 1; F[0][0][1] = 1; F[0][0][2] = 1; F[0][0][3] = 0;
	F[0][1][0] = 1; F[0][1][1] = 0; F[0][1][2] = 1; F[0][1][3] = 0;
	F[0][2][0] = 0; F[0][2][1] = 1; F[0][2][2] = 1; F[0][2][3] = 1;
	F[0][3][0] = 1; F[0][3][1] = 1; F[0][3][2] = 1; F[0][3][3] = 1;

	edt(F);

	//输出计算数据
	for (int k = 0; k < F.size(); k++)
	{
		for (int j = 0; j < F[k].size(); j++)
		{
			for (int i = 0; i < F[k][j].size(); i++)
			{
				cout << F[k][j][i] << " ";
			}
			cout << endl;
		}		
	}

	return 0;
}

结果
在这里插入图片描述

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

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

相关文章

[Halcon学习笔记]在Qt上实现Halcon窗口的字体设置颜色设置等功能

1、 Halcon字体大小设置在Qt上的实现 在之前介绍过Halcon窗口显示文字字体的尺寸和样式&#xff0c;具体详细介绍可回看 &#xff08;一&#xff09;Halcon窗口界面上显示文字的字体尺寸、样式修改 当时介绍的设定方法 //Win下QString Font_win "-Arial-10-*-1-*-*-1-&q…

忘记密码找回流程请求拦截器-前端

目录 设置找回密码请求拦截器 1.相关参数 2.约定 代码实现 1. 实现思路 2. 实现代码 校园统一身份认证系统&#xff1a; 基于网络安全&#xff0c;找回密码、重新设置密码的流程和正常登录流程中密钥等请求头不一致。 设置找回密码请求拦截器 1.相关参数 clientId 应…

明日周刊-第3期

第3期&#xff0c;分享自己最近的感悟和实用工具。 文章目录 1. 一周热点2. 资源分享3. 言论4. 歌曲推荐 1. 一周热点 国内生产总值持续增长&#xff1a;统计局最新数据显示&#xff0c;2023年全年国内生产总值&#xff08;GDP&#xff09;超过126万亿元&#xff0c;比上年增长…

提升质量透明度,动力电池企业的数据驱动生产实践 | 数据要素 × 工业制造

系列导读 如《“数据要素”三年行动计划&#xff08;2024—2026年&#xff09;》指出&#xff0c;工业制造是“数据要素”的关键领域之一。如何发挥海量数据资源、丰富应用场景等多重优势&#xff0c;以数据流引领技术流、资金流、人才流、物资流&#xff0c;对于制造企业而言…

4 Spring IOC/DI配置管理第三方bean

文章目录 1&#xff0c;IOC/DI配置管理第三方bean1.1 案例:数据源对象管理1.1.1 环境准备1.1.2 思路分析1.1.3 实现Druid管理步骤1:导入druid的依赖步骤2:配置第三方bean步骤3:从IOC容器中获取对应的bean对象步骤4:运行程序 1.1.4 实现C3P0管理步骤1:导入C3P0的依赖步骤2:配置第…

DBO优化GRNN回归预测(matlab代码)

DBO-GRNN回归预测matlab代码 蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法&#xff0c;在2022年底提出&#xff0c;主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 数据为Excel股票预测数据。 数据集划分为训练集、验证集、测试集,比例…

博途建立S7-1200PLC与HMS AB7013Profinet通讯

1、新建一个博图项目1200PLC .CPU 1214C ACDC/RIY 6ES7 214-1BG31-0x80 2、安装GSD文件 Install general station description fle (GsD) GSDMLV2.3-HMS-ABC PROFINET GSD 3、连接PLC 4、在线访问 5、增加访问子网络 </

FPGA 以太网传输ov5640视频

1 实验任务 使用 DFZU4EV MPSoC 开发板及双目 OV5640 摄像头其中一个摄像头实现图像采集&#xff0c;并通过开发板上的以太网接口发送给上位机实时显示。 2 系统框架 时钟模块用于为 I2C 驱动模块、以太网顶层模块和开始传输控制模块提供驱动时钟&#xff1b;I2C 驱动模块…

用最小堆实现通用的高效定时器组件

用最小堆实现通用的高效定时器组件 文章目录 用最小堆实现通用的高效定时器组件开篇解决方案类图源码实现测试总结 开篇 在程序开发过程中&#xff0c;定时器会经常被使用到。而在Linux应用开发中&#xff0c;系统定时器资源有限&#xff0c;进程可创建的定时器数量会受到系统限…

Priority Queue实现栈和队列

在排序算法中&#xff0c;堆排序利用了完全二叉树形式的堆结构&#xff0c;结合了插入排序与合并排序的优点&#xff0c;能够以 O ( n log ⁡ n ) O(n\log{n}) O(nlogn)的时间完成排序。优先级队列是可基于堆结构进行实现的一种数据结构&#xff0c;在计算机系统中可以用来记录…

【现代C++】可变参数模板

现代C中的可变参数模板是C11引入的一个功能&#xff0c;允许模板接受可变数量的参数&#xff0c;使得模板编程更加灵活和强大。 1. 基本用法 可变参数模板允许您创建接受任意数量参数的函数或类模板。 template<typename... Args> void func(Args... args) {// 处理参…

C++ 基本运算

何谓运算符和操作数 基本运算 1、双目运算 2、单目运算 3、赋值表达式 表达形式&#xff1a; <变量><表达式>; 表达式是指各种运算符把常量、变量&#xff0c;函数等运算对象连接起来的具有实际意义并符合C语法规则的式子。赋值是指表达式的值赋给一个变量。 …

基于SSM的NEUQ宿舍管理系统的设计与实现

基于SSM的NEUQ宿舍管理系统的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全 获取源码——》公主号&#xff1a;计算机专业毕设大全

LabVIEW电动汽车直流充电桩监控系统

LabVIEW电动汽车直流充电桩监控系统 随着电动汽车的普及&#xff0c;充电桩的安全运行成为重要议题。通过集成传感器监测、单片机技术与LabVIEW开发平台&#xff0c;设计了一套电动汽车直流充电桩监控系统&#xff0c;能实时监测充电桩的温度、电压和电流&#xff0c;并进行数…

PMP适合哪些人?考试PMP有什么职业要求吗?

威班PMP 3A路过拿证学员 。PMP认证没听说过有啥职业的要求&#xff0c;也没听说过限制在哪些行业可用&#xff0c;根据我考后经验所了解&#xff0c;它并不只作用在某一个领域&#xff0c;知识点也是项目管理相关的工作都能用到&#xff0c;毕竟这些都是通用的专业实践。如果非…

linux命令学习——sort

sort可以对文本文件进行“排序”&#xff0c;比如-n可以对文本&#xff0c;按照首行字母数字顺序排序 -r参数可以对排序结果进行反转 -u参数可以对查看结果去重

3.18_C++_day6_作业

作业要求&#xff1a; 程序代码&#xff1a; #include <iostream>using namespace std;class Animal { private:string name;string color;int *age; public://无参构造函数Animal(){cout << "Animal::无参构造函数" << endl;}//有参构造函数Anim…

基于深度学习的生活垃圾智能分类系统(微信小程序+YOLOv5+训练数据集+开题报告+中期检查+论文)

摘要 本文基于Python技术&#xff0c;搭建了YOLOv5s深度学习模型&#xff0c;并基于该模型研发了微信小程序的垃圾分类应用系统。本项目的主要工作如下&#xff1a; &#xff08;1&#xff09;调研了移动端垃圾分类应用软件动态&#xff0c;并分析其优劣势&#xff1b;…

附近最小 单调队列 滑动窗口 蓝桥杯

q[t]i 的执行过程如下&#xff1a; 首先&#xff0c;t 的值会先自增 1。然后&#xff0c;新值 i 被赋给 q[t]&#xff0c;即元素 i 被插入到数组 q 的下标为 t 的位置上。 q[t]i 的执行过程如下&#xff1a; 首先&#xff0c;i 的值被赋给 q[t]&#xff0c;即元素 i 被插入到数…

深度学习pytorch——可视化visdom(持续更新)

安装可看&#xff1a;e: Error while finding module specification for ‘visdom.server‘ (ModuleNotFoundError: No module name-CSDN博客 在命令行窗口使用python -m visdom.server&#xff0c;会出现一个web地址&#xff0c;在浏览器中访问&#xff0c;即可看见在python中…