操作系統(tǒng):Centos7.4
1. 準(zhǔn)備工作
1.1 install protobuf
- cd protobuf-2.6.1/
- ./autogen.sh (需要下載gtest-1.6.0放到當(dāng)前目錄,重命名為gtest,下載地址:https://pan.baidu.com/s/1kU7ac4J)
- ./configure
- make
- make install
- protoc --version
1.2. install tensorflow
For CPU
pip install tensorflow
For GPU
pip install tensorflow-gpu
1.3. 配置tensorflow/models
參考:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md
Tensorflow Object Detection API 依賴以下庫:
- Protobuf 2.6
- Pillow 1.0
- lxml
- tf Slim (which is included in the "tensorflow/models/research/" checkout)
- Jupyter notebook
- Matplotlib
- Tensorflow
具體步驟如下:
- 下載TensorFlow Models
git clone https://github.com/tensorflow/models.git
- 編譯protobuf(在object_detection/protos/下生成若干py文件)
#From tensorflow/models/research
cd models/research
protoc object_detection/protos/*.proto --python_out=.
- 添加PYTHONPATH
From tensorflow/models/research
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
或者在/root/.bashrc中加入:export PYTHONPATH=$PYTHONPATH:/home/tensorflow_install/models/research:/home/tensorflow_install/models/research/slim
- 驗證
#From tensorflow/models/research
python object_detection/builders/model_builder_test.py
驗證前先確保setup.py編譯安裝,一些依賴庫是否安裝,我在驗證中遇到很多錯誤,安裝以下依賴庫解決:
- python setup.py build
- python setup.py install
- pip install matplotlib
- yum install -y tkinter
- pip install image
- pip install pillow
1.4. 準(zhǔn)備數(shù)據(jù)
參考:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/preparing_inputs.md
以PASCAL VOC 2012為例:
- 下載并解壓
#From tensorflow/models/research/object_detection
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar
tar -xvf VOCtrainval_11-May-2012.tar
- 生成TFRecord(得到pascal_train.record和pascal_val.record)
#From tensorflow/models/research
mkdir object_detection/VOC2012
python object_detection/dataset_tools/create_pascal_tf_record.py
--label_map_path=object_detection/data/pascal_label_map.pbtxt
--data_dir=VOCdevkit --year=VOC2012 --set=train
--output_path=object_detection/VOC2012/pascal_train.record
python object_detection/dataset_tools/create_pascal_tf_record.py
--label_map_path=object_detection/data/pascal_label_map.pbtxt
--data_dir=VOCdevkit --year=VOC2012 --set=val
--output_path=object_detection/VOC2012/pascal_val.record
如果需要用自己的數(shù)據(jù),則參考create_pascal_tf_record.py編寫處理數(shù)據(jù)生成TFRecord的腳本。(參考:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/using_your_own_dataset.md)在下一篇文章介紹。
1.5. (可選)下載模型
官方提供了不少與訓(xùn)練模型(https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md),這里以ssd_mobilenet_v1_coco以例:
#From tensorflow/models/research/object_detection
wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_2017_11_17.tar.gz
tar -xzvf ssd_mobilenet_v1_coco_2017_11_17.tar.gz
2. 訓(xùn)練
如果使用現(xiàn)有模型進(jìn)行預(yù)測則不需要訓(xùn)練。
文件結(jié)構(gòu):
models
├── research
│ ├── object_detection
│ │ ├── VOC2012
│ │ │ ├── ssd_mobilenet_train_logs
│ │ │ ├── ssd_mobilenet_val_logs
│ │ │ ├── ssd_mobilenet_v1_voc2012.config
│ │ │ ├── pascal_label_map.pbtxt
│ │ │ ├── pascal_train.record
│ │ │ └── pascal_val.record
│ │ ├── infer.py
│ │ └── create_pascal_tf_record.py
│ ├── eval_voc2012.sh
│ └── train_voc2012.sh
2.1. 配置
參考:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/configuring_jobs.md
配置分為5個部分:
- model config:定義了什么類型的模型將被訓(xùn)練(如元架構(gòu),特征提取器)
- train_config:決定應(yīng)該使用哪些參數(shù)來訓(xùn)練模型參數(shù)(如SGD參數(shù),輸入預(yù)處理和特征提取器初始化值)
- eval_config
- train_input_config:定義了模型應(yīng)該訓(xùn)練的數(shù)據(jù)集
- eval_input_config:定義了模型將被評估的數(shù)據(jù)集
在object_detection/samples/model_configs文件夾中提供了示例模型配置。這些配置文件的內(nèi)容可以粘貼到框架配置的模型區(qū)域。應(yīng)該注意的是,num_classes字段應(yīng)該改為適合正在訓(xùn)練的數(shù)據(jù)集的值。
這里使用ssd_mobilenet:
#From tensorflow/models/research
- cp object_detection/samples/configs/ssd_mobilenet_v1_pets.config object_detection/VOC2012/ssd_mobilenet_v1_voc2012.config
- 修改9行為
num_classes:20- 修改158行為
fine_tune_checkpoint: "object_detection/ssd_mobilenet_v1_coco_2017_11_17/model.ckpt"- 修改177行為
input_path: "object_detection/VOC2012/pascal_train.record"- 修改179行和193行為:
label_map_path: "object_detection/data/pascal_label_map.pbtxt"- 修改191行為:input_path: "object_detection/VOC2012/pascal_val.record"
2.2. 訓(xùn)練
新建research/train_voc2012.sh,添加以下內(nèi)容:
python object_detection/train.py \
--logtostderr \
--pipeline_config_path=object_detection/VOC2012/ssd_mobilenet_v1_voc2012.config \
--train_dir=object_detection/VOC2012/ssd_mobilenet_train_logs \
2>&1 | tee object_detection/VOC2012/ssd_mobilenet_train_logs.txt &
執(zhí)行以下命令即可訓(xùn)練:
./train_voc2012.sh
2.3. 驗證
可一邊訓(xùn)練一邊驗證,注意使用其它的GPU或合理分配顯存。
新建tensorflow/models/eval_voc2012.sh,內(nèi)容以下:
--logtostderr \
--pipeline_config_path=object_detection/VOC2012/ssd_mobilenet_v1_voc2012.config \
--checkpoint_dir=object_detection/VOC2012/ssd_mobilenet_train_logs \
--eval_dir=object_detection/VOC2012/ssd_mobilenet_val_logs &
進(jìn)入tensorflow/models/research,運行CUDA_VISIBLE_DEVICES="1" (這里就不需要設(shè)置了,我們使用CPU,不用GPU)./train_voc2012.sh即可驗證。
3. 測試
3.1. 導(dǎo)出模型
訓(xùn)練完成后得到一些checkpoint文件在ssd_mobilenet_train_logs中,如:
- graph.pbtxt
- model.ckpt-200000.data-00000-of-00001
- model.ckpt-200000.info
- model.ckpt-200000.meta
其中meta保存了graph和metadata,ckpt保存了網(wǎng)絡(luò)的weights。
而進(jìn)行預(yù)測時只需模型和權(quán)重,不需要metadata,故可使用官方提供的腳本生成推導(dǎo)圖:
python object_detection/export_inference_graph.py \
--input_type image_tensor \
--pipeline_config_path object_detection/VOC2012/ssd_mobilenet_v1_voc2012.config \
--trained_checkpoint_prefix object_detection/VOC2012/ssd_mobilenet_train_logs/model.ckpt-200000 \
--output_directory object_detection/VOC2012
3.2. 測試圖片
- 運行object_detection_tutorial.ipynb并修改其中的各種路徑即可。
- 或自寫編譯inference腳本,如tensorflow/models/research/object_detection/infer.py
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
## This is needed to display the images.
#%matplotlib inline
# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
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_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
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())
#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_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)
#Helper code
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) ]
TEST_IMAGE = sys.argv[1]
print 'the test image is:', TEST_IMAGE
# Size, in inches, of the output images.
IMAGE_SIZE = (12, 8)
with detection_graph.as_default():
with tf.Session(graph=detection_graph) as sess:
# Definite input and output Tensors for detection_graph
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')
#for image_path in TEST_IMAGE_PATHS:
image = Image.open(TEST_IMAGE)
# 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)
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')
# 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(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8)
print(scores)
print(classes)
print(category_index)
count = 0
for i in range(100):
if scores is None or final_score[i] > 0.5:
count = count + 1
print 'the count of objects is: ', count
plt.figure(figsize=IMAGE_SIZE)
plt.imshow(image_np)
plt.show()
其中,這段代碼是統(tǒng)計識別的物體個數(shù):
count = 0
for i in range(100):
if scores is None or final_score[i] > 0.5:
count = count + 1
print 'the count of objects is: ', count
運行 infer.py test_images/image2.jpg,效果如圖:
源碼安裝tensorflow
git clone --recurse-submodules https://github.com/tensorflow/tensorflow
wget https://copr.fedorainfracloud.org/coprs/vbatts/bazel/repo/epel-7/vbatts-bazel-epel-7.repo
cp vbatts-bazel-epel-7.repo /etc/yum.repos.d/
yum install -y bazel
yum install -y python-numpy swig python-dev python-wheel
cd tensorflow
./configure
bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package

