利用WebRTC和TensorFlow通过网络实现计算机视觉2

作者:Chad Hart(原文链接

翻译:刘通

原标题:Computer Vision on the Web with WebRTC and TensorFlow

前文连接:利用WebRTC和TensorFlow通过网络实现计算机视觉1

 

代码走查

第1部分——确保Tensorflow正常工作

为确保TensorFlow对象检测API正常工作,我们首先从用于演示对象检测的官方版Jupyter Notebook经调整后的版本着手。我将此文件保存为object_detection_tutorial.py

如果您剪切并粘贴该notebook的每个部分,得到的结果应如下所示:

cv21-1

cv21-2

cv21-3

cv21-4

在这里我就不再赘述实际TensorFlow代码的作用了,这方面的信息可在Jupyter演示及其他教程中找到。我将重点介绍我们对代码所做的修改。

我们不需要的内容

我注释掉了几个小节:

  1. 更改了一些位置引用
  2. 删除了对Python matplot的所有引用。Python matplot用于在GUI环境中以可视化方式呈现输出结果。在我的Docker环境中没有设置它——根据您采用的具体运行方式,可以酌情决定是否保留这些引用。

对象检测API的输出结果

正如第111行所示,对象检测API输出4种对象:

  1. 类——一个由对象名组成的数组
  2. 分值——一个由置信度分值组成的数组
  3. 方框——检测到的每个对象所在的位置
  4. 数量——检测到的对象总数

类、分值和方框都是相互并列、大小相等的数组,因此classes[n]与scores[n]和boxes[n]都是一一对应的。

由于我删去了可视化功能,我们需要通过某种方式来查看结果,所以我们要把下面的命令添加到文件末尾:

cv22

第一个np.squeeze部分只是将多维数组输出缩减成一维,这与原来的可视化代码一样。我认为这是TensorFlow的一个副产品,因为它通常会输出多维数组。

接着我们要为它输出的分值设置一个阈值。好像TensorFlow默认会返回100个对象。其中很多对象嵌套在置信度更高的对象内或与这些对象重叠。在选择阈值方面我还没有发现任何最佳做法,不过对于这些示例图像来说,50%似乎是合适的。

最后,我们需要循环遍历这些数组,直接输出那些超过阈值的分值。

如果您运行下面的命令:

cv23

应该会获得下面的输出:

cv24

第2部分——打造一项对象API网络服务

在这一部分,我们将对教程代码作一些改动,以将其作为一项网络服务加以运行。我在Python方面的经验颇为有限(主要在Raspberry Pi项目中使用过),所以如有不对的地方,请添加备注或提交拉取请求,以便我可以修正。

2.1 将演示代码转变成一项服务

至此我们已经让TensorFlow Object API能够正常工作了,接下来我们就将它封装成一个可以调用的函数。我将演示代码复制到了一个名为object_detection_api.py的新python文件中。您可以看到,我删除了很多没有用到或注释掉的行,以及用于将详细信息输出到控制台的部分(暂时删除)。

由于我们要将这些信息输出到网络上,因此最好将我们的输出结果封装成一个JSON对象。为此,请务必向您导入的内容中添加一个import jso语句,然后再添加下面的命令:

cv25

接下来,我们要重复利用之前的代码创建一个get_objects函数:

cv26

在此函数中我们添加了一个图像输入参数和一个默认为0.5的threshold值。其余内容都是在演示代码的基础上重构的。

现在我们再向此函数添加一些代码,以查询具体的值并将它们输出到一个JSON对象中:

cv27

这一次我们是使用Object类来创建一些初始元数据并将这些元数据添加到output列表中。然后我们使用循环向此列表中添加Object数据。最后,将此列表转换成JSON并予以返回。

之后,我们来创建一个测试文件(这里要提醒自己:先做测试),以检查它是否调用了object_detection_test.py

cv28

至此万事俱备,接下来就是运行了。

cv29

除了前面的控制台输出之外,您应该还会看到一个JSON字符串:

cv210

2.2 添加一个网络服务器

我们已经有了函数——接下来我们就用它来打造一项网络服务。

先使用测试用的路由(Route)运行

我们有了一个可以轻松添加到网络服务的良好API。我发现使用Flask是最简单的测试方法。我们来创建一个server.py,然后执行一次快速测试:

cv211

现在,运行该服务器:

cv212

确保该服务正常工作

然后调用该网络服务。就我自己的情况而言,我只是从主机运行了下面的命令(因为我的Docker实例现在正在前台运行该服务器):

cv213

json.tool将帮助您为输出结果设置格式。您应该会看到下面的结果:

cv214

好了,接下来我们就要接受一个包含一个图片文件及其他一些参数的POST,使用真实路由运行了。为此,需要在/test路由函数下添加一个新的/image路由:

cv215

这样就会从一个采用表单编码方式的POST中获取图片,并且可以选择指定一个阈值,然后将该图片传递给我们的object_detection_api。

我们来测试一下:

cv216

这时看到的结果应该与上面使用/test路径时相同。继续测试,可以指定您任选的其他本地图像的路径。

让该服务在localhost以外的位置也能正常工作

如果您打算在localhost上运行浏览器,可能就不需要再做些什么。但如果是真实的服务,甚至是在需要运行很多测试的情况下,这就不太现实了。如果要跨网络运行网络服务,或者使用其他资源运行网络服务,都需要用到CORS。幸好,在路由前添加以下代码就可以轻松解决这一问题:

cv217

让该服务支持安全源

最佳做法是搭配HTTPS使用WebRTC,因为Chrome和Safari等浏览器若不作专门配置,则仅支持安全源(不过Chrome可以很好地支持localhost,您也可以将Safari设为允许在非安全网站上捕获信息——跳转到此处的调试工具部分了解详情)。为此,您需要获取一些SSL证书或生成一些自托管证书。我将我自己的证书放在了ssl/目录中,然后将最后一行app.run更改为:

cv218

如果您使用的是自签名证书,您在使用CURL进行测试时可能需要添加–insecure选项:

cv219

严格来讲并非一定要生成您自己的证书,而且这会增加一定的工作量,所以在server.py最底部,我依然让SSL版本保持被注释掉的状态。

如果是要投入生产环境中使用的应用程序,您可能需要使用nginx之类的代理向外发送HTTPS,同时在内部依然使用HTTP(此外还要做很多其他方面的改进)。

添加一些路由以便提供我们的网页

在开始介绍浏览器端的工作之前,我们先为后面需要用到的一些路由生成存根。为此,请将下面的代码放在index()路由后面:

cv220

Python方面的工作到此就结束了。接下来我们将用到JavaScript,并且需要编写一些HTML。

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

WebRTC 中文社区由

运营