Python 计算tensorflow中3D张量的像素方向距离?

Python 计算tensorflow中3D张量的像素方向距离?,python,tensorflow,heatmap,euclidean-distance,Python,Tensorflow,Heatmap,Euclidean Distance,我试图在tensorflow中创建一个3d距离图(大小:W*H*D),用于训练的损失函数。我有一个地面真值(大小为W*H*D的二进制体积),我将使用它来创建距离贴图,即距离贴图的每个像素的值将是该像素到地面真值中正值(即像素=1)形状的最小距离。 将3d形状问题作为L2.NORM,将轴减少为2D形状,并使该问题完全可微。如有任何建议或建议,将不胜感激 如果我理解正确,您需要计算从卷中的每个位置到给定类的最近位置的距离。为了简单起见,我将假设有趣的类被标记为1,但如果它不同,希望您可以根据您的情况

我试图在tensorflow中创建一个3d距离图(大小:W*H*D),用于训练的损失函数。我有一个地面真值(大小为W*H*D的二进制体积),我将使用它来创建距离贴图,即距离贴图的每个像素的值将是该像素到地面真值中正值(即像素=1)形状的最小距离。 将3d形状问题作为L2.NORM,将轴减少为2D形状,并使该问题完全可微。如有任何建议或建议,将不胜感激


如果我理解正确,您需要计算从卷中的每个位置到给定类的最近位置的距离。为了简单起见,我将假设有趣的类被标记为
1
,但如果它不同,希望您可以根据您的情况调整它。该代码适用于TensorFlow 2.0,但应适用于1.x

最简单的方法是使用
1
计算体积中所有坐标与每个坐标之间的距离,然后从中选择最小距离。您可以这样做:

将tensorflow导入为tf
#输入数据
w、 h,d=10,20,30
w、 h,d=2,3,4
t=tf.random.stateless_uniform([w,h,d],(0,0),0,2,tf.int32)
打印(t.numpy())
# [[[0 1 0 0]
#   [0 0 0 0]
#   [1 1 0 1]]
#
#  [[1 0 0 0]
#   [0 0 0 0]
#   [1 1 0 0]]]
#坐标
coords=tf.meshgrid(tf.range(w)、tf.range(h)、tf.range(d)、index='ij')
坐标=tf.stack(坐标,轴=-1)
#找到正坐标
m=t>0
coords_pos=tf.布尔掩码(coords,m)
#找到每一对距离
向量d=tf.重塑(坐标,[-1,1,3])-坐标位置
#您可以在此处选择不同的精度类型
dists=tf.linalg.norm(tf.dtypes.cast(vec_d,tf.float32),axis=-1)
#找到最小距离
最小距离=tf。减小最小距离(距离,轴=-1)
#重塑
out=tf.重塑(最小距离[w,h,d])
打印(out.numpy().round(3))
# [[[1.    0.    1.    2.   ]
#   [1.    1.    1.414 1.   ]
#   [0.    0.    1.    0.   ]]
#
#  [[0.    1.    1.414 2.236]
#   [1.    1.    1.414 1.414]
#   [0.    0.    1.    1.   ]]]
这对您来说可能已经足够好了,尽管它可能不是最有效的解决方案。最聪明的做法是在每个位置的相邻区域中搜索最近的正位置,但要有效地进行搜索是很复杂的,一般来说都是如此,在TensorFlow中更是如此。然而,我们有几种方法可以改进上面的代码。一方面,我们知道a
1
的位置总是有零距离,因此不需要计算这些位置。另一方面,如果3D体积中的
1
类表示某种密集形状,那么如果我们只计算与该形状表面的距离,我们可以节省一些时间。所有其他正位置与形状外部位置之间的距离必须更大。所以我们可以做和以前一样的事情,但是只计算从非正位置到正表面位置的距离。您可以这样做:

将tensorflow导入为tf
#输入数据
w、 h,d=10,20,30
w、 h,d=2,3,4
t=tf.dtypes.cast(tf.random.stateless_uniform([w,h,d],(0,0))>.15,tf.int32)
打印(t.numpy())
# [[[1 1 1 1]
#   [1 1 1 1]
#   [1 1 0 0]]
# 
#  [[1 1 1 1]
#   [1 1 1 1]
#   [1 1 1 1]]]
#查找曲面上的正坐标和负坐标
#(已包围,但至少有一个0)
t_pad_z=tf.pad(t,[(1,1),(1,1),(1,1)])0
m_环绕_z=tf.类零(m_位置)
#穿过周围的6个位置
对于范围(3)中的i:
对于[slice(None,-2),slice(2,None)]中的s:
切片=元组(如果i!=j,则切片(1,-1)表示范围(3)中的j)
m_环绕_z |=t_垫_z.u获取项目_uu(切片)
#曲面点是由一些零包围的正点
m_surf=m_pos&m_surround_z
coords_-surf=tf.where(m_-surf)
#找到零坐标
coords_z=tf.where(~m_pos)
#找到每一对距离
vec_d=tf.重塑(coords_z,[-1,1,3])-coords_surf
dists=tf.linalg.norm(tf.dtypes.cast(vec_d,tf.float32),axis=-1)
#找到最小距离
最小距离=tf。减小最小距离(距离,轴=-1)
#在输出数组中放置最小距离
out=tf.散射nd(坐标z,最小距离[w,h,d])
打印(out.numpy().round(3))
# [[[0. 0. 0. 0.]
#   [0. 0. 0. 0.]
#   [0. 0. 1. 1.]]
#
#  [[0. 0. 0. 0.]
#   [0. 0. 0. 0.]
#   [0. 0. 0. 0.]]]
编辑:这里有一种方法,您可以使用TensorFlow循环将距离计算分块:

#从前面开始
coords_surf=。。。
coords_z=。。。
CHUNK_SIZE=1_000#选择CHUNK SIZE
dtype=tf.32
#如果使用TF2.x,您可以提前知道张量数组的大小
#(尽管由于最后一个块的原因,元素形状不会保持不变)
num_z=tf.shape(coords_z)[0]
arr=tf.TensorArray(dtype,size=(num_z-1)//CHUNK_size+1,element_shape=[None],推断_shape=False)
_,arr=tf。while_循环(λi,arr:i
您能举一个您需要的具体例子吗?如果可能的话,你尝试过什么样的事情?我不确定我是否理解问题的输入和输出。基本真理是三维二元张量(仅由1和0组成)还是其他什么?你想计算,对于一个同样大小的体积,距离地面真相中最近的1的距离吗?@jdehesa当然,我有一个3d体积形状(112112),它是地面真相掩码结构1=