tensorflow - tensorflow 获得最大 IOU 的框对,但丢弃全为零的框
问题描述
这个问题是从这个问题构建的:(tensorflow记住计算得到最大框后的索引)。我发现丢弃全为零的盒子特别困难,所以我发布了一个新的。
完整说明:
假设我有两个盒子数组,每个盒子都有形状(?, b1, 4)
和(?, b2, 4)
分别(?
视为未知批量大小):
box1: [[[1,2,3,4], [2,3,4,5], [3,4,5,6], [0,0,0,0], [0,0,0,0]...]...]
box2: [[[4,3,2,1], [3,2,5,4], [4,3,5,6]...]...]
(以上数字任意设定)
请注意,末尾可能有box1
也可能没有假框( )。[0,0,0,0]
我想要:
在每一个batch中,对于每一个non-fake box A in
box1
(即不包含全0的boxes),在box2
box B中找到与A的IOU(intersection over union)最大的box B (当然是在同一个batch中) ),然后将元组(A, B)附加到列表list_max。附加到list_nonmax中所有
box2
没有最大 IOU 的框与任何框box1
(当然,按批次分隔)
你可以假设:
b1和b2都是 python 变量,而不是 tensorflow 张量。
计算单个盒子之间或一批盒子之间的 IOU 的方法已经存在并且可以从字面上使用:
iou_single_box(box1, box2)
: box1和box2都是有形状的(4,)
。iou_multiple_boxes(bbox1, bbox2)
:bbox1和bbox2的形状分别为(b1, 4)
和(b2, 4)
。iou_batch_boxes(bbbox1, bbbox2)
:bbbox1和bbbox2的形状(?, b1, 4)
和(?, b2, 4)
分别(?
视为未知的批量大小)。
大家可以看一下我之前发的问题(tensorflow记住计算得到最大框后的索引)。我只添加一个约束:
- 我不希望任何假盒子
box1
与任何盒子相匹配box2
。获取list_max和list_nonmax时
注意,假盒子的数量没有设置。
****:我知道这个问题很复杂。我做所有这些是因为 Tensorflow 无法处理动态长度数组(你必须在运行时有一个确定性b1
)box1
。所以我[0, 0, 0, 0]
在末尾填充box1
以使长度固定。
解决方案
我相信这很容易用tf.boolean_mask()
这样的代码(经过测试)来实现:
from __future__ import print_function
import tensorflow as tf
box1 = tf.reshape( tf.constant( range( 16 ), dtype = tf.float32 ), ( 2, 2, 4 ) )
box1 = tf.concat( [ box1, tf.zeros( ( 2, 2, 4 ) ) ], axis = 1 )
box2 = tf.reshape( tf.constant( range( 2, 26 ), dtype = tf.float32 ), ( 2, 3, 4 ) )
batch_size = box1.get_shape().as_list()[ 0 ]
def dummy_iou_batch_boxes( box1, box2 ):
b1s, b2s = box1.get_shape().as_list(), box2.get_shape().as_list()
return tf.constant( [ [ [9.0,8,7], [1,2,3], [ 0, 10, 0 ], [ 0, 0, 0 ],
[0 ,1,2], [0,5,0], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ] )
iou = dummy_iou_batch_boxes( box1, box2 )
val, idx = tf.nn.top_k( iou, k = 1 )
idx = tf.reshape( idx, ( batch_size, box1.get_shape().as_list()[ 1 ] ) )
one_hot_idx = tf.one_hot( idx, depth = box2.get_shape().as_list()[ 1 ] )
# for listmax
full_idx = tf.where( tf.equal( 1.0, one_hot_idx ) )
box1_idx = full_idx[ :, 0 : 2 ]
box2_idx = full_idx[ :, 0 : 3 : 2 ]
box12 = tf.gather_nd( box1, box1_idx )
box22 = tf.gather_nd( box2, box2_idx )
list_max_raw = tf.stack( [ box12, box22 ], axis = 1 )
# filter out for a = [ 0, 0, 0, 0 ]
nonzero_mask = tf.reduce_any( tf.not_equal( 0.0, list_max_raw ), axis = 2 )[ :, 0 ]
list_max = tf.boolean_mask( list_max_raw, nonzero_mask )
# for list nonmax
nonzero_mask = tf.cast( tf.reduce_any( tf.not_equal( 0.0, box1 ), axis = 2 ), tf.float32 )[ ..., None ]
filtered_one_hot = one_hot_idx * nonzero_mask
active_box2 = tf.sign( tf.reduce_sum( filtered_one_hot, axis = 1 ) )
nonactive_box2 = 1.0 - active_box2
nonactive_box2_idx = tf.where( tf.equal( 1.0, nonactive_box2 ) )
list_nonmax = tf.gather_nd( box2, nonactive_box2_idx )
with tf.Session() as sess:
res = sess.run( [ box1, box2, list_max ] )
print( "Input boxes: " )
for v in res[ : 2 ]:
print( v )
print( " ", "=" * 40 )
print( "List max: " )
for v in res[ 2 : ]:
print( v )
print( " ", "=" * 40 )
res = sess.run( [ list_nonmax ] )
print( "List nonmax: " )
for v in res:
print( v )
print( " ", "=" * 40 )
将输出
输入框:
[[[0.1.2.3.]
[4.5.6.7.]
[0.0.0.0 .][0.0.0.0.
]][[ 8. 9. 10. 11.]
[12. 13. 14. 15.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]]
===================== ===================
[[[ 2. 3. 4. 5.]
[ 6. 7. 8. 9.]
[10. 11. 12. 13.]][[14。15. 16. 17.]
[18. 19. 20. 21.]
[22. 23. 24. 25.]]]
========================================
列表最大值:
[[[ 0. 1. 2. 3.]
[ 2. 3. 4. 5.]][[ 4. 5. 6. 7.]
[10. 11. 12. 13.]][[ 8. 9. 10. 11.]
[22. 23. 24. 25.]][[12。13. 14. 15.]
[18. 19. 20. 21.]]]
========================================
列表非最大值:
[[ 6. 7. 8. 9.]
[14. 15. 16. 17.]]
=========================================
推荐阅读
- typo3 - 如何在 TYPO3 仪表板中注册扩展名和图标?
- flutter - Flutter setState 与快照
- android - 使用“制作模块”进行构建有什么作用?
- angular - 与 BehaviorSubject 共享数据 api - 架构 Observables Store
- android - Facebook Android SDK (v12.0.0) + Jetpack Compose + startActivityForResult(已弃用)
- email - Azure DevOps - 从工作项链接到电子邮件
- html - 防止相邻组件高度在网格内增加
- identityserver4 - ADFS + IdentityServer4 + MSIS9642 无法构造 id 令牌
- python - 如何使返回菜单选项起作用?
- jenkins - 我可以为声明性管道编写 Jenkins 自定义步骤以使我能够完成代码吗?