如何在 Tensorflow 对象检测 API 中查找边界框坐标

Posted

技术标签:

【中文标题】如何在 Tensorflow 对象检测 API 中查找边界框坐标【英文标题】:How to find bounding boxes coordinates in Tensorflow Object Detection API 【发布时间】:2019-09-30 18:42:42 【问题描述】:

我正在使用 Tensorflow 对象检测 API 代码。我训练了我的模型并获得了很好的检测百分比。我一直在尝试获取边界框坐标,但它不断打印出 100 个奇异数组的列表。

在网上广泛搜索后,我发现数组中的数字是什么意思(边界框坐标是 [0.0, 1.0] 相对于底层图像的宽度和高度的浮点数。)但是,我的数组仍然非常与在线示例中显示的不同。另一个奇怪的事情是,我用少于 100 个图像测试了我的模块,那么怎么会有 100 个边界框坐标的数据。

我得到的数组;

 [[3.13721418e-01 4.65148419e-01 7.11575747e-01 6.85783863e-01]
 [9.78936195e-01 6.50490820e-03 9.97096300e-01 1.82596639e-01]
 [9.51383412e-01 0.00000000e+00 1.00000000e+00 3.88432704e-02]
 [9.85813320e-01 8.96016136e-02 9.97273505e-01 3.15960884e-01]
 [9.88873005e-01 2.13812709e-01 1.00000000e+00 4.14675951e-01]

 ......
 [4.42647263e-02 9.90755498e-01 2.57772505e-01 1.00000000e+00]
 [2.69711018e-05 5.21758199e-02 6.37509704e-01 6.62899792e-01]
 [0.00000000e+00 3.00989419e-01 9.92376506e-02 1.00000000e+00]
 [1.87531322e-01 2.66501214e-04 4.50700432e-01 1.23927500e-02]
 [9.36755657e-01 4.61095899e-01 9.92406607e-01 7.62619019e-01]]

进行检测并获取边界框坐标的函数。 output_dict['detection_boxes'] 是保存上述数组的位置。

def run_inference_for_single_image(image, graph):
  with graph.as_default():
    with tf.Session() as sess:
      # Get handles to input and output tensors
      ops = tf.get_default_graph().get_operations()
      all_tensor_names = output.name for op in ops for output in op.outputs
      tensor_dict = 
      for key in [
          'num_detections', 'detection_boxes', 'detection_scores',
          'detection_classes', 'detection_masks'
      ]:
        tensor_name = key + ':0'
        if tensor_name in all_tensor_names:
          tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(
              tensor_name)
      if 'detection_masks' in tensor_dict:
        # The following processing is only for single image
        detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
        detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])
        # Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
        real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
        detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
        detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
        detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
            detection_masks, detection_boxes, image.shape[1], image.shape[2])
        detection_masks_reframed = tf.cast(
            tf.greater(detection_masks_reframed, 0.5), tf.uint8)
        # Follow the convention by adding back the batch dimension
        tensor_dict['detection_masks'] = tf.expand_dims(
            detection_masks_reframed, 0)
      image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')

      # Run inference
      output_dict = sess.run(tensor_dict,
                             feed_dict=image_tensor: image)

      # all outputs are float32 numpy arrays, so convert types as appropriate
      output_dict['num_detections'] = int(output_dict['num_detections'][0])
      output_dict['detection_classes'] = output_dict[
          'detection_classes'][0].astype(np.int64)
      output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
      output_dict['detection_scores'] = output_dict['detection_scores'][0]
      if 'detection_masks' in output_dict:
        output_dict['detection_masks'] = output_dict['detection_masks'][0]
  return output_dict

我希望输出是边界框的常规 x,y 坐标。

【问题讨论】:

【参考方案1】:

output_dict['detection_boxes'] 中的值确实是标准化格式。通过检查您提供的数组中的值,这些值都在 0 和 1 之间,因此它们是合理的。

有 100 个框,因为模型总是输出相同数量的边界框。 (等于配置文件中的max_total_detections)。但并不是所有的都总是有意义的,你需要根据置信度分数过滤掉一些框,它存储在output_dict['scores']中。

获取常规边界框。您可以执行以下操作:

boxes = np.squeeze(output_dict['detection_boxes'])
scores = np.squeeze(output_dict['detection_scores'])
#set a min thresh score, say 0.8
min_score_thresh = 0.8
bboxes = boxes[scores > min_score_thresh]

#get image size
im_width, im_height = image.size
final_box = []
for box in bboxes:
    ymin, xmin, ymax, xmax = box
    final_box.append([xmin * im_width, xmax * im_width, ymin * im_height, ymax * im_height])

【讨论】:

如果此解决方案不起作用,请告诉我。

以上是关于如何在 Tensorflow 对象检测 API 中查找边界框坐标的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tensorflow 对象检测 API 中使用“忽略”类?

如何在 TensorFlow 对象检测 API 中从头开始训练?

如何在 iOS 中运行 Tensorflow 对象检测 API 模型?

如何修改 ssd mobilenet 配置以使用 tensorflow 对象检测 API 检测小对象?

Tensorflow 对象检测 api:如何使用 imgaug 进行增强?

如何从代码运行 tensorflow 对象检测 api (model_main_tf2)?