Cat Ghonim:如何使猫在家里的草坪上不放松自己?

有65岁的加利福尼亚程序员Robert Bond。 他有一个园艺妻子,非常爱她干净的草坪。 但这是加利福尼亚州,没有带猫保护系统的两米围栏。 邻居的猫在草坪上行走,胡扯!



这个问题必须解决。 罗伯特是如何决定的? 他在计算机上购买了一些熨斗,将一台室外监控摄像头连接到草坪上望去,然后做了一件不寻常的事情,他下载了可用的免费开源软件-神经网络,并开始训练她识别摄像头图像中的猫。 一开始的任务似乎微不足道,因为如果您学到了一些东西并且很容易,那么这对猫来说就是对的,因为猫在互联网上乱七八糟,所以有成千上万的猫。 如果一切都这么简单,但情况变得更糟,在现实生活中,猫大多会在晚上胡扯。 互联网上几乎没有夜猫子在草坪上撒尿的照片。 在工作期间,有些猫甚至设法从灌溉系统中喝水,但仍将其丢弃。



下面我们提供作者对该项目的描述,可以在此处找到英文版本。

这个项目的动机有两点:希望更多地了解神经网络软件,并希望鼓励附近的猫在草坪旁闲逛。

该项目仅包含三个硬件组件: Nvidia Jetson TX1板, Foscam FI9800P IP摄像机和连接到继电器粒子光子 。 摄像机安装在草坪一侧的房屋一侧。 她联系WI-FI接入点,然后联系Jetson。 粒子光子和继电器安装在灌溉系统的控制单元中,并连接到厨房的WI-FI接入点。

在此过程中,将摄像机配置为监视院子中的变化。 发生变化时,相机会每秒将一组7张图像传输到Jetson。 由Jetson提供支持的服务跟踪传入的图像,并将其传输到Caffe的深度训练神经网络。 如果网络检测到猫,Jetson会向云中的“粒子光子”服务器发送信号,该服务器会向“光子”发送消息。 光子通过打开喷头2分钟来响应。

在这里,猫走进了框架,打开了相机:



几秒钟后,猫进入院子中央,再次打开相机并启动了灌溉系统的洒水装置:



相机设定


安装相机没有什么不寻常的。 唯一的永久连接是12伏的有线连接,该连接穿过壁架下方的小孔。 我将相机安装在一个木盒子上,用草坪拍摄了前院。 一束电线连接到了我藏在盒子里的相机。

按照Foscam的说明将其与Jetson的AP关联(请参见下文)。 在我的设置中,Jetson为10.42.0.1。 我为摄像机分配了一个固定的IP地址10.42.0.11,以便于查找。 完成此操作后,将Windows便携式计算机连接到摄像机并配置“警告”参数以激活更改。 通过警告(警报)设置通过FTP上传7张图像。 然后在Jetson上为其提供用户ID和密码。 我的相机通过FTP将640x360图像发送到其主目录。

在下面,您可以看到为摄像机配置选择的参数。



设置粒子光子


光子很容易设置。 我把它放在灌溉控制单元中。



左侧带有蓝色LED的黑匣子是在eBay上购买的24 V AC(5 V)至5 V DC转换器。 您可以在中继板上看到白色的继电器,在前面看到蓝色的连接器。 光子本身在右边。 两者都粘在一块纸板上以将它们固定在一起。

转换器的5 V输出连接到粒子光子VIN连接器。 继电器板大部分是模拟的:它具有一个集电极开路NPN晶体管和一个3 V继电器,该晶体管的标称输入电压为3.3V。 光子控制器无法提供足够的电流来控制继电器,因此我通过一个电阻为15欧姆,功率为1/2 W的电阻器将晶体管输入的集电极连接至5 V,从而限制了电流。 继电器触点与普通控制电路并联连接至水风扇。

这是连接图:

