Window下在TensorFlow中安装protoc

TensorFlow Object-detection API : github地址

    这个API的目的是创建一个能够在单个图像中定位和识别多个对象的精确机器学习模型,这在仍然是计算机视觉领域仍然是一个核心挑战。该API是在tensorflow上构造的开源框架,易于构建、训练和部署目标检测模型,谷歌已经应用在公司的视觉项目中,来源是开头的那篇论文,如果有兴趣可以研究一下,主要对比了几种不同的Object Detection神经网络(FasterRCNN RFCN SSD)。

一、下载TensorFlow Model模型库

      TensorFlow 模型库包含了很多开源的模型,包括图像分类、检测、自然语言处理NLP、视频预测、图像理解等等,我们要学习的对象检测API也包括在这里面,可以用git checkout到本地,也可以直接在github下载zip包,本文直接下载的zip包(大概415M,虽然我们只会用到里面很少一部分内容)

下载后,解压到~/tensorflow目录下,为了与github目录结构一致,我们将models-master目录重命名为models

得到如下目录结构~/tensorflow/models/research/object_detection  

               Window下在TensorFlow中安装protoc

二、安装

2.1 依赖库

Tensorflow Object Detection API 依赖如下组件包:

    Tensorflow (安装过程参考《window下搭建TensorFlow运行环境(用Anaconda)》

    Protobuf 2.6
    Python-tk
    Pillow 1.0
    lxml
    tf Slim (已在 "tensorflow/models/research/" 目录下)
    Jupyter notebook
    Matplotlib
    cocoapi

    若你是通过《window下搭建TensorFlow运行环境(用Anaconda)》介绍的方式,用anaconda安装的tensorflow,那么这上面的所有依赖项(除了cocoapi)都已经自动安装好,你可以像安装tensorflow一样在anaconda-navigator的搜索框里搜索下上面的组件,检验是否均已安装。

2.2 COCO API 安装

coco api主要是用于度量模型在COCO数据集上的分值(mAP指标等),对于我们学习来说,并没有什么用,所以暂时不需要安装,以后需要的时候可以再参考下面的官方说明安装之。

Download the cocoapi and copy the pycocotools subfolder to the tensorflow/models/research directory if you are interested in using COCO evaluation metrics. The default metrics are based on those used in Pascal VOC evaluation. To use the COCO object detection metrics add metrics_set: "coco_detection_metrics" to the eval_config message in the config file. To use the COCO instance segmentation metrics add metrics_set: "coco_mask_metrics" to the eval_config message in the config file.

  • git clone https://github.com/cocodataset/cocoapi.git
  • cd cocoapi/PythonAPI
  • make
  • cp -r pycocotools <path_to_tensorflow>/models/research/

2.3 Protobuf 编译(非常重要)

    Protocol-buffer,Google开发的一套数据存储、网络通信时用于协议编码的工具库,和XML或json类似,就是把数据以某种结构保存下来,不同之处在于protobuf是二进制的,而且编码的时间和空间开销都降低很多。原理可以参考博客:majianfei1023

google protobuf原理

        使用方法:在Google的git仓库下载需要的版本:根据前文依赖需要的是Protobuf 2.6,我们只需要它的编解码功能,所以只需要下载win64版本(我电脑是64位的,这里跟据你的电脑版本下在)即可。下载解压发现是一个可执行文件,OK,把它剪切到复制到..\models\research文件夹下,然后将该路径加入环境变量:在path中添加exe文件路径,并新建一个proto_path,路径为exe文件路径。调用cmd,输入protoc发现提示missing input file或者类似不报错的提示都可以,证明已经可以使用了。

    Window下在TensorFlow中安装protoc

Window下在TensorFlow中安装protoc

 Tensorflow Object Detection API 用 Protobufs 来配置模型和训练参数. 在用这个框架之前,必须先编译Protobuf 库,切换到这个目录下: tensorflow/models/research/,另外,确保当前bash是在anaconda的Tensorflow环境(即你tensorflow所在的环境)中,具体过程如下;# 在这个目录下: tensorflow/models/research/

  • 1. 通过cmd或者Anaconda Prompt进入命令行创口(这里以cmd方式进入)
  • 2. activate TensorFlow #进入anaconda的TensorFlow环境中
  • Window下在TensorFlow中安装protoc
  • 3.cd ~/tensorflow/models/research/ #进入Tensorflow安装包所在的目录。anaconda安装在默认路径下的话用该条指令。

      ###我的安装在D盘,所以需要先进入D:,再具体指到该文件下,如下图

      Window下在TensorFlow中安装protoc

  • 4. protoc object_detection/protos/*.proto --python_out=. #*.proto表示是对research目录下的所有后缀名为proto的文件转成.py文件
  • Window下在TensorFlow中安装protoc

       ###不知道为啥我输入这条命令时会报错,没办法只能用最笨的办法——逐个文件更改,把*处用具体文件名代替,如下

  • Window下在TensorFlow中安装protoc

      或者写个指令脚本:

import os 
path_url = os.path.join(os.getcwd(),r"object_detection\protos") 
print("proto path:",path_url) 
for file in os.listdir(path_url): 
    cmd = "protoc object_detection\protos\{} --python_out=." 
    if file.endswith(".proto"): 
        command = cmd.format(file) 
        print("excuting command:",command) 
        os.popen(command)

..\research目录下新建一个文件excuter.py,把以上代码复制进去,保存运行,稍等一会儿就可以看到..\research\object_detection\protos目录下生成了许多.py文件,如下图。说明protoc配置成功。

               Window下在TensorFlow中安装protoc

2.4 添加环境变量 PYTHONPATH(非常重要)

依次打开:我的电脑—>高级系统设置—>环境变量,新建一个系统变量:

Window下在TensorFlow中安装protoc

  • 2.4.1变量名为PYTHONPATH,该变量名下只有两个值 tensorflow\models\research/ 和 ..\research\slim 的绝对路径。

    Window下在TensorFlow中安装protoc

  • 2.4.2 重启电脑让环境变量生效。
  • 2.4.3 将slim路径添加到环境变量:
  • export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim 
  • #这一步我安装失败了,提示export不是工作命令之类的,看到别的博客里有没安装这一步的,我也跳过了,做了测试能环境可以运行,就先这样,之后出问题再来填坑。

2.5 测试

python object_detection/builders/model_builder_test.py

Window下在TensorFlow中安装protoc

Window下在TensorFlow中安装protoc

2.6 利用tensorflow自带模型测试

测试的图片是在

..\models\research\object_detection\test_images

我们看到这里有现成的两张图片,当然也可以换成自己的。

测试的脚本是

...\models\research\object_detection\object_detection_tutorial.ipynb

2.6.1 python版本的测试模型:

这是一个需要用jupyter notebook打开的文件,不过好像在jupyter notebook运行会有许多毛病。我找到了一个py版本的测试模型,文件内容如下:

注意,下面这个demo里第4步是从网络中下载预训练模型文件,若执行的时候速度很慢,可以单独去下载这个模型文件,然后解压到相应目录,确保存在object_detection/ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb 文件,然后屏蔽到代码中下载指令,如图所示,把Download Model代码块设置MarkDown或直接注释掉也可以。

Window下在TensorFlow中安装protoc

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

from distutils.version import StrictVersion
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image

# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
from object_detection.utils import ops as utils_ops

if StrictVersion(tf.__version__) < StrictVersion('1.9.0'):
  raise ImportError('Please upgrade your TensorFlow installation to v1.9.* or later!')

from utils import label_map_util

from utils import visualization_utils as vis_util


# What model to download.
MODEL_NAME = 'ssd_mobilenet_v1_coco_2017_11_17'
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_FROZEN_GRAPH = 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')


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())


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


category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True)


def load_image_into_numpy_array(image):
  (im_width, im_height) = image.size
  return np.array(image.getdata()).reshape(
	  (im_height, im_width, 3)).astype(np.uint8)


# For the sake of simplicity we will use only 2 images:
# image1.jpg
# image2.jpg
# If you want to test the code with your images, just add path to the images to the TEST_IMAGE_PATHS.
PATH_TO_TEST_IMAGES_DIR = 'test_images'
TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, 'image{}.jpg'.format(i)) for i in range(1, 3) ]

# Size, in inches, of the output images.
IMAGE_SIZE = (12, 8)

output_num = 1
output_img_dic = r'\output_images'


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[0], image.shape[1])
		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: np.expand_dims(image, 0)})

	  # 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.uint8)
	  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


for image_path in TEST_IMAGE_PATHS:
  image = Image.open(image_path)
  # the array based representation of the image will be used later in order to prepare the
  # result image with boxes and labels on it.
  image_np = load_image_into_numpy_array(image)
  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
  image_np_expanded = np.expand_dims(image_np, axis=0)
  # Actual detection.
  output_dict = run_inference_for_single_image(image_np, detection_graph)
  # Visualization of the results of a detection.
  vis_util.visualize_boxes_and_labels_on_image_array(
	  image_np,
	  output_dict['detection_boxes'],
	  output_dict['detection_classes'],
	  output_dict['detection_scores'],
	  category_index,
	  instance_masks=output_dict.get('detection_masks'),
	  use_normalized_coordinates=True,
	  line_thickness=8)
  plt.figure(figsize=IMAGE_SIZE)
  print(1,image_np)
  plt.imshow(image_np)
  plt.show()
  global output_num
  global output_img_dic
  if not os.path.exists(output_img_dic):
	  os.mkdir(output_img_dic)
  output_img_path = os.path.join(output_img_dic,str(output_num)+".png")
  plt.savefig(output_img_path)

    运行上述代码需要安装matplotlib库,直接pip install matplotlib安装失败的可以去官网安装与python版本对应的whl文件。安装matplotlib.whl时需要先出pycharm。

2.6.2 jupyter版的测试模型

在你的TensorFlow环境中,将jupyter的默认工作目录修改到目标检测文件里的research文件夹下,运行jupyter notebook。若之前修改过默认工作路径,则需要恢复jupyter的默认路径后,再做上一步的修改工作路径。然后打开/object_detection/object_detection_tutorial.ipynb

            Window下在TensorFlow中安装protocWindow下在TensorFlow中安装protoc

注意,下面这个demo里第4步是从网络中下载预训练模型文件,若执行的时候速度很慢,可以单独去下载这个模型文件,然后解压到相应目录,确保存在object_detection/ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb 文件,然后屏蔽到代码中下载指令,如图所示,把Download Model代码块设置MarkDown或直接注释掉也可以。

Window下在TensorFlow中安装protoc
接下就一步步执行里面的代码,看看最后的结果是否如下图,更多的细节和功能大家自己去研究研究吧:

Window下在TensorFlow中安装protoc

 

参考资料:

TensorFlow 安装protoc:

https://blog.****.net/chenmaolin88/article/details/79371891(步骤全面详细)

https://blog.****.net/ygdxt/article/details/84779203(这个也比较好,这两个可以结合来看)

https://blog.****.net/wenyusuran/article/details/83753062

Ubuntu下安装:

https://blog.****.net/liujiayu2/article/details/77837360

Windows安装(windows cpp vs下)

https://blog.****.net/program_anywhere/article/details/77365876

linux下

https://blog.****.net/hailong0715/article/details/52057873