首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Tensorflow进行实时移动视频对象检测

使用Tensorflow进行实时移动视频对象检测

作者头像
代码医生工作室
发布2019-10-10 15:13:41
2K0
发布2019-10-10 15:13:41
举报
文章被收录于专栏:相约机器人相约机器人

作者 | 刘天翔

来源 | Medium

编辑 | 代码医生团队

随着对计算机视觉的用例日益增长的兴趣,例如无人驾驶汽车,面部识别,智能交通系统等,人们希望建立定制的机器学习模型以检测和识别特定对象。

但是,从头开始构建定制模型需要大量的专业知识,时间和计算资源-从数据标记到模型服务。为减少障碍,Google发布了Tensorflow对象检测API和Tensorflow Hub等开源工具,使人们能够利用那些已经广泛使用的预先训练的模型(例如Faster R-CNN,R-FCN和SSD)来快速构建自定义模型,迁移学习。

本文旨在展示如何通过以下步骤使用TensorFlow的对象检测API训练实时视频对象检测器并将其快速嵌入到自己的移动应用中:

  1. 搭建开发环境
  2. 准备图像和元数据
  3. 模型配置和训练
  4. 将训练后的模型转换为TensorFlow Lite
  5. 在移动应用中测试模型

搭建环境

本文中的所有代码均基于macOS和Linux系统。对于Windows用户,可以在docker容器中工作:

docker run -it --rm tensorflow/tensorflow:latest-devel-py3 bash

或安装适用于Linux的Windows子系统(由于主机硬件隔离,因此不支持TensorFlow GPU)。

https://docs.microsoft.com/en-us/windows/wsl/install-win10

对于VS Code用户,远程WSL和Containers的扩展还提供了更好的开发体验,并且应与本文中的脚本完全兼容。

设置项目目录

为了使项目易于阅读,将在主项目目录中创建三个子文件夹:

data — 用于存储模型数据的文件夹(例如* .record,*。csv等)

models — 一个文件夹,用于存储所有预先训练的模型及其配置文件。

tf-models — 一个文件夹,其中包含Tensorflow中克隆的模型代码,将在建模中使用。

使用下面的脚本重现上面的项目文件夹结构。

# Define your project name
export PROJECT=FashionDetector
# Under your project workspace
# Create your project root directory
mkdir $PROJECT
cd $PROJECT
# Create directory to store your model data
mkdir data
# Create directory to store your pre trained models and their related config files
mkdir models
# Clone tensorflow model scripts
git clone https://github.com/tensorflow/models tf-models

安装Tensorflow对象检测API和依赖项

一旦完成了项目设置,Tensorflow对象检测API现在应该位于中rf-models/research/object_detection,该代码库目前由社区维护,稍后将在此处调用该模块进行模型训练。

(可选)要在Tensorflow对象检测API代码基础之上进行进一步的工作,请检出model_main.py并model_lib.py作为起点。

现在,需要安装其余的依赖项。要安装所需的python库:

# Install Tensorflow (tensorflow-gpu for GPU)
pip install tensorflow --upgrade
# Install dependencies
pip install Cython --upgrade
pip install contextlib2 --upgrade
pip install pillow --upgrade
pip install lxml --upgrade
pip install jupyter --upgrade
pip install matplotlib --upgrade

安装COCO API

https://github.com/cocodataset/cocoapi

export PROJECT_DIR=<YOUR PROJECT DIRECTORY>
 
# Install COCO API
cd $PROJECT_DIR/tf-models
git clone https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI
make
# If there is error, try to specify using python3 as below
# python3 setup.py build_ext install
 
# Copy compiled modules
cp -r pycocotools $PROJECT_DIR/tf-models/research/

注意:如果在编译COCO API时遇到问题,请确保在编译前已安装Cython和Numpy。

要安装Protobuf,Tensorflow Object Detection API使用Protobufs配置模型和训练参数。

https://github.com/protocolbuffers/protobuf