24VAC转换器24VAC <--->控制箱24VAC OUT
24VAC转换器+ 5V <--->光子VIN,继电器板上的电阻+ 3.3V
24VAC转换器GND <--->光子GND,继电器GND
光子D0 <--->继电器板信号输入
继电器COM <--->控制箱24VAC OUT
继电器NO <--->前院水阀

安装Jetson


添加到Jetson的唯一硬件组件是SATA SSD和小型Belkin USB集线器。 集线器有两个连接键盘和鼠标的无线键。

SSD出现了问题。 我将其重新格式化为EXT4并将其安装为/ caffe。 我极力建议您从Jetson内部SD卡中删除所有项目代码,Git存储库和应用程序数据,因为在升级Jetpack时通常最容易擦除系统。



如果您遵循本指南,则设置无线访问点非常简单(正确!)。 只需按照指示使用Ubuntu菜单,并确保添加此配置参数

我将vsftpd安装为FTP服务器 。 该配置主要是库存。 我没有启用匿名FTP。 我为相机提供了不再用于任何用途的用户名和密码。

我使用JetsonHacks配方安装了Caffe。 我认为当前版本中不再存在LMDB_MAP_SIZE问题,因此请在进行任何更改之前尝试对其进行构建。 您应该能够运行JetsonHacks shell脚本中提到的测试和计时演示。 我目前正在使用Cuda 7.0,但不确定在此阶段是否有意义。 使用CDNN,可以在这些小型系统中节省大量内存。 构建完成后,将构建目录添加到PATH变量中,以便脚本可以找到Caffe。 还将Caffe Python lib目录添加到您的PYTHONPATH。

~ $ echo $PATH /home/rgb/bin:/caffe/drive_rc/src:/caffe/drive_rc/std_caffe/caffe/build/tools:/usr/local/cuda-7.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ~ $ echo $PYTHONPATH /caffe/drive_rc/std_caffe/caffe/python: ~ $ echo $LD_LIBRARY_PATH /usr/local/cuda-7.0/lib:/usr/local/lib 

我正在使用完全卷积网络进行语义分割(FCN)选项。 参见伯克利模型动物园github

我尝试了其他几个网络,最后选择了FCN。 在下一篇文章中阅读有关选择过程的更多信息。 Fcn32s在TX1上运行良好-占用了超过1 GB的内存,运行约10秒钟,并在约三分之一的时间内分割了640x360图像。 当前github存储库中有一组不错的脚本,并且设置独立于图像的大小-它调整网络的大小以适合您放入其中的内容。

要尝试,您将需要部署已经训练有素的Caffe模型。 这需要几分钟:文件大小fcn32s-heavy-pascal.caffemodel超过500 MB。

 $ cd voc-fcn32s $ wget `cat caffemodel-url` 

通过将Image.open()命令中的路径更改为相应的.jpg来编辑infer.py。 更改“ net”行,使其指向刚加载的模型:

  -net = caffe.Net('fcn8s/deploy.prototxt', 'fcn8s/fcn8s-heavy-40k.caffemodel', caffe.TEST) +net = caffe.Net('voc-fcn32s/deploy.prototxt', 'voc-fcn32s/fcn32s-heavy-pascal.caffemodel', caffe.TEST) 

您将需要voc-fcn32s / deploy.prototxt文件。 它很容易从voc-fcn32s / train.prototxt生成。 查看voc-fcn8s / train.prototxt和voc-fcn8s / deploy.prototxt之间的更改,以了解如何执行此操作,或者可以从我在github上的chas -cats存储库中获取它。 您现在应该可以运行了。

  $ python infer.py 

我的存储库包括infer.py的多个版本,一些Python实用程序,这些实用程序了解分段文件,Photon代码和管理脚本以及用于启动和监视系统的操作脚本。 在下面阅读有关该软件的更多信息。

网络选择


