tf对象检测api - 为每个检测bbox提取特征向量

时间:2018-03-08 10:02:30

标签: tensorflow object-detection object-detection-api tensorflow-slim

我正在使用Tensorflow对象检测API并在预训练的ssd-mobilenet模型上工作。有没有办法将每个bbox的移动网络的最后一个全局池作为特征向量?我无法找到包含此信息的操作的名称。

我已经能够根据github上的示例提取检测标签和bbox:

 image_tensor = detection_graph.get_tensor_by_name( 'image_tensor:0' )
 # Each box represents a part of the image where a particular object was detected.
 detection_boxes = detection_graph.get_tensor_by_name( 'detection_boxes:0' )
 # Each score represent how level of confidence for each of the objects.
 # Score is shown on the result image, together with the class label.
 detection_scores = detection_graph.get_tensor_by_name( 'detection_scores:0' )
 detection_classes = detection_graph.get_tensor_by_name( 'detection_classes:0' )
 num_detections = detection_graph.get_tensor_by_name( 'num_detections:0' )
 #TODO: add also the feature vector output

 # Actual detection.
 (boxes, scores, classes, num) = sess.run(
                [detection_boxes, detection_scores, detection_classes, num_detections],
                feed_dict={image_tensor: image_np_expanded} )

3 个答案:

答案 0 :(得分:3)

正如史蒂夫所说,在SecondStageBoxPredictor之后,对象检测api中Faster RCNN中的特征向量似乎被丢弃了。我可以通过修改core / box_predictor.py和meta_architectures / faster_rcnn_meta_arch.py​​使其通过网络。

问题的关键在于非最大抑制代码实际上具有一个用于Additional_fields的参数(请参阅master上的core / post_processing.py:176)。您可以传递一个张量的字典,该张量在前两个维中具有与框和分数相同的形状,并且该函数将以与框和分数相同的方式对它们进行过滤。这与我所做的更改大师有所不同:

https://gist.github.com/donniet/c95d19e00ff9abeb786415b3a9348e62

然后,不是加载冻结的图,而是重建网络并从这样的检查点加载变量(请注意:我从此处下载了检查点以获取更快的rcnn:http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_coco_2018_01_28.tar.gz

import sys
import os
import numpy as np

from object_detection.builders import model_builder
from object_detection.protos import pipeline_pb2

from google.protobuf import text_format
import tensorflow as tf

# load the pipeline structure from the config file
with open('object_detection/samples/configs/faster_rcnn_resnet101_coco.config', 'r') as content_file:
    content = content_file.read()

# build the model with model_builder
pipeline_proto = pipeline_pb2.TrainEvalPipelineConfig()
text_format.Merge(content, pipeline_proto)
model = model_builder.build(pipeline_proto.model, is_training=False)

# construct a network using the model
image_placeholder = tf.placeholder(shape=(None,None,3), dtype=tf.uint8, name='input')
original_image = tf.expand_dims(image_placeholder, 0)
preprocessed_image, true_image_shapes = model.preprocess(tf.to_float(original_image))
prediction_dict = model.predict(preprocessed_image, true_image_shapes)
detections = model.postprocess(prediction_dict, true_image_shapes)

# create an input network to read a file
filename_placeholder = tf.placeholder(name='file_name', dtype=tf.string)
image_file = tf.read_file(filename_placeholder)
image_data = tf.image.decode_image(image_file)

# load the variables from a checkpoint
init_saver = tf.train.Saver()
sess = tf.Session()
init_saver.restore(sess, 'object_detection/faster_rcnn_resnet101_coco_11_06_2017/model.ckpt')

# get the image data
blob = sess.run(image_data, feed_dict={filename_placeholder:'image.jpeg'})
# process the inference
output = sess.run(detections, feed_dict={image_placeholder:blob})

# get the shape of the image_features
print(output['image_features'].shape)

注意:我没有针对所做的更改运行tensorflow单元测试,因此仅出于演示目的考虑它们,应进行更多测试以确保它们不会破坏对象检测api中的其他内容。

答案 1 :(得分:2)

这无疑是一个完美的答案,但我已经用TF-OD API进行了大量的Faster-RCNN挖掘,并在这个问题上取得了一些进展。我将通过深入研究Faster-RCNN版本来解释我所理解的内容,并希望您可以将其转换为SSD。你最好的选择是在TensorBoard上挖掘图形并筛选检测图中的张量名称。

首先,功能和盒子/分数之间并不总是简单的一一对应。也就是说,没有一个简单的张量可以从网络中提取,至少在默认情况下不是这样。

以下是从Faster-RCNN网络获取功能的代码:

https://gist.github.com/markdtw/02ece6b90e75832bd44787c03a664e8d

虽然这提供了看起来像特征向量的东西,但您可以看到还有一些其他人遇到了这个解决方案的问题。基本问题是在SecondStagePostprocessor之前提取特征向量,它在detection_boxes张量之前执行多个操作,并且创建类似的张量。

在SecondStagePostprocessor之前,会创建类分数和框,并且不会再次看到特征向量。在后处理器中,有一个多类NMS阶段和一个排序阶段。最终结果是MaxProposalsFromSecondStage,而为[MaxProposalsFromFirstStage,NumberOfFeatureVectors]填充特征向量。因此,存在抽取和排序操作,这使得难以将最终输出与特征向量索引配对。

我目前的解决方案是从第二阶段之前拉出特征向量和方框,然后手动完成剩下的工作。毫无疑问,这是一个比这更好的解决方案,但是很难跟踪图表并找到适合于排序操作的张量。

我希望这会帮助你!很抱歉,我无法为您提供端到端的解决方案,但我希望这能让您了解目前的路障。

答案 2 :(得分:1)

在最近的PR中添加了对特征提取的支持:(https://github.com/tensorflow/models/pull/7208)。要使用此功能,您可以使用exporter tool重新导出经过预训练的模型。

作为参考,这是我使用的脚本:

Point 1 -> Location A
Point 2 -> Location B

要使用重新导出的模型,您可以在示例笔记本中更新#!/bin/bash # NOTE: run this from tf/models/research directory # Ensure that the necessary modules are on the PYTHONPATH PYTHONPATH=".:./slim:$PYTHONPATH" # Modify this to ensure that Tensorflow is accessible to your environment conda activate tf37 # pick a model from the model zoo ORIG_MODEL="faster_rcnn_inception_resnet_v2_atrous_oid_v4_2018_12_12" # point at wherever you have downloaded the pretrained model ORIG_MODEL_DIR="object_detection/pretrained/${ORIG_MODEL}" # choose a destination where the updated model will be stored DEST_DIR="${ORIG_MODEL_DIR}_with_feats" echo "Re-exporting model from $ORIG_MODEL_DIR" python3 object_detection/export_inference_graph.py \ --input_type image_tensor \ --pipeline_config_path "${ORIG_MODEL_DIR}/pipeline.config" \ --trained_checkpoint_prefix "${ORIG_MODEL_DIR}/model.ckpt" \ --output_directory "${DEST_DIR}" ,使其包含run_inference_for_single_image作为输出:

detection_features