# Install Protobuf (find release for your system - https://github.com/protocolbuffers/protobuf/releases)
cd $PROJECT_DIR/tf-models/research/
curl -L https://github.com/protocolbuffers/protobuf/releases/download/v3.9.2/protoc-3.9.2-osx-x86_64.zip -o protobuf.zip
unzip ./protobuf.zip
rm ./protobuf.zip
./bin/protoc object_detection/protos/*.proto --python_out=.

将Tensorflow库添加到PYTHONPATH

在本地运行时,需要将rf-models/research/和rf-models/research/slim目录附加到PYTHONPATH,以便将TensorFlow对象检测API中的python模块添加到搜索路径中,稍后将在模型脚本中调用它们。

export PROJECT_DIR=<YOUR PROJECT DIRECTORY>
export TF_API_DIR=$PROJECT_DIR/tf-models/research
export PYTHONPATH=$PYTHONPATH:$TF_API_DIR:$TF_API_DIR/slim

注意:以上脚本需要在每个新的终端环境中运行。另外,可以在〜/ .bashrc文件中添加绝对路径作为永久解决方案。

测试安装

要测试一切是否按预期工作:

python $TF_API_DIR/object_detection/builders/model_builder_test.py

并且应该看到如下测试结果:

准备图像和元数据

下载图像数据

使用的图像数据来自DeepFashion数据库,该数据库由中国香港中文大学多媒体实验室创建。这是一个大型服装数据库,包含超过800,000种多样的时尚图片,从摆放得体的商店图片到不受约束的消费者照片。

http://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html

数据库中的所有图像均带有丰富的信息,包括50种不同的类别,1,000个描述性属性,边界框和服装地标。

特别是,将“类别和属性预测基准”类别用作时尚对象检测任务的训练数据。

在此处下载数据(Google Drive)并将其解压缩到data项目目录中的文件夹中。完成后将有三个子文件夹:

https://drive.google.com/drive/folders/0B7EVK8r0v71pWGplNFhjc01NbzQ

Anno- 注释,包括边界框标签,时尚地标标签,服装类别标签和服装属性标签。

评估- 分别用于训练,验证和测试集的图像名称。

img — 289,222种多样的服装图像。(为了加快开发速度,本文中使用了低分辨率图像)

先来看一下数据

从数据集中随机挑选了一些图像,并用其边界框打印。

注意:由于DeepFashion数据库已经提供了边界框标签,因此不需要为数据添加标签,而如果想为其他图像创建自己的标签或改善当前标签(如上图所示,一些边界框的质量并不完美,LabelImg将是完成这些工作的工具之一。

https://github.com/tzutalin/labelImg

还将使用图像元数据的聚合视图为训练集和测试集创建摘要表。摘要表将在以后的阶段中使用,以生成用于模型训练的建模数据。

汇总表-训练集

可以在此处找到Jupyter笔记本中用于可视化以上图像并生成汇总表的python脚本。结果,现在在文件夹中有摘要表(train_labels.csv&test_labels.csv)data。

https://github.com/ivanliu1989/Real-time-Mobile-Video-Object-Detection/blob/master/generate_summary_table.ipynb

注意:为简化工作,会在笔记本中看到仅选择前6个常见类别。

生成TF记录

为了有效地读取数据,TensorFlow使用TFRecord格式-一种用于存储二进制记录序列的简单格式。它正在对数据进行序列化以使它们能够被线性读取,尤其是在通过网络流传输数据的情况下。

要将图像数据转换为TFRecord格式,将使用以下python模板,并以创建的摘要表作为参考:

"""
Usage:
  # From tensorflow/models/
  # Create train data:
  python generate_tfrecord.py --csv_input=data/train_labels.csv  --output_path=data/train.record
  # Create test data:
  python generate_tfrecord.py --csv_input=data/test_labels.csv  --output_path=data/test.record
"""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
 
import os
import io
import pandas as pd
import tensorflow as tf
 
from PIL import Image
from object_detection.utils import dataset_util
from collections import namedtuple, OrderedDict
 
flags = tf.app.flags
flags.DEFINE_string('csv_input', '', 'Path to the CSV input')
flags.DEFINE_string('output_path', '', 'Path to output TFRecord')
flags.DEFINE_string('image_dir', '', 'Path to images')
FLAGS = flags.FLAGS
 
 
# TO-DO replace this with label map
def class_text_to_int(row_label):
    if row_label == 'Blouse':
        return 1
    if row_label == 'Shorts':
        return 2
    if row_label == 'Skirt':
        return 3
    if row_label == 'Sweater':
        return 4
    if row_label == 'Tank':
        return 5
    if row_label == 'Tee':
        return 6
    else:
        None
 
 
def split(df, group):
    data = namedtuple('data', ['filename', 'object'])
    gb = df.groupby(group)
    return [data(filename, gb.get_group(x)) for filename, x in zip(gb.groups.keys(), gb.groups)]
 
 
def create_tf_example(group, path):
    with tf.io.gfile.GFile(os.path.join(path, '{}'.format(group.filename)), 'rb') as fid:
        encoded_jpg = fid.read()
    encoded_jpg_io = io.BytesIO(encoded_jpg)
    image = Image.open(encoded_jpg_io)
    width, height = image.size
 
    filename = group.filename.encode('utf8')
    image_format = b'jpg'
    xmins = []
    xmaxs = []
    ymins = []
    ymaxs = []
    classes_text = []
    classes = []
 
    for index, row in group.object.iterrows():
        xmins.append(row['xmin'] / width)
        xmaxs.append(row['xmax'] / width)
        ymins.append(row['ymin'] / height)
        ymaxs.append(row['ymax'] / height)
        classes_text.append(row['class'].encode('utf8'))
        classes.append(class_text_to_int(row['class']))
 
    tf_example = tf.train.Example(features=tf.train.Features(feature={
        'image/height': dataset_util.int64_feature(height),
        'image/width': dataset_util.int64_feature(width),
        'image/filename': dataset_util.bytes_feature(filename),
        'image/source_id': dataset_util.bytes_feature(filename),
        'image/encoded': dataset_util.bytes_feature(encoded_jpg),
        'image/format': dataset_util.bytes_feature(image_format),
        'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
        'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
        'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
        'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
        'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
        'image/object/class/label': dataset_util.int64_list_feature(classes),
    }))
    return tf_example
 
 
def main(_):
    writer = tf.io.TFRecordWriter(FLAGS.output_path)
    path = os.path.join(FLAGS.image_dir)
    examples = pd.read_csv(FLAGS.csv_input)[['filename','class','xmin','ymin','xmax','ymax']]
    grouped = split(examples, 'filename')
    for group in grouped:
        tf_example = create_tf_example(group, path)
        writer.write(tf_example.SerializeToString())
 
    writer.close()
    output_path = os.path.join(os.getcwd(), FLAGS.output_path)
    print('Successfully created the TFRecords: {}'.format(output_path))
 
 
if __name__ == '__main__':
    tf.compat.v1.app.run()
 
python generate_tfrecord.py --csv_input=data/train_labels.csv --image_dir=data --output_path=data/train.record
python generate_tfrecord.py --csv_input=data/test_labels.csv --image_dir=data --output_path=data/test.record

注意:通过为新标签更新class_text_to_int(),可以为其他数据集使用相同的模板。

执行完成后,将在data文件夹下看到2个新文件,分别名为test.record和train.record。

生成标签图

现在需要创建一个标签映射,即将每个使用的标签映射到一个整数值。训练和推理过程都将使用标签图。

cat <<EOT >> data/label_map.pbtxt
item {
    id: 1
    name: 'Blouse'
}
item {
    id: 2
    name: 'Shorts'
}
item {
    id: 3
    name: 'Skirt'
}
item {
    id: 4
    name: 'Sweater'
}
item {
    id: 5
    name: 'Tank'
}
item {
    id: 6
    name: 'Tee'
}
EOT

上面的脚本为提供了一个名为的新文件label_map.pbtxt。如果要引入其他新标签,则需要相应地对其进行更新。

现在,已在data文件夹中准备好所有必需的文件。

模型配置和训练

下载预训练的模型

正如在开始时提到的,将使用预先训练的模型,而不是从头开始设计模型,检测模型动物园收集了广泛使用的预先训练的模型的列表。

https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md

例如,将使用SSD移动网络量化模型,该模型针对移动设备性能进行了优化,同时降低了模型推断的复杂性(同时牺牲了一些模型性能)。

export PROJECT_DIR=<YOUR PROJECT DIRECTORY>
 
cd $PROJECT_DIR/models
curl -L http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_quantized_300x300_coco_2019_01_03.tar.gz -o ssd_mobilenet_v2_quantized.tar.gz
tar -xvf ssd_mobilenet_v2_quantized.tar.gz
rm ssd_mobilenet_v2_quantized.tar.gz

模型文件将保存在以下models文件夹中。

需要注意的一些文件是:

  • model.ckpt — 模型的检查点(预先训练的模型/部分训练的模型),带有估算器,以进行进一步的训练。
  • pipeline.config — 模型,训练数据,评估数据等的配置。

更新模型管道配置

有五个主要部分pipeline.config。该模型部限定了网的预先设计的体系结构。该train_config部分是定义模型训练参数,这给灵活性来调整参数,如批量大小,学习率,学习步骤等。

model {
(... Add model config here...)
}
 
train_config : {
(... Add train_config here...)
}
 
train_input_reader: {
(... Add train_input configuration here...)
}
 
eval_config: {
}
 
eval_input_reader: {
(... Add eval_input configuration here...)
}

对于试用,将模型配置和超参数保留为默认值,并仅更新以下配置:

  • num_classes:6
  • fine_tune_checkpoint:检查点文件的路径model.ckpt
  • label_map_path:label_map.pbtxt上面创建的路径
  • tf_record_input_reader:路径train.record和test.record上面创建

模型训练

接下来,要初始化训练,现在可以直接使用来自TensorFlow Object Detection API的建模脚本:

export PROJECT_DIR=<YOUR PROJECT DIRECTORY>
export MODEL_DIR=$PROJECT_DIR/models/<YOUR MODEL>
export PIPELINE_CONFIG_PATH=$MODEL_DIR/pipeline.config
export TF_RESEARCH_MODEL_DIR=$PROJECT_DIR/tf-models/research
 
export NUM_TRAIN_STEPS=50000
export SAMPLE_1_OF_N_EVAL_EXAMPLES=1
 
# From the project/tf-models/research/ directory
# Make sure you've updated PYTHONPATH
cd $TF_RESEARCH_MODEL_DIR
python object_detection/model_main.py \
    --pipeline_config_path=${PIPELINE_CONFIG_PATH} \
    --model_dir=${MODEL_DIR} \
    --num_train_steps=${NUM_TRAIN_STEPS} \
    --sample_1_of_n_eval_examples=$SAMPLE_1_OF_N_EVAL_EXAMPLES \
    --alsologtostderr

训练开始后,应该会在下面的控制台中看到训练进度的日志。

此外,还可以使用张量板根据可视化的性能指标和在训练步骤中对验证集的预测来连续监视进度。

tensorboard --logdir=${MODEL_DIR}

注意1:如果在训练过程中出现内存不足错误,请尝试减少pipeline.config文件中训练步骤的批量大小。

注意2:可以随时停止训练,并稍后通过更新fine_tune_checkpoint中的任何检查点继续进行训练pipeline.config。

转换为TensorFlow Lite

拥有经过训练/部分受训练的模型后,要为移动设备部署模型,首先需要使用TensorFlow Lite将模型转换为针对移动和嵌入式设备进行了优化的轻量级版本。它使设备上机器学习推理具有低延迟和较小的二进制大小。它使用诸如量化内核之类的技术来构建更小和更快的(定点数学)模型。

目前仅支持SSD型号。目前不支持类似fast_rcnn之类的模型。

安装Bazel并生成冻结图

将需要首先安装Bazel构建工具(请参阅不同操作系统的安装指南)。

https://docs.bazel.build/versions/master/install.html
 
# Install Bazel macOS
# Other systems see: https://docs.bazel.build/versions/master/install.html
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew tap bazelbuild/tap
brew install bazelbuild/tap/bazel
 
# Check bazel version
bazel --version

安装完Bazel之后,将选择最新的检查点以获取可与TensorFlow Lite一起使用的兼容操作的TensorFlow冻结图。要获取冻结图,可以export_tflite_ssd_graph.py直接从中使用模板脚本tf-models/research。

注意:这是为了简单起见,同时应始终检查模型评估以确定最佳检查点/步骤。

export PROJECT_DIR=<YOUR PROJECT DIRECTORY>
export MODEL_DIR=$PROJECT_DIR/models/<YOUR SSD MODEL>
 
export TF_API_DIR=$PROJECT_DIR/tf-models/research
export MODEL_CONFIG=$MODEL_DIR/pipeline.config
export CHECKPOINT_PATH=$MODEL_DIR/model.ckpt-<CHECKPOINT NUMBER>
export OUTPUT_DIR=$MODEL_DIR/tmp/tflite
 
# Run the export_tflite_ssd_graph.py script to get the frozen graph
# Make sure PYTHONPATH is updated
cd $TF_API_DIR
python object_detection/export_tflite_ssd_graph.py \
--pipeline_config_path=$MODEL_CONFIG \
--trained_checkpoint_prefix=$CHECKPOINT_PATH \
--output_directory=$OUTPUT_DIR \
--add_postprocessing_op=true

这将在指定的输出目录()中提供两个文件(tflite_graph.pb&)。tflite_graph.pbtxt/tmp/tflite

之后,将使用TensorFlow Lite优化转换器TOCO从Tensorflow冻结图源文件(tflite_graph.pb)中获取优化模型。通过在tensorflow目录中的脚本下面运行,将生成量化模型以提高移动性能。

# Convert TensorFlow graphs into TensorFlow Lite graphs
# Clone tensorflow repo (can be in your workspace)
git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git
cd tensorflow
 
bazel run -c opt tensorflow/lite/toco:toco -- \
--input_file=$OUTPUT_DIR/tflite_graph.pb \
--output_file=$OUTPUT_DIR/detect.tflite \
--input_shapes=1,300,300,3 \
--input_arrays=normalized_input_image_tensor \
--output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' \
--inference_type=QUANTIZED_UINT8 \
--mean_values=128 \
--std_values=128 \
--change_concat_input_ranges=false \
--allow_custom_ops

如果脚本成功运行,现在应该在/tmp/tflite目录- 下看到一个新文件detect.tflite。该文件包含图形和所有模型参数,并且可以通过Andriod和iOS设备上的TensorFlow Lite解释器运行。

在移动设备上运行TensorFlow Lite模型

现在,还有最后一步将模型嵌入到移动应用程序中,这应该很简单,因为TensorFlow已经提供了示例应用程序,使人们更容易测试模型。

要下载示例应用代码并以ios为例:

# Install example app from tensorflow
cd <YOUR WORKSPACE>
git clone https://github.com/tensorflow/examples
 
# Install cocoapods if first time
sudo gem install cocoapods
 
# Install pods
cd examples/lite/examples/object_detection/ios/
pod install

注意:构建iOS应用程序不在本文讨论范围之内,基本上,以上脚本正在安装Podfile中列出的iOS应用程序的所有依赖项。脚本完成后,*.xcworkspace将在ios目录中创建一个文件。

将保存实际的模型文件,ios/ObjectDetection/Model其中包含模型文件(detect.tflite)和标签映射文件。需要覆盖模型中的模型文件和标签图。

# Copy your Tensorflow Lite model file
cp $OUTPUT_DIR/detect.tflite ./ObjectDetection/Model/
 
# Update label file
cat << until_it_ends | sudo tee ./ObjectDetection/Model/labelmap.txt
Blouse
Shorts
Skirt
Sweater
Tank
Tee
until_it_ends

接下来,构建应用程序:

  1. ObjectDetection.xcworkspace在Xcode中打开。
  2. 首次编译应用程序时,请更新捆绑包标识符,然后在“常规”->“签名”中选择开发团队。
  3. 将移动设备连接到笔记本电脑
  4. 在Xcode中构建并运行该应用程序。

建立项目后,该应用程序现在应该可以在移动设备上运行,并测试模型的性能如何!

下一步是什么

到目前为止,已经完成了使用实时视频对象检测的自定义模型创建iOS应用的过程,这也是通过利用一些现有的预训练模型来快速构建思想原型的良好起点。

有一些方法可以通过以下方式进一步使应用程序运行:

  • 手动标记原始图像数据以获得更好的训练集质量(例如,如下所示的LabelImg )

  • 模型选择和超参数调整可提高模型性能。
  • 容器化应用程序并利用云服务(例如TPU)进一步扩大建模范围。

本教程的 GitHub存储库。

https://github.com/ivanliu1989/Real-time-Mobile-Video-Object-Detection

参考

  • https://www.tensorflow.org/lite/examples?source=post_page-----a75fa0c5859d----------------------
  • https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/training.html?source=post_page-----a75fa0c5859d----------------------#training-the-model
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档