通常训练用于图像识别的神经网络来识别一组对象。 假设我们给每个对象从1到n的索引。 分类网络回答了“此图像中有哪些对象?”的问题。 返回一个从零到n-1的数组,其中每个数组项的值都从零到一。 零表示该对象不在图像中。 非零值表示当该值接近于1时,它存在的可能性会增大。 这是由5个元素组成的猫和男人:



分段网络将列表中对象所占区域的图像像素进行了细分。 她通过返回带有记录的数组来回答这个问题,该记录对应于图像中的每个像素。 如果每个记录是背景像素,则每个记录的值为零;对于它可以识别的n个不同对象,其记录的值从1到n。 这个虚构的例子可能是一个人的脚:



该项目是旨在使用计算机控制无线电遥控汽车的大型项目的一部分。 这个想法是使用神经网络来确定汽车的位置(全球三维位置和方向),以将导航命令传输到汽车。 相机是固定的,草坪大部分是平坦的。 我可以稍微使用触发器来更改3d位置,以便神经网络可以找到屏幕像素和方向。 猫在所有这一切中的作用是“预期目的”。

我开始主要考虑汽车,因为我不知道结果如何,假设认识到具有预训练网络的猫是微不足道的。 经过大量的工作(在本文中将不做详细介绍),我决定可以以相当高的可靠性确定汽车的方向。 以下是292.5度角的训练镜头:



大部分工作是通过分类网络Caffe模型bvlc_reference_caffenet完成的。 因此,我决定让分段网络任务确定机器在屏幕上的位置。

我使用的第一个网络是Faster R-CNN [1]。 它返回图像中对象的边界框,而不是像素。 但是对于此应用程序,Jetson上的网络速度太慢。 包围盒的想法非常吸引人,因此我还研究了面向驾驶的网络[2]。 她也太慢了。 FCN [3]是我尝试过的最快的细分网络。 “ FCN”表示“完全卷积网络”,即完全卷积网络,因为它不再需要输入任何特定的图像大小,而仅由卷积/池组成。 仅切换到卷积层会导致明显的加速,在Jetson上将我的图像分类大约1/3秒。 FCN包括一组用于培训和易于部署的Python脚本。 Python脚本会调整网络的大小以适合传入图像的任何大小,从而使处理主图像更加容易。 我有一个赢家!

FCN GitHub版本具有多个选项。 首先,我尝试了voc-fcn32s。 效果很好。 Voc-fcn32s被预先训练为20种标准voc-class。 由于这太简单了,所以我尝试了pascalcontext-fcn32s。 他接受了59课的培训,包括草木树木,所以我认为应该更好。 但事实证明,并非总是如此-输出​​的图像具有更多的像素集,并且叠加在草丛和灌木丛上的猫和人的分割并不那么精确。 来自siftflow的细分更加复杂,因此我很快又回到了voc选项。

选择voc网络仍然意味着需要考虑三件事:voc-fcn32s,voc-fcn16s和voc-fcn8s。 它们在输出细分的“步骤”上有所不同。 步骤32是网络的主要步骤:在卷积层完成时,将640x360的图像缩小为20x11的网络。 然后,如[3]中所述,这种粗略的细分会“反卷积”回640x360。 通过向网络添加更多逻辑以实现更好的分段,可以实现步骤16和步骤8。 我什至没有尝试-我尝试了32段细分,但后来我坚持了下来,因为细分对于该项目来说足够好,而且如上所述,对于其他两个网络来说,培训看起来更加复杂。

培训课程


当我打开并启动系统时,我注意到的第一件事是网络仅识别出30%的猫。 我发现有两个原因。 首先,猫经常在晚上来,所以相机会在红外线下看到它们。 这很容易解决-只需添加一些分割的猫的红外图像进行训练即可。 在查看了训练包中的几百张猫照片后,我发现的第二个问题是,许多照片都属于“看着我的可爱猫”品种。 这些是在猫眼水平上的猫的正面图像。 猫要么躺在它的背上,要么躺在它主人的腿上。 它们看起来不像猫在我院子里漫游。 同样,可以使用某些分段的白天图像轻松修复它。



