使用TensorFlow与OpenCV识别实时视频中的对象

原文标题:Building a Real-Time Object Recognition App with Tensorflow and OpenCV
作者: “Dat Tran“

使用TensorFlow与OpenCV识别实时视频中的对象

本文将介绍如何使用python3中(python 3.5)TensorFlow的对象检测APIOpenCV构建一个实时对象识别应用。本文的主体是在我建立应用时遇到的挑战。点击此处查看完整代码

以下是app实际使用情况:

0625

我尝试区分桌子上各种小物件。

动机

Google刚刚发布了新的TensorFlow对象检测API。第一次发布的内容包括:
1.一些预先训练好的模型(尤其是注重轻量化模型,因此可以在移动设备上使用)
2.使用其中一个已发布的模型的Jupyter notebook范例
3.一些可以用来重新训练模型的方便的代码,例如,在你自己的数据集上训练。

我将基于这个API来建立一个实时对象识别演示。

对象检测演示

首先,我借鉴了TensorFlow模型notebook实例。这基本上包括使用先前训练好的模型的所有步骤。在他们的例子中,使用了‘SSD with Mobilenet‘模型,你同样可以下载一些其他的预先训练模型,他们称为’TensorFlow detection model zoo’.顺便提醒,这些模型是在COCO 数据集上训练的并且依赖模型速率(慢,中, 快)和模型表现(MAP-平均值精度)的程度不同。

我接下来运行了范例,这个例子描述的很清晰,它实际做了:

1.导入需要的包, 例如TensorFlow, PIL 等。
2.定义一些变量,例如类的数量,模型的名称。
3.下载frozen model(pb-protobuf)并且载入内存
4.载入一些帮助代码。
5.使用两张测试图片和代码检测。

注意:在运行范例之前,请查看安装注释,尤其是protobuf编译部分非常重要。

# From tensorflow/models/research/
protoc object_detection/protos/*.proto --python_out=.

如果不运行这行命令,范例就不能正常工作。

我接着相应的修改了范例代码:
移除下载模型部分。
我们不需要PIL,因为OpenCV中的视频流已经被存储在numpy数组里面(PIL在被用来读取图片,视频流时会造成重大的开销)。
没有对于TensorFlow部分的with声明,由于在每个视频流之后,这个session需要重新开始,这将会是一个巨大的开销。

接着我使用OpenCV连接网络摄像机。有许多范例介绍如何连接网络摄像机,即便是官方文件也有。所以,我不会详细介绍。更有趣的部分是我为了提高app使用性能所做的优化。在我看来,我关注好的FPS-每秒帧数。

通常,OpenCV中的许多例子并不是最优的,例如OpenCV中的一些函数是输入输出有界的。所以我必须提出不同的解决方案:

从网络摄像头读取frame造成大量I/O,我的想法是使用multiprocessing library把这部分完全移动到不同的python进程中。有时这并不管用。在stackoverflow上有一些关于为什么不能工作的解释,我不会详细介绍这部分。幸运的是,我在Adrian Rosebrock的pyimagesearch网站上找到了完美的范例,使用了Threading代替,并且极大增加了FPS。顺便提一句,如果你想了解multiprocessing和threading的不同,可以在stackoverflow上看到清晰的解释

在每次APP启动时,向内存中载入frozen模型是一个相当大的花费。我已经对每次运行使用一个TF进程然而还是很慢。所以我该如何做才能解决问题?答案非常简单。我使用了multiprocessing library将对象识别部分的重大花费移动到了多个过程中。由于每个进程都需要向内存中载入模型,并且启动TF模块,第一次启动依然会比较慢,但是之后我们会在平行对应中受益。

降低视频流中frame的宽度和高度也提高了FPS。

注意:如果像我一样在Mac OSX上使用OpenCV 3.1, 一段时间之后,OpenCV的视频捕捉有几率崩溃。如果想解决这个问题,请还原会OpenCV 3.0版本。

结论和展望

如果你喜欢本文请给我一个好评。下载代码,并且自己尝试运行,查看TensorFlow对象识别的API。这些API在第一眼看来就非常简单。下一步我想尝试使用这些API训练我自己的训练集,同时也使用其它APP的预先训练模型。我对我的APP表现不是非常满意。FPS仍然不是最优的。在OpenCV中我遇到了解决不了的瓶颈,但是我有一些可替换的方法,像使用WebRTC.然而这是基于网络的。进一步,我在考虑使用async来提高帧率。

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营