【问题标题】:Tensorflow dilation behave differently than morphological dilationTensorflow 膨胀的行为与形态膨胀不同
【发布时间】:2019-07-08 06:32:52
【问题描述】:

如以下代码所示,tensorflow tf.nn.dilation2D function 的行为不像conventional dilation operator

import tensorflow as tf
tf.InteractiveSession()
A = [[0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0],
     [0, 0, 0, 1, 1, 1, 0],
     [0, 0, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0]]
kernel = tf.ones((3,3,1))
input4D = tf.cast(tf.expand_dims(tf.expand_dims(A, -1), 0), tf.float32)
output4D = tf.nn.dilation2d(input4D, filter=kernel, strides=(1,1,1,1), rates=(1,1,1,1), padding="SAME")
print(tf.cast(output4D[0,:,:,0], tf.int32).eval())

返回以下张量:

array([[1, 1, 1, 2, 2, 2, 1],
       [1, 1, 2, 2, 2, 2, 2],
       [1, 1, 2, 2, 2, 2, 2],
       [1, 1, 2, 2, 2, 2, 2],
       [1, 1, 1, 2, 2, 2, 1],
       [1, 1, 1, 1, 1, 1, 1]], dtype=int32)

我不明白为什么它的行为是这样的,也不明白如何我应该使用tf.nn.dilation2d 来检索预期的输出:

array([[0, 0, 0, 1, 1, 1, 0],
       [0, 0, 1, 1, 1, 1, 1],
       [0, 0, 1, 1, 1, 1, 1],
       [0, 0, 1, 1, 1, 1, 1],
       [0, 0, 0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 0]], dtype=int32)

有人可以启发 tensorflow 的简洁文档并解释 tf.nn.dilation2D 函数的作用吗?

【问题讨论】:

  • @CrisLuengo,我尝试通过执行此帖子中的第一个代码框来重现该行为。我得到“AttributeError:模块'tensorflow'没有属性'InteractiveSession'”。当我删除“tf.InteractiveSession”时,我得到“TypeError: dilation2d_v2() got an unexpected keyword argument 'filter'”。您能否发布一个适用于 tensorflow v2.4.1 的代码版本?
  • @Mark,这不是我的代码。我从来没有使用过 tensorflow 进行图像处理。
  • 谢谢,克里斯。 @Jav,有 cmets 吗?
  • 这个问题是 2 年前提出的,因此适用于 tf1.14。如果要将 tf1 代码转换为 tf2,请阅读 tf2 文档。
  • 将问题更新为 tensorflow2 无关紧要,因为此后行为可能已发生变化。

标签: python tensorflow image-processing mathematical-morphology image-morphology


【解决方案1】:

如链接的文档页面中所述,

计算 4-D 输入和 3-D 滤波器张量的灰度膨胀。

详细来说,灰度形态二维膨胀是最大和相关 [...]

这意味着将内核的值与图像的每个位置的值相加,然后取最大值作为输出值。

将此与相关性进行比较,将乘法替换为加法,并将积分(或总和)替换为最大值:

    卷积:g(t) = ∫ f(?) h(?- t) d?

     膨胀:g(t) = max? { f(?) + h (?-t) }

或者在离散世界中:

    卷积:g[n] = ∑kf[k] h[k-n]

    膨胀:g[n] = maxk { f[ k] + h[k-n] }


二元结构元素(内核,问题称为“常规膨胀”)的膨胀使用仅包含 1 和 0 的结构元素(内核)。这些表示“包含”和“排除”。也就是说,1 决定了结构元素的域。

要使用灰度值膨胀重新创建相同的行为,请将“包含”像素设置为 0,将“排除”像素设置为负无穷大。

例如,问题中使用的 3x3 方形结构元素应该是一个 3x3 零矩阵。

【讨论】:

  • 谢谢,您可以编辑回答“它应该如何使用 [...]”这个问题吗?我认为这取决于内核,但我不想弄乱你的答案;-)
  • @Jav:我忘记了问题的那一部分。已添加。
  • @CrisLuengo,除了“要使用灰度膨胀重新创建相同的行为,请将“包含”像素设置为 0,将“排除”像素设置为负无穷大。”,不要您还必须将结果“最大化”为 0,以防止结果包含 -infinity's?
  • @MarkLavin 如果内核至少有一个值不是-infinity,那么操作将始终返回一个有限值。当然假设输入图像仅包含有限值。如果内核都是-infinity,那么这个操作就没有意义了。
  • max(res,0) 将有助于避免任何负值,而不是避免非有限值。
【解决方案2】:

可以这样:

def dilation2d(self, img4D):
    '''
    '''
    with tf.variable_scope('dilation2d'):
        kernel = tf.ones((3, 3, img4D.get_shape()[3])) 
        output4D = tf.nn.dilation2d(img4D, filter=kernel, strides=(1,1,1,1), rates=(1,1,1,1), padding="SAME")
        output4D = output4D - tf.ones_like(output4D)

        return output4D

【讨论】:

  • 很遗憾我的回答没有被理解。如果你做kernel = tf.zeros(...)(而不是ones),那么你不需要在膨胀之后减去1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2022-09-30
相关资源
最近更新 更多