如何在训练图像中分割对象? 我的方法是减去背景图像,然后处理前景像素以指示要跟踪的对象。 实际上,这很好用,因为在我的相机存档中,通常有一张图像是在分割图像之前几秒钟拍摄的。 但是有些工件需要清理,并且分割经常需要澄清,因此我编写了一个用于编辑图像段的粗略准备实用程序src / extract_fg.cpp。 请参阅源文件顶部的注释以供使用。 它有点笨拙,验证错误也很小,需要进行一些改进,但足以胜任这项任务。

现在我们有了一些训练图像,让我们看看如何做。 我将voc-fcn32s克隆到rgb_voc_fcn32s目录。 在本课程结束之前,所有文件名都将引用此目录。

  $ cp -r voc-fcn32s rgb_voc_fcn32s 

我的github上的代码,包括data / rgb_voc中的样本训练文件。 主要变化如下所示。

训练文件格式


分布式数据层需要硬编码的图像和分段目录。 训练文件每个文件一行。 然后数据层获取图像文件和段的名称,并添加硬编码的目录名称。 这对我不起作用,因为我有几类训练数据。 我的训练数据有一组线,每条线包含一个图像和该图像的分段。

  $ head data/rgb_voc/train.txt /caffe/drive_rc/images/negs/MDAlarm_20160620-083644.jpg /caffe/drive_rc/images/empty_seg.png /caffe/drive_rc/images/yardp.fg/0128.jpg /caffe/drive_rc/images/yardp.seg/0128.png /caffe/drive_rc/images/negs/MDAlarm_20160619-174354.jpg /caffe/drive_rc/images/empty_seg.png /caffe/drive_rc/images/yardp.fg/0025.jpg /caffe/drive_rc/images/yardp.seg/0025.png /caffe/drive_rc/images/yardp.fg/0074.jpg /caffe/drive_rc/images/yardp.seg/0074.png /caffe/drive_rc/images/yard.fg/0048.jpg /caffe/drive_rc/images/yard.seg/0048.png /caffe/drive_rc/images/yard.fg/0226.jpg /caffe/drive_rc/images/yard.seg/0226.png 

我将voc_layers.py替换为rgb_voc_layers.py,它了解新方案:

  --- voc_layers.py 2016-05-20 10:04:35.426326765 -0700 +++ rgb_voc_layers.py 2016-05-31 08:59:29.680669202 -0700 ... - # load indices for images and labels - split_f = '{}/ImageSets/Segmentation/{}.txt'.format(self.voc_dir, - self.split) - self.indices = open(split_f, 'r').read().splitlines() + # load lines for images and labels + self.lines = open(self.input_file, 'r').read().splitlines() 

