我如何使用 tensorflow 对象检测来仅检测人员?

Posted

技术标签:

【中文标题】我如何使用 tensorflow 对象检测来仅检测人员?【英文标题】:How can i use tensorflow object detection to only detect persons? 【发布时间】:2019-07-20 04:04:37 【问题描述】:

我一直在尝试使用 tensorflow 的对象检测来尝试设置一个体面的存在检测。我正在使用 tensorflow 的预训练模型和代码示例在网络摄像头上执行对象检测。有没有办法从模型中删除对象或从人员类中过滤掉对象? 这是我目前拥有的代码。

import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile

from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image


from utils import label_map_util

from utils import visualization_utils as vis_util


# # Model preparation 
# Any model exported using the `export_inference_graph.py` tool can be loaded here simply by changing `PATH_TO_CKPT` to point to a new .pb file.  
# By default we use an "SSD with Mobilenet" model here. See the [detection model zoo](https://github.com/tensorflow/models/blob/master/object_detection/g3doc/detection_model_zoo.md) for a list of other models that can be run out-of-the-box with varying speeds and accuracies.

# What model to download.
MODEL_NAME = 'ssd_mobilenet_v1_coco_11_06_2017'
MODEL_FILE = MODEL_NAME + '.tar.gz'
DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/'

# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_CKPT = MODEL_NAME + '/frozen_inference_graph.pb'

# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = os.path.join('data', 'mscoco_label_map.pbtxt')

NUM_CLASSES = 90


# ## Download Model

if not os.path.exists(MODEL_NAME + '/frozen_inference_graph.pb'):
    print ('Downloading the model')
    opener = urllib.request.URLopener()
    opener.retrieve(DOWNLOAD_BASE + MODEL_FILE, MODEL_FILE)
    tar_file = tarfile.open(MODEL_FILE)
    for file in tar_file.getmembers():
      file_name = os.path.basename(file.name)
      if 'frozen_inference_graph.pb' in file_name:
        tar_file.extract(file, os.getcwd())
    print ('Download complete')
else:
    print ('Model already exists')

# ## Load a (frozen) Tensorflow model into memory.

detection_graph = tf.Graph()
with detection_graph.as_default():
  od_graph_def = tf.GraphDef()
  with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
    serialized_graph = fid.read()
    od_graph_def.ParseFromString(serialized_graph)
    tf.import_graph_def(od_graph_def, name='')


# ## Loading label map
# Label maps map indices to category names, so that when our convolution network predicts `5`, we know that this corresponds to `airplane`.  Here we use internal utility functions, but anything that returns a dictionary mapping integers to appropriate string labels would be fine

label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)

#intializing the web camera device

import cv2
cap = cv2.VideoCapture(0)

# Running the tensorflow session
with detection_graph.as_default():
  with tf.Session(graph=detection_graph) as sess:
   ret = True
   while (ret):
      ret,image_np = cap.read()
      image_np = cv2.resize(image_np,(600,400))
      # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
      image_np_expanded = np.expand_dims(image_np, axis=0)
      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.
      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.
      scores = detection_graph.get_tensor_by_name('detection_scores:0')
      classes = detection_graph.get_tensor_by_name('detection_classes:0')
      num_detections = detection_graph.get_tensor_by_name('num_detections:0')

      b = [x for x in classes if x == 1]
      # Actual detection.
      (boxes, scores, classes, num_detections) = sess.run(
          [boxes, scores, classes, num_detections],
          feed_dict=image_tensor: image_np_expanded)
      # Visualization of the results of a detection.

      vis_util.visualize_boxes_and_labels_on_image_array(
          image_np,
          np.squeeze(boxes),
          np.squeeze(b).astype(np.int32),
          np.squeeze(scores),
          category_index,
          use_normalized_coordinates=True,
          line_thickness=8)

      #print (len(boxes.shape))

      #print (classes)

      final_score = np.squeeze(scores)    
      count = 0
      for i in range(100):
          if scores is None or final_score[i] > 0.5:
                  count = count + 1
                  print (count, ' object(s) detected...')

#      plt.figure(figsize=IMAGE_SIZE)
#      plt.imshow(image_np)
      cv2.imshow('image',image_np)
      if cv2.waitKey(200) & 0xFF == ord('q'):
          cv2.destroyAllWindows()
          cap.release()
          break

【问题讨论】:

【参考方案1】:

我看到您在b = [x for x in classes if x == 1] 行中使用了过滤器来获取所有人员检测。 (在标签映射中,人的 id 正好是 1)。但它不起作用,因为您需要相应地更改boxesscoresclasses。试试这个:

首先删除该行

b = [x for x in classes if x == 1]

然后在sess.run()函数后面加上以下内容

boxes = np.squeeze(boxes)
scores = np.squeeze(scores)
classes = np.squeeze(classes)

indices = np.argwhere(classes == 1)
boxes = np.squeeze(boxes[indices])
scores = np.squeeze(scores[indices])
classes = np.squeeze(classes[indices])

然后调用可视化函数

vis_util.visualize_boxes_and_labels_on_image_array(
      image_np,
      boxes,
      classes,
      scores,
      category_index,
      use_normalized_coordinates=True,
      line_thickness=8)

这个想法是模型可以产生多个类的检测,但只有类人被选择在图像上进行可视化。

【讨论】:

这很完美!谢谢你的反馈!不过,我的声誉太低了,无法给你投票:( 我遇到了这个问题中提到的同样的问题,有人可以检查这个链接并回复一个有价值的解决方案吗? 这个解决方案对我帮助很大。尽管还有其他方法可以检测图像上是否有人。 # Score is shown on the result image, together with the class label. scores = detection_graph.get_tensor_by_name('detection_scores:0') classes = detection_graph.get_tensor_by_name('detection_classes:0') 在这些代码行中,一个数组将存储在分数和类中。在类中将是该模型检测到的类。在分数中,与每个班级匹配的百分比。然后,您可以遍历这两个以找到您想要的课程和匹配的分数。 如果您需要任何帮助,请随时询问。【参考方案2】:

当检测到的类是唯一的类时, 我建议使用这种方法来防止数组丢失。

# Select specific class
boxes = np.squeeze(boxes)
scores = np.squeeze(scores)
classes = np.squeeze(classes).astype(np.int32)

indices = np.argwhere(classes == 1)
boxes = np.squeeze(boxes[indices], axis=1) # to prevent errors made by nd.array of size 1 nd.array
scores = np.squeeze(scores[indices], axis=1)
classes = np.squeeze(classes[indices], axis=1)

【讨论】:

以上是关于我如何使用 tensorflow 对象检测来仅检测人员?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

如何在 Tensorflow 对象检测 api 中评估预训练模型

如何使用 Tensorflow 2 对象检测 API 恢复微调模型以进行测试?

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