并修改了train.prototxt以使用我的rgb_voc_layers代码。 注意,参数也不同。

  --- voc-fcn32s/train.prototxt 2016-05-03 09:32:05.276438269 -0700 +++ rgb_voc_fcn32s/train.prototxt 2016-05-27 15:47:36.496258195 -0700 @@ -4,9 +4,9 @@ top: "data" top: "label" python_param { - module: "layers" - layer: "SBDDSegDataLayer" - param_str: "{\'sbdd_dir\': \'../../data/sbdd/dataset\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 116.66877, 122.67892)}" + module: "rgb_voc_layers" + layer: "rgbDataLayer" + param_str: "{\'input_file\': \'data/rgb_voc/train.txt\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 1 

val.prototxt中几乎相同的更改:

  --- voc-fcn32s/val.prototxt 2016-05-03 09:32:05.276438269 -0700 +++ rgb_voc_fcn32s/val.prototxt 2016-05-27 15:47:44.092258203 -0700 @@ -4,9 +4,9 @@ top: "data" top: "label" python_param { - module: "layers" - layer: "VOCSegDataLayer" - param_str: "{\'voc_dir\': \'../../data/pascal/VOC2011\', \'seed\': 1337, \'split\': \'seg11valid\', \'mean\': (104.00699, 116.66877, 122.67892)}" + module: "rgb_voc_layers" + layer: "rgbDataLayer" + param_str: "{\'input_file\': \'data/rgb_voc/test.txt\', \'seed\': 1337, \'split\': \'seg11valid\', \'mean\': (104.00699, 116.66877, 122.67892)}" 

解算器


运行Solve.py开始锻炼:

  $ python rgb_voc_fcn32s / solve.py 

它修改了Caffe的某些正常机制。 特别是,迭代次数设置在文件的底部。 在此特定设置中,迭代是一幅图像,因为网络大小会针对每幅图像进行更改,并且图像一次会被跳过。

与Nvidia合作的一大好处是可以使用真正出色的设备。 我在工作站中内置了Titan,我的管理层不介意让我将其用于与此项目一样可疑的事情。 我的最后一次训练是4,000次迭代,在Titan上花了两个多小时。

我学到了一些东西


  • 少量图像(少于50张)足以训练网络识别夜间入侵者。
  • 夜间射击让网络认为小径上的阴影是猫。
  • 负片拍摄,即没有分段像素的图像,有助于解决阴影问题。
  • 使用固定摄像机重新训练网络很容易,因此所有不同之处都归为随机类别。
  • 猫和人重叠在随机的背景下,有助于解决过度训练带来的问题。

如您所见,该过程是迭代的。

推荐建议


[1]更快的R-CNN:使用区域提议网络实现实时目标检测任少清,何开明,罗斯·吉尔希克,孙健abs / 1506.01497v3
[2]对高速公路驾驶深度学习的实证评估Brody Huval,Tao Wang,Sameep Tandon,Jeff Kiske,Will Song,Joel Pazhayampallil,Mykhaylo Andriluka,Pranav Rajpurkar,Toki Migimatsu,Royce Cheng-Yue,Fernando Cojuju,Fernando Mujica, Andrew Y.Ng arXiv:1504.01716v3github.com /brodyh / caffe.git
[3]用于语义分割的全卷积网络Jonathan Long,Evan Shelhamer,Trevor Darrell arXiv:1411.4038v2github.com /shelhamer / fcn.berkeleyvision.org.git

结论


为了教神经网络识别夜猫,有必要添加必要的数据并进行累积。 之后,进行了最后一步-将系统连接到阀门,从而启动喷涂机。 这个想法是,一旦猫进入草坪并想要适应,它就会开始被浇水。 猫丢了。 这样就解决了任务,妻子幸福了,所有这些奇怪的奇迹都是一个神经网络,它学会识别猫,发现互联网上没有足够的源图像进行训练,并且已经学会了这一点,成为了世界上唯一可以识别夜猫的神经网络。

值得一提的是,这一切都是由一个不是超级程序员的人完成的,他不是一辈子都在Yandex或Google中工作,并借助廉价,紧凑和简单的硬件帮助。

一点广告:)


感谢您与我们在一起。 你喜欢我们的文章吗? 想看更多有趣的资料吗? 通过下订单或将其推荐给您的朋友来支持我们,在我们为您发明的独特模拟入门级服务器上为Habr用户提供30%的折扣: 关于VPS(KVM)E5-2650 v4(6核)的全部真相10GB DDR4 240GB SSD 1Gbps从$ 20还是如何划分服务器? (RAID1和RAID10提供选件,最多24个内核和最大40GB DDR4)。

戴尔R730xd便宜2倍? 只有我们有2台Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100电视在荷兰起价199美元 戴尔R420-2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB-$ 99起! 阅读有关如何构建基础架构大厦的信息。 使用价格为9000欧元的Dell R730xd E5-2650 v4服务器的上等课程?

Source: https://habr.com/ru/post/zh-CN473334/


All Articles