第 3 节:使用 TensorFlow 的计算机视觉的高级实现
在本节中,您将基于从上一节中获得的理解,并开发更新的概念并学习用于动作识别和对象检测的新技术。 在本节中,您将学习不同的 TensorFlow 工具,例如 TensorFlow Hub,TFRecord 和 TensorBoard。 您还将学习如何使用 TensorFlow 开发用于动作识别的机器学习模型。
在本节结束之前,您将能够执行以下操作:
- 理解理论并开发各种动作识别方法(例如 OpenPose,Stacked HourGlass 和 PoseNet)的直觉(第 9 章)
- 分析 OpenPose 和 Stacked HourGlass 代码,以加深对如何构建非常复杂的神经网络以及连接其不同模块的理解。 希望您可以通过这次学习来构建自己的复杂网络(第 9 章)
- 使用 TensorFlow PoseNet 通过网络摄像头进行动作识别(第 9 章)
- 了解各种类型的对象检测器,例如 SSD,R-FCN,更快的 R-CNN 和 MaskR-CNN(第 10 章)。
- 了解如何在 TFRecord 中转换图像和标注文件以输入到 TensorFlow 对象检测 API(第 10 章)
- 了解如何使用自己的图像来使用 TensorFlow 对象检测 API 训练模型并对其进行推理(第 10 章)
- 了解如何使用 TensorFlow 集线器进行对象检测以及如何使用 TensorBoard 可视化训练进度(第 10 章)
- 了解与对象检测相关的 IOU,ROI,RPN 和 ROI 对齐(第 10 章)。
- 了解如何使用 Mask R-CNN 对图像进行分割(第 10 章)
- 了解不同的 OpenCV 以及基于连体网络的对象跟踪方法,并将其用于视频文件(第 10 章)
本节包括以下章节:
- “第 9 章”,“使用多任务深度学习的动作识别”
- “第 10 章”,“使用 R-CNN,SSD 和 R-FCN 进行对象检测”
九、使用多任务深度学习的动作识别
动作识别是计算机视觉的关键部分,涉及识别人的手,腿,头和身体的位置,以检测特定的运动并将其分类为众所周知的类别。 困难在于视觉输入(例如,身体凌乱或衣服被覆盖)的变化,类似的动作,不同的类别(如饮用水或使用手持手机的通话)以及获得代表性的训练数据。
本章详细概述了可用于人体姿势估计和动作识别的关键方法。 动作识别将姿势估计方法与基于加速度的活动识别以及基于视频和三维点云的动作识别相结合。 该理论将通过使用 TensorFlow 2.0 的实现解释加以补充。
本章分为四个部分。 前三个讨论了可用于人体姿势估计的三种不同方法,而第四个全部涉及动作识别:
- 人体姿势估计 – OpenPose
- 人体姿势估计 – 栈式沙漏模型
- 人体姿势估计 - PoseNet
- 使用各种方法的动作识别
人体姿势估计 – OpenPose
人体姿势估计是深度神经网络取得巨大成功的另一个领域,并且近年来发展迅速。 在最后几章中,我们了解到深度神经网络结合使用线性(卷积)和非线性(ReLU)运算来预测给定输入图像集的输出。 在姿势估计的情况下,当提供一组输入图像时,深度神经网络会预测关节位置。 图像中的标记数据集由一个边界框组成,该边界框确定图像中的N
个人和每人K
关节。 随着姿势的改变,关节的方向也会改变,因此通过观察关节的相对位置来表征不同的位置。 在以下各节中,我们将描述可以使用的不同姿势估计方法。
OpenPose 背后的理论
OpenPose 是第一个针对图像或视频中的多个人的开源实时二维姿态估计系统。 它主要由卡内基梅隆大学(CMU)的学生和教职员工开发。 论文的标题是《OpenPose:使用部分亲和力字段进行实时多人 2D 姿势估计》,作者是 Zhe Cao,Gines Hidalgo,Tomas Simon,Shih-En-Wei 和 Yaser Sheikh。 您可以在这个页面上找到该论文。
请注意,OpenPose 首次出现在 CVPR 2017 中,题目为《使用部分亲和力字段进行实时多人 2D 姿势估计》,可在这个页面中找到。 接下来是 2018 年的论文《OpenPose:使用部分亲和力字段的实时多人 2D 姿势估计》,网络得到了进一步改善。
本文的主要发现如下:
- 网络的输入由 VGG-19 模型的前 10 层组成,用于生成一组特征映射
F
。 下图显示了 OpenPose 网络的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hP22sIPK-1681784662627)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/2046a738-43a7-4f9b-9500-f98202f7a431.png)]
- OpenPose 网络将特征映射作为输入,并由 CNN 的两个阶段组成:第一阶段使用
T[p]
编号预测部分相似性字段(PAF) 迭代次数,而第二阶段则以T[c]
迭代次数预测置信度图。 由于以下两个关键指标,2018 年提出的 OpenPose 模型是对 2017 年提出的早期模型的总体改进: - 通过先计算 PAF,再计算置信度图,可将计算时间减少一半。 这不同于两者的同时计算以及用
3 x 3
卷积代替3 x 3
卷积。 - 改进的 PAF 估计(2018 年论文)通过增加神经网络的深度来改善常规 PAF(2017 年)的置信度图,从而提高了准确率。
- 在下一阶段中,将前一阶段的预测与原始图像特征
F
合并在一起,以为图像中的所有人产生二维关键点预测。 在估计的预测,地面真实特征映射和 PAF 之间的每个阶段的末尾都应用了损失函数。 重复此过程几次迭代,从而得到最新的特征映射和 PAF 检测。 - 使用基于特征向量的自下而上的方法,无论图像中有多少人,都可以实现高精度。
- 置信度图是特定特征(身体部位)可以位于任何给定像素中的概率的二维表示。 另一方面,特征映射表示 CNN 给定层中给定过滤器的输出图。
- 网络架构由几个
1 x 1
和1 x 1
核组成。 每个1 x 1
核的输出是连接的。 - OpenPose 是第一个实时多人系统,使用三个独立的 CNN 块检测 135 个关键点:(a)身体和脚部检测,(b)手部检测和(c)人脸检测。
- 在对象检测讨论(“第 5 章”,“神经网络架构和模型”和“第 7 章”,“使用 YOLO 进行对象检测”)中,我们发现,与诸如 SSD 或 YOLO 等单次检测方法相比,诸如 Faster R-CNN 之类的区域提议方法可带来更高的准确率,但速度却更低。 同样,对于人体姿势估计,自下而上的方法与自下而上的方法相比,具有较高的准确率,但速度较低。 自上而下的方法分别为每个由人组成的边界框提供图像。 自下而上的方法提供了由一个人的多个边界框组成的整个图像,从而产生了一个较小分辨率的人的图像。
在 2019 年,OpenPose 的作者以及其他一些人(Gines Hidalgo,Yaadhav Raaj,Haroon Idrees,Donglai Xiang,Hanbyul Joo,Tomas Simon1 和 Yaser Sheikh)提高了 OpenPose 的准确率和检测时间。 HTG0]单网络全身姿势估计。 您可以在这个页面上找到本文。
主要功能如下:
- 不需要重复进行手和脸姿势检测的网络,因此与 OpenPose 相比,它的速度更快。 多任务学习(MTL)用于从四个不同任务中训练单个全身估计模型:身体,面部,手和脚检测。
- 通过连接面部,手和脚的置信度图可以增强关键点置信度图。 使用这种方法,所有关键点都在同一模型架构下定义。
- 网络架构的输入分辨率和卷积层数增加了,以提高整体精度。
- 对于其中只有一个人的图像,检测时间输出比 OpenPose 快 10%。
了解 OpenPose 代码
CMU 使用 OpenPose 模型,而 OpenCV 在其新的深度神经网络(DNN)框架中集成了经过预训练的 OpenPose 模型。 可以从下面的 GitHub 页面下载整个代码块。 该模型使用 TensorFlow 示例,而不是 OpenPose 作者最初使用的 Caffe 模型,可以在这个页面中找到。
可以使用以下命令在终端中执行 OpenCV 的 OpenPose 代码:
python openpose.py --input image.jpg
要开始使用 PC 的网络摄像头,只需在终端中键入以下内容:
python openpose.py
下图显示了针对足球运动员图像的 OpenPose 实现:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6mrHhLrx-1681784662628)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/512124c8-371f-4a6a-aa7f-d6197ff36961.png)]
该算法容易受到背景图像的影响,如以下棒球运动员的图像所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hji8c2vJ-1681784662628)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/d4e4d303-353f-46ae-94b9-6d6e1c91b18b.png)]
去除背景后,该算法的预测非常好。
让我们来看一下代码的主要功能。 我们将定义关键点,然后构建预测模型:
- 该模型输入 18 个身体部位和姿势对,如下所示:
BODY_PARTS = { "Nose": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,"LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9,"RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "REye": 14,"LEye": 15, "REar": 16, "LEar": 17, "Background": 18 }
POSE_PAIRS = [ ["Neck", "RShoulder"], ["Neck", "LShoulder"], ["RShoulder", "RElbow"],["RElbow", "RWrist"], ["LShoulder", "LElbow"], ["LElbow", "LWrist"],["Neck", "RHip"], ["RHip", "RKnee"], ["RKnee", "RAnkle"], ["Neck", "LHip"],["LHip", "LKnee"], ["LKnee", "LAnkle"], ["Neck", "Nose"], ["Nose", "REye"],["REye", "REar"], ["Nose", "LEye"], ["LEye", "LEar"] ]
- 接下来,使用以下代码通过 TensorFlow 实现 OpenPose:
net = cv.dnn.readNetFromTensorflow("graph_opt.pb")
使用tf-pose-estimation
在 TensorFlow 中实现 OpenPose。 TensorFlow/model/graph
的实际 GitHub 页面可在这个页面中找到。 请注意,可以在这个页面中找到 MobileNetV1 的描述。
- 接下来,使用
cv.dnn.blobFromImage
对图像进行预处理(执行减法和缩放):
net.setInput(cv.dnn.blobFromImage(frame, 1.0, (inWidth, inHeight), (127.5, 127.5, 127.5), swapRB=True, crop=False))
- 接下来,我们使用
out = net.forward()
预测模型的输出,并获得 MobileNetV1 输出的前 19 个元素:
out = out[:, :19, :, :] .
- 以下代码计算热图,使用 OpenCV 的
minMaxLoc
函数查找点值,并在其置信度高于阈值时添加点。 热图是用颜色表示的数据图:
for i in range(len(BODY_PARTS)):
# Slice heatmap of corresponding body's part.
heatMap = out[0, i, :, :]
# Originally, we try to find all the local maximums. To simplify a sample
# we just find a global one. However only a single pose at the same time
# could be detected this way.
_, conf, _, point = cv.minMaxLoc(heatMap)
x = (frameWidth * point[0]) / out.shape[3]
y = (frameHeight * point[1]) / out.shape[2]
# Add a point if it's confidence is higher than threshold.
points.append((int(x), int(y)) if conf > args.thr else None)
- 以下代码块在原始图像中使用
cv.line
和cv.ellipse
显示关键点:
for pair in POSE_PAIRS:
partFrom = pair[0]
partTo = pair[1]
assert(partFrom in BODY_PARTS)
assert(partTo in BODY_PARTS)
idFrom = BODY_PARTS[partFrom]
idTo = BODY_PARTS[partTo]
if points[idFrom] and points[idTo]:
cv.line(frame, points[idFrom], points[idTo], (0, 255, 0), 3)
cv.ellipse(frame, points[idFrom], (3, 3), 0, 0, 360, (0, 0, 255), cv.FILLED)
cv.ellipse(frame, points[idTo], (3, 3), 0, 0, 360, (0, 0, 255), cv.FILLED)
到目前为止,我们已经使用 OpenPose 通过自下而上的方法来确定多个身体姿势。 在下一节中,我们将使用堆叠的沙漏方法,该方法同时使用了自上而下和自下而上的方法。
人体姿势估计 – 栈式沙漏模型
栈式沙漏模型是由 Alejandro Newell,Kaiyu Yang 和 Jia Deng 于 2016 年在他们的论文“用于人体姿势估计的栈式沙漏网络”中开发的。 可以在这个页面中找到该模型的详细信息。
下图说明了该模型的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pzIXJtXB-1681784662629)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/7fc3ae51-e449-4258-864b-070ab283effc.png)]
该模型的主要功能如下:
- 通过将多个沙漏堆叠在一起,可在所有刻度上重复进行自下而上和自上而下的处理。 该方法导致能够验证整个图像的初始估计和特征。
- 该网络使用多个卷积和一个最大池化层,这导致最终分辨率较低,然后再进行上采样以提高分辨率。
- 在每个最大池化步骤中,平行于主网络添加其他卷积层。
- 输出结果将产生热图,表示每个像素出现关节的概率。
- 该架构充分利用了残差模型。 每个残差都有三层:
1 x 1 Conv2D
,可将尺寸从 256 减少到 128 通道3 x 3 Conv2D
的 128 个通道1 x 1 Conv2D
,可将尺寸从 128 个通道增加到 256 个通道- 该架构从
7 x 7
卷积开始,跨步为 2,将输入图像从7 x 7
带到64 x 64
,从而可以有效地使用 GPU 内存。 - 跨度为 2 的最大
2 x 2
合并用于对图像进行下采样。 在执行每个最大池化之前和之后,将残余块添加,然后在上采样到原始大小后再添加回主块。 - 最后的标题块由两个
1 x 1 Conv2D
组成。 - 表现最佳的是将八个沙漏模块堆叠在一起。 每个沙漏模块在每个分辨率下都有一个残差模块。
- 该模型大约需要进行 40,000 次迭代,以达到 70% 以上的精度。
- 训练过程需要 FLIC 约 5,000 张图像(用于训练的 4,000 张和用于测试的 1,000 张)和用于 MPII 的 40,000 张带标注的样本(用于训练的 28,000 张和用于测试的 12,000 张)。 FLIC 和 MPII 是两个姿势估计数据库。 FLIC 由从胶片中获取的 5003 张图像(用于训练的 3987 张图像和用于测试的 1,016 张图像)组成,而 MPII 由 40,000 个带标注的样本(用于训练的 28,000 张图像和用于测试的 12,000 张)组成。
- 该网络在 Torch 7 上进行了训练,学习率为
2.5e-4
。 在 12 GB 的 NVIDIA Titan X GPU 上进行训练大约需要 3 天。
了解沙漏模型
沙漏模型在 MPII 人类姿态数据集中的所有关节上都达到了最先进的结果,但这是以占用资源密集型网络带宽为代价的。 这是由于每层通道数量众多而导致训练困难。 张峰,朱夏田和 Mao 在题为“快速人体姿态估计”的论文中,将 FastPose 蒸馏(FPD)引入 CVPR 2019。 与沙漏模型相比,FPD 可以实现更快,更经济的模型推断,同时达到相同的模型表现。 主要功能如下:
- 四个沙漏(而不是八个)可以预测 95% 的模型准确率。
- 从 256 个通道下降到 128 个通道只会导致精度降低 1%。
- 首先,在大型沙漏模型(也称为教师姿势模型)上进行训练。 然后,在教师姿势模型的帮助下训练目标学生模型(四个沙漏,128 个通道)。 定义了蒸馏损失函数,以从教师模型中提取知识并将其传递给学生模型。
- 姿势蒸馏损失函数如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wosY1zwT-1681784662629)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/d44ab73e-308f-4e9b-915c-6c0299867377.png)]
在这里,K
是关节总数,L[pd]
是 FPD 的预测关节置信度图, m[ks]
是学生模型预测的第k
个关节的置信度图,而m[kt]
是教师模型预测的第k
个关节。
- 总体损失函数如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUPHtwtJ-1681784662629)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/12c75f63-6358-4566-9007-1f3bcfbf9dec.png)]
此处, L[fpd]
是整体 FPD 损失函数,L[gt]
是用于真实情况标注的置信度图,而M
是权重函数。
- 使用前面描述的损失函数分别训练教师模型和目标模型。
可在这个页面中找到该模型的 Keras 实现。
请注意,下一部分的目的是详细解释沙漏网络的代码。 这是一个复杂的神经网络模型,其想法是,一旦掌握了这些代码,您就应该能够自己构建一个非常复杂的神经网络模型。 我们不会在前面的 GitHub 页面上详细说明如何运行代码。
在下一部分中,我们将描述模型的架构并进行详细说明。
编码沙漏模型
下图显示了沙漏模型的编码块:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9CZrXazN-1681784662630)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/8e1b3ef1-f05d-4128-99fc-3d682e50f51c.png)]
让我们花一点时间来理解前面的图,因为我们将在以下部分中对其进行编码:
- 前模块将图像作为输入和通道数(每层的第三个尺寸,前两个尺寸是宽度和高度)。
- 图像穿过前模块的不同层,最后一个模块连接到左半块。
- 左半块具有四个瓶颈回旋块-
f1
,f2
,f4
和f8
,每个块分别具有 1、1/2、1/4 和 1/8 的分辨率。 如果查看架构图,就在堆叠的沙漏感应下,这应该很清楚。 - 每个块的最后一层–
f1
,f2
,f4
和f8
–创建一个对应的特征映射,即lf1
,lf2
,lf4
和lf8
。 - 特征映射
lf1
,lf2
,lf4
和lf8
连接到右半块。 该块的输出为rf1
。 - 底部层也从左半块连接到
lf8
特征映射。 - 头部快连接到
rf1
。 总共有两个头部快。 每个使用1 x 1
卷积。
让我们看一下不同的代码块。
argparse
包
Python 命令行参数(通过终端输入)允许程序通过parser.add_argument
命令获取有关神经网络操作的不同指令。 可以从argparse
函数包中导入。
下图显示了 16 种不同的类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uP4EvFCu-1681784662630)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/96a6b1d6-f6f7-4b80-8190-2f2d3a00c181.png)]
上图使用的代码块如下:
0 - r ankle, 1 - r knee, 2 - r hip, 3 - l hip, 4 - l knee, 5 - l ankle, 6 - pelvis, 7 - thorax, 8 - upper neck, 9 - head top, 10 - r wrist, 11 - r elbow, 12 - r shoulder, 13 - l shoulder, 14 - l elbow, 15 - l wrist
以下代码导入argparse
模块,TensorFlow 和 HourglassNet 模型。 它有两种类型的用户可选模型:用于小型网络的 128 个通道和用于大型网络的 256 个通道:
import argparse
import os
import tensorflow as tf
from keras import backend as k
from hourglass import HourglassNet
parser.add_argument("--resume", default=False, type=bool, help="resume training or not")
parser.add_argument("--resume_model", help="start point to retrain")
parser.add_argument("--resume_model_json", help="model json")
parser.add_argument("--init_epoch", type=int, help="epoch to resume")
parser.add_argument("--tiny", default=False, type=bool, help="tiny network for speed, inres=[192x128], channel=128")
args = parser.parse_args()
if args.tiny:
xnet = HourglassNet(num_classes=16, num_stacks=args.num_stack, num_channels=128, inres=(192, 192),outres=(48, 48))
else:
xnet = HourglassNet(num_classes=16, num_stacks=args.num_stack, num_channels=256, inres=(256, 256),outres=(64, 64))
if args.resume:
xnet.resume_train(batch_size=args.batch_size, model_json=args.resume_model_json,model_weights=args.resume_model,init_epoch=args.init_epoch, epochs=args.epochs)
else:
xnet.build_model(mobile=args.mobile, show=True)
xnet.train(epochs=args.epochs, model_path=args.model_path, batch_size=args.batch_size)
训练沙漏网络
沙漏网络已被描述。 在本节中,我们将解释训练网络背后的代码。
如果您想训练自己的沙漏网络,请按照这个页面上的说明进行操作。
训练沙漏网络的代码如下:
def build_model(self, mobile=False, show=False):
if mobile:
self.model = create_hourglass_network(self.num_classes, self.num_stacks, self.num_channels, self.inres, self.outres, bottleneck_mobile)
else:
self.model = create_hourglass_network(self.num_classes, self.num_stacks,self.num_channels, self.inres, self.outres, bottleneck_block)show model summary and layer name
if show:
self.model.summary(def train(self, batch_size, model_path, epochs):
train_dataset = MPIIDataGen("../../data/mpii/mpii_annotations.json", "../../data/mpii/images"
inres=self.inres, outres=self.outres, is_train=True)
#here MPIIDataGen is a data generator function (not shown here) - it takes in json file and the images to preapre data for training similar to how we use image data generator in Chapter6.
train_gen = train_dataset.generator(batch_size, self.num_stacks, sigma=1, is_shuffle=True,rot_flag=True, scale_flag=True, flip_flag=True)
csvlogger = CSVLogger(os.path.join(model_path, "csv_train_" + str(datetime.datetime.now().strftime('%H:%M')) + ".csv"))
modelfile = os.path.join(model_path, 'weights_{epoch:02d}_{loss:.2f}.hdf5')
checkpoint = EvalCallBack(model_path, self.inres, self.outres)
xcallbacks = [csvlogger, checkpoint]
self.model.fit_generator(generatepochs=epochs, callbacks=xcallbacks)
前面的代码是如何设置神经网络进行训练的典型示例。 我们在“第 6 章”,“使用迁移学习的视觉搜索”中对此进行了详细介绍。 主要函数如下:
create_hourglass_network
是主要模型。train_dataset
使用 MPIIDatagen,这是用于输入数据的外部模块。train_gen
输入train_dataset
并放大图像。- 它包含回调和检查点,因此我们可以在训练过程中了解模型的内部状态。
model.fit_generator
开始训练过程。
创建沙漏网络
沙漏模型代码的实际实现将在此处说明。 用于此的代码称为create_hourglass_network
。 如前所述,该代码具有以下组件。
前端模块
以下代码描述了前端模块:
def create_front_module(input, num_channels, bottleneck):
_x = Conv2D(64, kernel_size=(7, 7), strides=(2, 2), padding='same', activation='relu', name='front_conv_1x1_x1')(input)
_x = BatchNormalization()(_x)
_x = bottleneck(_x, num_channels // 2, 'front_residual_x1')
_x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(_x)
_x = bottleneck(_x, num_channels // 2, 'front_residual_x2')
_x = bottleneck(_x, num_channels, 'front_residual_x3')
return _x
front_features = create_front_module(input, num_channels, bottleneck)
如前所述,它由一个 Conv2D 块组成,总共有 64 个过滤器,过滤器大小为7 x 7
,跨步为 2。该块的输出为(None, 32, 32,6)
。 接下来的几行贯穿批量规范化,瓶颈和最大池化层。 让我们定义瓶颈块。
左半块
左半块的代码如下:
def create_left_half_blocks(bottom, bottleneck, hglayer, num_channels):
create left half blocks for hourglass module
f1, f2, f4 , f8 : 1, 1/2, 1/4 1/8 resolution
hgname = 'hg' + str(hglayer)
f1 = bottleneck(bottom, num_channels, hgname + '_l1')
_x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(f1)
f2 = bottleneck(_x, num_channels, hgname + '_l2')
_x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(f2)
f4 = bottleneck(_x, num_channels, hgname + '_l4')
_x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(f4)
f8 = bottleneck(_x, num_channels, hgname + '_l8')
return (f1, f2, f4, f8)
前面的代码执行两个特定的操作:
- 它定义分辨率为
1, ½, ¼, and 1/8
的过滤器系数(f1, f2, f4, and f8)
。 - 对于每个过滤器块,它通过使用 2 的过滤器和 2 的跨度应用最大池化来生成最终输出。
接下来,下面的代码迭代从 0 到 2,以每个过滤器分辨率创建三个过滤器块:
for i in range(2):
head_next_stage, head_to_loss = create_left_half_blocks (front_features, num_classes, num_channels, bottleneck, i)
outputs.append(head_to_loss)
从左到右的连接
如果查看“编码沙漏模型部分开头的图像,您会注意到左右两个块由connect_left_to_right
块连接。 用于将左侧块连接到右侧块的代码如下:
def connect_left_to_right(left, right, bottleneck, name, num_channels):
'''
:param left: connect left feature to right feature
:param name: layer name
:return:
'''
_xleft = bottleneck(left, num_channels, name + '_connect')
_xright = UpSampling2D()(right)
add = Add()([_xleft, _xright])
out = bottleneck(add, num_channels, name + '_connect_conv')
return out
注意,每个右块是通过上采样生成的,并被添加到左块以生成最终输出。 在前面的代码中,_xleft
显示左侧块,_xright
显示右侧块,add
函数将两者相加。
右半块
右侧块的代码如下:
def create_right_half_blocks(leftfeatures, bottleneck, hglayer, num_channels):
lf1, lf2, lf4, lf8 = leftfeatures
rf8 = bottom_layer(lf8, bottleneck, hglayer, num_channels)
rf4 = connect_left_to_right(lf4, rf8, bottleneck, 'hg' + str(hglayer) + '_rf4', num_channels)
rf2 = connect_left_to_right(lf2, rf4, bottleneck, 'hg' + str(hglayer) + '_rf2', num_channels)
rf1 = connect_left_to_right(lf1, rf2, bottleneck, 'hg' + str(hglayer) + '_rf1', num_channels)
return rf1
在前面的代码中,lf8, lf4, lf2, and lf1
具有左特征。 相应的右图块的特征rf8, rf4, rf2, and rf1
是通过将左到右瓶颈图块应用到每个左图特征而生成的。 以下代码通过为每个左侧范围迭代 0 到 2 来应用此逻辑:
for i in range(2):
head_next_stage, head_to_loss = create_right_half_blocks (front_features, num_classes, num_channels, bottleneck, i)
outputs.append(head_to_loss)
头部快
头部快的代码如下:
def create_heads(prelayerfeatures, rf1, num_classes, hgid, num_channels):
two head, one head to next stage, one head to intermediate features
head = Conv2D(num_channels, kernel_size=(1, 1), activation='relu', padding='same', name=str(hgid) + '_conv_1x1_x1')(rf1)
head = BatchNormalization()(head)for head as intermediate supervision, use 'linear' as activation.
head_parts = Conv2D(num_classes, kernel_size=(1, 1), activation='linear', padding='same',name=str(hgid) + '_conv_1x1_parts')(head)
use linear activation
head = Conv2D(num_channels, kernel_size=(1, 1), activation='linear', padding='same',name=str(hgid) + '_conv_1x1_x2')(head)
head_m = Conv2D(num_channels, kernel_size=(1, 1), activation='linear', padding='same',name=str(hgid) + '_conv_1x1_x3')(head_parts)
head_next_stage = Add()([head, head_m, prelayerfeatures])
return head_next_stage, head_parts
头部有两个主要块,每个块由一个1 x 1 Conv2D
过滤器组成。 它使用激活层和填充。 作为复习,请参考“人体姿势估计-沙漏模型”部分下显示的沙漏架构图,以了解以下组件之间的联系:
- 进入下一个阶段
- 前往中间特征
以下逻辑将头部快应用于 0 到 2 的每个范围,分别对应于左块和右块:
for i in range(2):
head_next_stage, head_to_loss = create_head_blocks (front_features, num_classes, num_channels, bottleneck, i)
outputs.append(head_to_loss)
训练沙漏
沙漏网络在 FLIC 人体姿势数据集上进行了训练,该数据集包含 5,000 张图像(用于训练的 4,000 和用于测试的 1,000)和具有 40,000 图片(用于训练的 28,000 和用于测试的 12,000)的 MPII 人体姿势数据集。
请注意,在本书中,我们没有使用 MPII 数据集来训练沙漏模型。 提供了有关 MPII 数据集的信息,以解释如何训练沙漏模型进行人体姿势估计。
在大约 20,000 次训练迭代中,所有关节的平均准确率达到大约 70%,最大准确率大约为 80%。
到目前为止,我们已经讨论了 OpenPose 和姿势估计的栈式沙漏方法。 在下一节中,我们将讨论 PoseNet。
人体姿势估计 - PoseNet
TensorFlow 发布了 PoseNet 模型,该模型用于使用浏览器检测人体姿势。 它可以用于单个姿势和多个姿势。
PoseNet 基于 Google 的两篇论文。 一种使用自上而下的方法,而另一种使用自下而上的方法。
自上而下的方法
第一篇论文的标题为《在野外进行精确的多人姿势估计》,由 George Papandreou,Tyler Zhu,Nori Kanazawa,Alexander Toshev,Jonathan Tompson,Chris Bregler 和 Kevin Murphy 撰写。 您可以在这个页面上找到该论文。
这是一种由上而下的两阶段方法:
- 使用带有 ResNet-101 网络主干的 Faster R-CNN 确定边界框坐标(
x, y, w, h
)。 在“第 5 章”,“神经网络架构和模型”中引入了更快的 R-CNN 和 ResNet,但在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN 进行对象检测”中将在实际实现中一起使用它们。这种分类仅针对人类进行。 调整返回的所有边界框,使其具有固定的纵横比,然后将其裁剪为353 x 257
。 - 使用 ResNet-101 估计位于每个边界框内的人的 17 个关键点,用
3 x 17
输出替换最后一层。 已经使用分类和回归相结合的方法来找到人体的每个位置与 17 个关键点位置中的每个位置之间的偏移向量或距离。 每 17 个关键点计算一次距离小于半径的概率,从而得出 17 个热图。 使用 Sigmoid 激活函数训练具有 17 个热图的 ResNet-101 模型。
自下而上的方法
第二篇论文的标题为《PersonLab:使用自下而上的,基于部分的几何嵌入模型的人员姿势估计和实例细分》,由第一篇论文的许多相同作者撰写; 分别是 George Papandreou,Tyler Zhu,Chen-Chieh Chen,Spyros Gidaris,Jonathan Tompson 和 Kevin Murphy。 您可以在这个页面上找到该论文。
在这种无框的,自下而上的方法中,作者使用卷积神经网络检测单个关键点及其相对位移,以将关键点分组为人的姿势实例。 另外,设计了几何嵌入描述符来确定人员分割。 该模型使用 ResNet-101 和 ResNet-152 架构进行训练。
像自顶向下方法一样,定义了一个 32 像素大小的半径,对应于 17 个关键点中的每一个。 然后,如果图像中的空间位置在关键点位置的半径之内,则以热图概率 1 定义 17 个独立的二元分类任务; 否则,将其设置为 0。与自顶向下方法一样,图像位置和关键点之间的距离也称为短距离偏移向量。 因此,存在 17 个这样的偏移向量。 与自顶向下方法一样,热图和偏移向量使用二维 Hough 得分图分组在一起。
在这种方法中,我们有一个与关键点相关联的人,但是当图像中存在多个人的实例时,这不允许我们对每个人的关键点进行分组。 为了解决这个问题,开发了 32 个独立的中距离二维偏移量字段来连接成对的关键点。 除此之外,还开发了一个由单个1 x 1 Conv2D
层组成的简单语义分割模型,该模型可以执行密集逻辑回归并计算每个图像像素至少属于一个人的概率。 语义分段的详细信息在“第 8 章”,《语义分段和神经样式迁移》中进行了描述。
有关预测图像的信息,请参阅以下有关自上而下与自下而上的文章和这个。 这两篇论文都包含大量示例图像。
预测关键点在两种方法之间或多或少是相同的,但是自上而下的方法从绘制边界框开始,而自下而上的方法执行语义分割。
PoseNet 实现
到目前为止,我们已经讨论了 PoseNet 自上而下和自下而上方法背后的理论。 在本节中,我们将使用 PoseNet 识别这些操作。 有关如何实现 PoseNet 模型的详细信息,请参见这里。 查看此链接以了解 PoseNet 的文档。
接下来,我们将进行现场演示。 此实时演示是使用网络摄像头完成的,可以通过在网络浏览器中键入以下链接来启动。
尽管自上而下和自下而上的方法使用 ResNet-101 模型,但 PoseNet 模型使用 MobileNetV1 或 ResNet-50。 下表说明了它们之间的区别:
MobileNet V1 | ResNet 50 | |
---|---|---|
跨步 | 16 | 32 |
输入分辨率 | 宽度:640,高度:480 | 宽度:257,高度:200 |
PoseNet 网站说明了如何调整模型参数。 可以使用以下屏幕快照中显示的参数窗口来调整模型参数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6z3CCZF-1681784662630)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/c4ec18e5-b541-459f-a91d-ec8b5459fcb6.png)]
在前面的屏幕截图中,我们可以通过更改输入图像的分辨率来演示这两种模型,这似乎效果最好。
下图比较了八种不同配置(对于 MobileNetV1 和 ResNet,分辨率为 200 和 500 的上下姿势)的 PoseNet 输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZTuUgXq-1681784662630)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/ad6e3682-bbcd-4f56-87f1-61b8ab1a23f4.png)]
上图显示,当人的手举起时,ResNet 平均比 MobileNetV1 更准确。 当手的位置向下时,表现大致相同。 同样,与 500 分辨率相比,200 分辨率可实现更好的关键点预测。 边界框选项可用,但未显示。 下图显示了用于其他配置的 ResNet 的边界框:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i3dTUlbt-1681784662631)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/53554316-613a-43bd-83ea-c0f0ee3ecbd6.png)]
请注意边界框的大小和位置在不同方向上如何变化。 关键点存储在向量中。 生成的关键点之间的角度可用于预测动作。 上一个图像由三个不同的动作组成–侧向运动,向上和向下运动。 这些动作的关键角度不会重叠,因此预测将是可靠的。
将人体姿势应用于手势识别
到目前为止,我们已经学习了如何在给定的关键点上进行训练以生成人体姿势。 手势识别的过程类似。 请按照以下步骤执行手势识别以进行手部运动:
- 收集不同手的位置的图像 - 上,下,左和右。
- 调整图像大小。
- 此时,您可以用关键点标记图像。 如果为关键点标记图像,则每个图像都必须用相应的关键点表示。
- 将图像及其相应的标签加载到两个不同的数组中。
- 下一步是执行图像分类,类似于我们在“第 6 章”,“使用迁移学习进行视觉搜索”时所做的工作。
- CNN 模型最多可以包含三个
Conv2D
层,一个最大合并层和一个 ReLU 层。 - 对于关键点估计,而不是分类,我们将使用每个关键帧手势位置之间的距离,并选择具有最小距离的手势。
到目前为止,我们已经学习了如何开发用于训练的二维神经网络。 我们开发的网络也可以用于生产。
使用各种方法的动作识别
加速度计测量加速度的x
,y
和z
分量,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1P02cDxo-1681784662631)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/76b02856-dea6-432e-9557-50f717feeaf1.png)]
加速度计的这一特性使其可以放置在可穿戴设备中,例如安装在腕带上的手腕上的手机,智能手表,甚至是鞋子中,以测量加速度的 XYZ 分量。 在本节中,我们将学习如何使用神经网络分析加速度计数据以识别人类活动。 我们将使用 TensorFlow 开发机器学习模型。 这是本书中唯一讨论无图像的原始数据以及如何将其传递到神经网络以开发模型并从中进行推断的章节。
人类活动识别涉及基于加速度计数据对不同类型的活动进行分类。 这里的挑战是关联从不同类型的人体运动生成的加速度计数据,并基于不同的人体运动和活动来区分相似的加速度计轨迹。 例如,当左手移动和右手移动安装到人的腰部时,可能会产生类似的加速度计数据。 这减轻了加速度计数据应与姿势估计或视频图像数据结合的事实。 在本节中,我们将讨论可用于人类活动识别的两种不同工具。
基于加速度计识别动作
此方法涉及以下步骤:
- 处理输入的加速度计数据:加速度计数据对其位置敏感。 例如,如果安装在腰部区域,则与安装在手臂中相比,手部运动不会在加速度计中看到很大的变化。 另外,对于不同的位置,需要收集不同的数据,然后进行组合。
- 准备数据以便可以将其输入到 TensorFlow 中:使用
tf.data.Dataset
加载数据以开发简单,高效的数据管道。tensor_slices
命令从输入中提取一片数据。 - 开发 CNN 模型并对其进行训练:一层或两层密集层,最后具有
flatten
和 Softmax 函数。 - 检查测试数据:对照测试数据验证数据。
请参阅以下 GitHub 页面上的代码,以获取遵循这些步骤的代码示例。
在上一个链接中可以找到两个文件:Chapter9_TF_Accelerometer_activity.ipynb
和sample.csv
。 下载两个文件,并将它们放在同一文件夹下。
sample.csv
文件是一个示例 CSV 文件,其中包含用于六个不同动作的加速度计(x, y, z)
数据:慢跑(0),步行(1),楼上(2),楼下(3) ,坐(4)和站立(5),每个动作都包含 5,000 个数据点。 在您的实际情况下,这些数据值可能会根据放置位置和所使用的加速度计的类型而有所不同。 最好使用相同的加速度计进行训练数据进行推理,以避免推理错误。
接下来,根据索引文件将数据分为两部分:训练和测试。 在这里,我们将评估两个不同的分割 18 和 28,这意味着在一种情况下,如果索引文件小于 18,则数据属于train
文件夹; 否则,它属于test
文件夹。 该模型加载了三个密集(全连接)的层,分辨率为 128。 最终的 softmax 层被 Sigmoid 函数代替。 下图显示了在三种不同情况下模型的迭代:
- Softmax,训练与测试的索引为 18
- Sigmoid 函数,在索引 18 处分割,用于训练与测试
- Softmax,训练与测试的索引为 28:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qjpzUFXY-1681784662631)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/434ae075-6174-4070-9006-4d9a692bf94c.png)]
前面的数据表明,每次迭代大约需要 40 秒,最终精度约为 0.97。 下图以图形方式说明了这一点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kTQd854L-1681784662631)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/ba8fec99-a1e5-4e0e-adf3-5486104af508.png)]
前面的曲线表明,在所研究的三个条件下,训练的精度基本相同。 为了进一步分析这一点,让我们看一下下图中所示的置信度图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrlaLSfn-1681784662632)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/0f9d22e3-ebfa-437f-92e4-11bc984fb1d0.png)]
混淆矩阵指示测试数据与预测数据的比较程度。 在这里,我们可以看到在索引 18 处进行了训练分割的 Softmax 函数比其他站立和步行案例提供了更好的结果。 不出所料,Softmax 与 Sigmoid 激活函数没有导致任何显着差异。 一旦开发了模型,就可以使用模型的预测函数来预测实际测试情况下的数据。
将基于视频的动作与姿势估计相结合
动作识别可以是二维的,也可以是三维的。 二维动作识别方法使用人体的关节信息,以关键点表示。 这些关键点以称为特征映射的向量表示。 另一方面,三维动作识别方法不仅需要特征映射,还需要全身的骨架数据。 可以使用深度传感器(例如 Microsoft Kinect 或 Intel RealSense)获得此数据。 在 2018 年,Diogo C.Luvizon,David Picard 和 Hedi Tabia 介绍了他们的论文 《使用多任务深度学习的 2D/3D 姿势估计和动作识别》。 可以在这里中找到本文的详细信息。
在本文中,作者在一个多任务框架中将基于高级人体关节的姿势信息与低级视觉特征(来自对象识别和特征识别)集成在一起。 该方法能够进行二维和三维动作识别。 使用体积表示将二维姿态图扩展为三维图。
这些技术的组合有助于使动作识别对类似身体的关节运动(如饮用水和打个电话)的抵抗力更强。
使用 4D 方法的动作识别
4D 动作识别意味着体积表示的三维动作是时间的函数。 可以将其视为对动作进行批量跟踪。 全全友和郝江提出了一种新颖的 4D 方法,名为《Action4D:人群和杂物中的在线动作识别》。可以在这个页面中找到本文的详细信息。
该方法使用 4D 表示跟踪人类,并在混乱和拥挤的环境中识别他们的行为。 本文的概念如下:
- 使用多个 RGBD 图像为每个场景创建三维点云。
- 在拥挤场景中的检测得到了创新的跟踪建议的补充,该提议不使用背景减法,这意味着它在拥挤空间中不太容易出错。
- 跟踪过程通过训练 3 维 CNN(具有 3 维卷积,ReLU 和池化层)来使用候选人提案,以将每个候选量分类为人与非人。
- 使用一系列三维体积识别动作,这些三维体积经过一系列三维卷积和池化层(称为 Action4D)。
总结
在本章中,我们了解并实现了三种不同的姿势估计方法-OpenPose,栈式沙漏和 PostNet。 我们学习了如何使用 OpenCV 和 TensorFlow 预测人类关键点。 然后,我们了解了栈式沙漏方法的详细理论和 TensorFlow 实现。 我们向您展示了如何在浏览器中评估人体姿势,以及如何使用网络摄像头实时估计关键点。 然后将人体姿势估计与动作识别模型链接,以演示如何使用两者来提高准确率。 基于加速的代码展示了如何使用 TensorFlow 2.0 加载数据,训练模型和预测动作。
在下一章中,我们将学习如何实现 R-CNN 并将其与其他 CNN 模型(如 ResNet,Inception 和 SSD)结合使用,以提高对象检测的预测,准确率和速度。
十、R-CNN,SSD 和 R-FCN 对象检测
在“第 7 章”,“使用 YOLO 进行对象检测”中,我们了解了 YOLO 对象检测,然后在前两章中,我们了解了动作识别和图像修补。 本章通过为数据摄取和训练流水线以及模型开发奠定坚实的基础,标志着端到端(E2E)对象检测框架的开始。 在这里,我们将深入了解各种对象检测模型,例如 R-CNN,单发检测器(SSD),基于区域的全卷积网络(R-FCN)和 Mask R-CNN,并使用 Google Cloud 和 Google Colab 笔记本执行动手练习。 我们还将针对如何训练自己的自定义图像以使用 TensorFlow 对象检测 API 开发对象检测模型进行详细的练习。 我们将在本章结束时对各种对象跟踪方法进行深入概述,并使用 Google Colab 笔记本进行动手练习。
本章分为八个小节:
- SSD 概述
- R-FCN 概述
- TensorFlow 对象检测 API 概述
- 在 Google Cloud 上使用 TensorFlow 检测对象
- 使用 TensorFlow Hub 检测对象
- 使用 TensorFlow 和 Google Colab 训练自定义对象检测器
- Mask R-CNN 概述和 Google Colab 演示
- 开发对象跟踪器模型来补充对象检测器
SSD 概述
SSD 是一种非常快速的对象检测器,非常适合部署在移动设备和边缘设备上以进行实时预测。 在本章中,我们将学习如何使用 SSD 开发模型,在下一章中,我们将评估在边缘设备上部署时的表现。 但是在详细介绍 SSD 之前,我们将快速了解到目前为止我们在本书中了解的其他对象检测器模型。
我们在“第 5 章”,“神经网络架构和模型”中了解到,Faster R-CNN 包含 21,500 个区域提议(60 x 40
滑动窗口和 9 个锚定框),这些建议被扭曲为 2K 固定层。 这些 2K 层被馈送到全连接层和包围盒回归器,以检测图像中的包围盒。 9 个锚框来自 3 个比例尺,框面积分别为128^2
,256^2
,512^2
和三个长宽比:1:1、1:2 和 2:1。
9 个锚点框的说明如下:
128x128:1:1; 128x128:1:2; 128x128:2:1
256x256:1:1; 256x256:1:2; 256x256:2:1
512x512:1:1; 512x512:1:2; 512x512:2:1
在“第 7 章”,“使用 YOLO 进行对象检测”中,我们了解到 YOLO 使用单个 CNN,该 CNN 同时预测整个图像中对象的多个边界框。 YOLO v3 检测分为三层。 YOLO v3 使用 9 个锚点:(10, 13)
,(16, 30)
,(33, 23)
,(30, 61)
,(62, 45)
,(59, 119)
,(116, 90)
,(156, 198)
,(373, 326)
。 此外,YOLO v3 使用 9 个掩码,这些掩码链接到锚点,如下所述:
- 第一层:遮罩:6、7、8; 对应的锚点:
(116, 90)
,(156, 198)
,(373, 326)
- 第二层:遮罩:3、4、5; 对应的锚点:
(30, 61)
,(62, 45)
,(59, 119)
- 第三层:遮罩:0、1、2; 对应的锚点:
(10, 13)
,(16, 30)
,(33, 23)
SSD 于 2016 年由 Liu Wei,Dragomir Anguelov,Dumitru Erhan,Christian Szegedy,Scott Reed,傅成扬和 Alexander C.Berg 在题为《SSD:单发多框检测器》提出。
它的速度比 Faster R-CNN 快,但其准确率与 YOLO 相比。 改进来自消除区域提议并将小型卷积过滤器应用于特征映射,以预测不同比例的多层。
SSD 的主要功能概述如下:
- SSD 原始论文使用 VGG16 作为基础网络提取特征层,但也可以考虑使用其他网络,例如 Inception 和 ResNet。
- SSD 在基础网络之上添加了另外六个特征层,由
conv4_3
,conv7
(fc7
),conv8_2
,conv9_2
,conv10_2
和conv11_2
组成,用于对象检测。 - 一组默认框与每个特征映射单元相关联,因此默认框位置相对于特征映射单元是固定的。 每个默认框都会预测
c
类中每个类别的得分以及相对于地面真实情况的四个偏移,从而产生(c + 4)k
过滤器。 这些过滤器应用于特征映射(大小为m x n
),产生(c + 4)kmn
输出。 下表说明了这一点。 SSD 的独特之处在于默认框适用于不同分辨率的多个特征映射:
层名称 | 检测 | 过滤器输出 |
---|---|---|
Conv4_3 | 38 x 38 x 4 = 5776 | 3 x 3 x 4 x (c + 4) |
Conv7 | 19 x 19 x 6 = 2166 | 3 x 3 x 6 x (c + 4) |
Conv8_2 | 10 x 10 x 6 = 600 | 3 x 3 x 6 x (c + 4) |
Conv9_2 | 5 x 5 x 6 = 150 | 3 x 3 x 6 x (c + 4) |
Conv10_2 | 3 x 3 x 4 = 36 | 3 x 3 x 4 x (c + 4) |
Conv11_2 | 4 | |
总 | 8732 |
- 默认框的设计是使用比例因子和宽高比创建的,因此特定尺寸(基于真实情况预测)的特征映射与对象的特定比例相匹配。
- 比例范围可以从
smin(0.2)
到smax(0.95)
线性变化,而纵横比(ar
)可以取五个值(1
,2
,0.5
,3.0
和0.33
) ,其中k
在1
和m
之间变化。 - 对于长宽比
1
,添加了一个附加的默认框。 因此,每个特征映射位置最多有六个默认框。 - 默认框中心的坐标为
((i+0.5)/|fk|, (j+0.5)/|fk|)
,其中|fk|
是kth
正方形特征映射的大小,i
和j
的值从0
到|fk|
不等。 对六个默认框的每个重复此操作。 - SSD 通过将给定比例和宽高比的默认框与地面真实物体的默认框匹配,并消除不匹配的框,从而预测各种物体的大小和形状。 默认框与地面真值对象的匹配是通过 Jaccard 重叠(也称为交并比与 IOU)完成的,这在第 7 章,“使用 YOLO 进行对象检测”中。 例如,如果图像由
human
和bus
组成并且都具有不同的宽高比和比例,则 SSD 显然可以识别两者。 问题出现在两个类别彼此接近且纵横比相同时,我们将在后面看到。 - 使用 R-CNN,区域提议网络执行筛选以限制被视为 2K 的样本数量。 另一方面,SSD 没有区域提议,因此它会生成大量的边界框(如我们先前所知,为 8,732 个),其中许多都是负面示例。 SSD 拒绝了额外的负面示例,它使用硬性负面挖掘来使正面与负面之间的平衡保持至多 3:1。 硬否定挖掘是一种用于使用置信度损失进行排序以便保留最高值的技术。
- SSD 使用非最大抑制来选择给定类别具有最高置信度的单个边界框。 非最大抑制的概念在“第 7 章”,“使用 YOLO 进行对象检测”中。 非最大抑制算法以最高的概率选择对象类别,并丢弃 IOU 大于
0.5
的所有边界框。 - SSD 还通过获取假阴性图像作为训练期间的输入来使用硬性阴性挖掘。 SSD 保持负数与正数之比为 3:1。
- 为了进行训练,使用以下参数:
300x300
或512x512
图像大小,10^(-3)
的学习率为 40,000 次迭代,10^(-4)
至10^(-5)
的学习率为随后的 10,000 次迭代,衰减率为0.0005
和0.9
的势头。
R-FCN 概述
R-FCN 比 R-CNN 与 SSD 更相似。 R-FCN 由主要由 Microsoft Research 组成的团队于 2016 年开发,该团队由戴继峰,李毅,何凯明和孙健组成,题为《R-FCN:通过基于区域的全卷积网络进行对象检测》。 您可以在这个页面上找到该论文的链接。
R-FCN 也基于区域提议。 与 R-CNN 的主要区别在于,R-FCN 一直等到最后一层,然后应用选择性池提取特征以进行预测,而不是从 2K 区域提议网络开始。 在本章中,我们将使用 R-FCN 训练自定义模型,并将最终结果与其他模型进行比较。 下图描述了 R-FCN 的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zw2owfJf-1681784662632)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/d692d9d9-8340-4d58-a219-8002b8b93391.png)]
在上图中,汽车的图像通过 ResNet-101 生成了特征映射。 请注意,我们在“第 4 章”,“基于图像的深度学习”中使用,它介绍了如何可视化卷积神经网络(CNN)及其特征映射。 这种技术本质上是相同的。 然后,我们在特征映射内获取k x k
核(在此图像中,k = 3
),并将其在图像上滑动以创建k^2(C+1)
得分图。 如果得分图包含一个对象,则我们投票yes
,否则,我们投票no
。 展平不同区域之间的投票以创建 softmax 层,该层被映射到对象类别以进行检测。
R-FCN 的主要功能如下所述:
- 类似于 R-CNN,在整个图像上计算出全卷积区域提议网络(RPN)。
- R-FCN 并未像 R-CNN 那样将 2K 扭曲区域发送到全连接层,而是在预测之前使用了特征的最后卷积层。
- 减去平均池化层和全连接层的 ResNet-101 用于特征提取。 因此,仅卷积层用于计算特征映射。 ResNet-101 中的最后一个卷积块具有 2,048 个维,将其传递到 1,024 维的
1×1
卷积层以进行维降。 - 1,024 个卷积层产生一个
k^2
得分图,它对应于k^2(C + 1)
通道输出,带有C
对象类别加上背景。 - 应用选择性合并从
k^2
得分图中仅从得分图中提取响应。 - 这种从最后一层提取特征的方法可最大程度地减少计算量,因此 R-FCN 甚至比 Faster R-CNN 更快。
- 对于边界框回归,在
4k^2
卷积层上使用平均池,从而为每个关注区域层生成4k^2
维向量。 来自每个k^2
层的4k^2
向量被聚合为四维向量,该向量将边界框的位置和几何形状表征为x
,y
,宽度和高度 。 - 为了进行训练,使用以下参数:衰减率为
0.0005
,动量为0.9
,将图像调整为高度为600
像素,20,000 批量的学习率为0.001
和0.0001
10,000 个批量。
TensorFlow 对象检测 API 概述
可以在这里找到 TensorFlow 对象检测 API。 在撰写本书时,TensorFlow 对象检测 API 仅适用于 TensorFlow 版本 1.x。 在终端中下载 TensorFlow 1.x 时,它将models/research/object detection
目录安装到您的 PC。 如果您的 PC 上装有 TensorFlow 2.0,则可以从 GitHub 下载研究目录。
TensorFlow 对象检测 API 具有预先训练的模型,您可以使用网络摄像头对其进行检测以及有关自定义图片的示例训练。 浏览前两个链接,然后自己尝试,然后返回下一部分。
在本章中,我们将使用 TensorFlow 对象检测器执行以下任务:
- 使用 Google Cloud 和 Coco 数据集上的预训练模型进行对象检测
- 使用 TensorFlow Hub 和 Coco 数据集上的预训练模型进行对象检测
- 使用迁移学习训练 Google Colab 中的自定义对象检测器
在所有这些示例中,我们将使用汉堡和薯条数据集进行检测和预测。
在 Google Cloud 上使用 TensorFlow 检测对象
以下说明介绍了如何使用 Google Cloud 上的 TensorFlow 对象检测 API 来检测对象。 为此,您必须具有 Gmail 和 Google Cloud 帐户。 提交信用卡信息后,根据地区的不同,Google Cloud 可以在有限的时间内免费提供访问权限。 此免费访问权限应涵盖此处列出的练习。 请按照以下步骤在 Google Cloud Console 中创建虚拟机(VM)实例。 需要 VM 来运行 TensorFlow 对象检测 API 并进行推断:
- 登录到您的 Gmail 帐户,然后转到 h ttps://cloud.google.com/solutions/creating-object-detection-application-tensorflow 。
- 创建一个项目,如下面的屏幕快照所示。 在这里,
R-CNN-trainingpack
是我的项目的名称。 您的项目名称可能会有所不同。 - 按照[启动 VM 实例]下的 10 条说明进行操作-在“步骤 12”之后的屏幕快照中也进行了说明。
- 在 Google Cloud Console 中,导航到“VM 实例”页面。
- 点击顶部的“创建实例”。 它应该带您到另一个页面,您必须在其中输入实例名称。
- 以小写字母输入实例的名称。 请注意,实例名称与项目名称不同。
- 单击“计算机类型”,然后选择
n1-standard-8
(8vCPU,30 GB 内存)。 - 单击“自定义”,然后调整水平条以将“计算机类型”设置为 8 个 vCPU,将“内存”设置为 8GB,如以下屏幕截图所示。
- 选择“防火墙”下的“允许 HTTP 通信”。
- 在防火墙下,您将看到管理,安全性,磁盘,网络,唯一租赁链接,如屏幕快照所示,该屏幕快照说明了创建 VM 实例的步骤。 单击它,然后单击“网络”选项卡。
- 在“网络”选项卡中,选择“网络接口”部分。 接下来,在“网络接口”部分中,我们将通过在“外部 IP”下拉列表中分配一个新 IP 地址来分配静态 IP 地址。 给它起一个名字(例如
staticip
),然后单击“保留”。 - 完成所有这些步骤之后,请检查并确保已按照说明填充所有内容,然后单击“创建”(如以下屏幕截图所示)以创建 VM 实例。
以下屏幕快照显示了在 Google 云平台中创建名为R-CNN-trainingpack
的项目:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zcwuFAkF-1681784662632)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/5a02623c-bc4c-4a7b-ab9c-1b9aca54f7f0.png)]
创建项目是第一步,然后我们将在项目中创建一个实例,如下面的屏幕快照所示。 此屏幕快照说明了我们刚刚描述的 VM 实例创建的步骤:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kvcUZ4Qp-1681784662632)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/84c13cc1-e50d-4291-b431-4a87579ab3d6.png)]
然后,按照以下说明在测试图像上创建对象检测推断:
- 接下来,我们将使用安全套接字外壳(SSH)客户端通过互联网安全地访问实例。 您将需要输入用户名和密码。 将用户名设置为
username
,将密码设置为passw0rd
; 请记住,它不是o
而是0
,如零。 - 使用这个页面上描述的说明,安装 TensorFlow 对象检测 API 库和必备包。
正确遵循上述说明并上传图像后,您将获得如下所示的输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-74VTutUF-1681784662633)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/9b7712b3-064e-4911-8ff3-7720963edf18.png)]
在此屏幕截图中,检测到了汉堡,酒杯和桌子,但未检测到炸薯条。 在下一节中,我们将看到为什么会这样,然后我们将训练自己的神经网络来检测这两者。
使用 TensorFlow Hub 检测对象
在此示例中,我们将从tfhub
导入 TensorFlow 库,并使用它来检测对象。 TensorFlow Hub 是一个库,其中的代码可用并且可以用于计算机视觉应用。 该代码是从 TensorFlow Hub 中提取的,但图像是在本地插入的,而不是云端。
可以在这个页面中找到用于此练习的修改后的代码。
在这里,我们通过导入tensorflow_hub
和six.moves
安装 TensorFlow 库。 six.moves
是一个 Python 模块,用于提供 Python 2 和 Python 3 之间的通用包。它显示图像并在图像上绘制边框。 在通过检测器之前,图像将转换为数组。 检测器是直接从集线器加载的模块,该模块在后台执行所有神经网络处理。 以下显示了在两种不同模型的tfhub
上运行示例图像时的输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IzVFBOx8-1681784662633)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/1dfd202a-1189-4b8d-99d8-8ce5d20d32e9.png)]
如您所见,具有 Inception 和 ResNet 作为特征提取器的 R-CNN 可以正确预测汉堡包和炸薯条以及许多其他对象。 具有 MobileNet 模型的 SSD 可以检测到汉堡,但无法检测到薯条-将其分类为snacks
类别。 当我们训练自己的对象检测器并开发自己的模型并基于此进行推论时,我们将在下一部分中了解更多信息。
使用 TensorFlow 和 Google Colab 训练自定义对象检测器
在本练习中,我们将使用 TensorFlow 对象检测 API 使用四种不同的模型训练自定义对象检测器。 Google Colab 是在 Google 服务器上运行的 VM,因此 TensorFlow 的所有包都得到了适当的维护和更新:
序号 | 模型 | 特征提取器 |
---|---|---|
1 | 更快的 R-CNN | Inception |
2 | SSD | MobileNet |
3 | SSD | Inception |
4 | R-FCN | ResNet-101 |
请注意,在撰写本书时,TensorFlow 对象检测 API 尚未迁移到 TensorFlow 2.x,因此请在 Google Colab 默认版本 TensorFlow 1.x 上运行此示例。 您可以通过键入%tensorflow_version 2.x
在 Google Colab 中安装 TensorFlow 2.x,但是对象检测 API 会导致错误。 该演示练习安装了 TenorFlow 1.14 版和 numpy 1.16 版。
我们将在此练习中使用迁移学习,首先从在 Coco 数据集上训练的预训练模型开始,然后在通过我们自己的数据集进行训练的基础上建立迁移学习。 TensorFlow 已经在 ModelZoo GitHub 站点中存储了预训练的模型,该站点可从这里获取。 这些模型主要是具有不同特征提取器的 R-CNN,SSD 和 R-FCN。 相应的配置文件可以在这个页面中找到。
可可数据集具有以下类别:
Person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, traffic light, fire hydrant, stop sign, parking meter, bench, bird, cat, dog, horse, sheep, cow, elephant, bear, zebra, giraffe, backpack, umbrella, handbag, tie, suitcase, frisbee, skis, snowboard, sports, ball, kite, baseball, bat, baseball, glove, skateboard, surfboard, tennis, racket, bottle, wine, glass, cup, fork, knife, spoon, bowl, banana, apple, sandwich, orange, broccoli, carrot, hot dog, pizza, donut, cake, chair, couch, potted plant, bed, dining table, toilet, tv, laptop, mouse, remote, keyboard, cell phone, microwave oven, toaster, sink, refrigerator, book, clock, vase, scissors, teddy bear, hair drier, toothbrush
如您所见,Coco 数据集没有burger
或French fries
作为类别。 形状接近这些的项目是sandwich
,donut
和carrot
。 因此,我们将获得模型权重,并在我们自己的数据集上使用迁移学习来开发检测器。 GitHub 网站上的 Jupyter 笔记本具有执行 E2E 训练工作的 Python 代码。
训练工作使用 TensorFlow 对象检测 API,该 API 在执行期间调用各种 Python .py
文件。 经过大量练习,我们发现,最好是使用 Google Colab 笔记本而不是您自己的 PC 来运行此工作。 这是因为许多库都是用 TensorFlow 1.x 版本编写的,需要进行转换才能在 TensorFlow 2.0 中工作。 此处显示了在本地 PC 上使用 Anaconda 运行作业时发生的一些错误示例:
module 'keras.backend' has no attribute 'image_dim_ordering' self.dim_ordering = K.common.image_dim_ordering() module 'tensorflow_core._api.v2.image' has no attribute 'resize_images'
rs = tf.image.resize(img[:, y:y+h, x:x+w, :], (self.pool_size, self.pool_size))
61 outputs.append(rs)
62
AttributeError: module 'tensorflow_core._api.v2.image' has no attribute 'resize_images'
当作业在 Colab 上的 TensorFlow 中运行时,模块之间的依存关系配置良好。 因此,不会花费很多时间解决许多简单的错误,您可以将时间花在训练开发上,而不是修正错误以开始训练。
在以下部分中,将提供逐步指南,以建立训练组合。 可以在这个页面中找到代码的详细信息。
将图像收集并格式化为.jpg
文件
本节介绍如何处理图像,使其具有相同的格式和大小。 步骤在这里列出:
- 了解您要使用的类数量,并确保图像具有相等的类分布。 这意味着,例如,如果我们要使用两个类别(
burger
和french fries
),则图像应包含大约三分之一的汉堡包,三分之一的薯条,以及三分之一两者的混合。 仅具有汉堡的图像和炸薯条的图像而不包含组合的图像是不好的。 - 确保图像包含不同的方向。 对于具有均匀形状的图像(例如汉堡的圆形)或具有不均匀形状(例如炸薯条)的图像,方向无关紧要,但是对于特定形状(例如汽车,钢笔和船形),不同的方向至关重要。
- 将所有图像转换为
.jpg
格式。 - 调整所有图像的大小以供神经网络快速处理。 在此示例中,考虑
416x416
图像大小。 在 Linux 中,您可以使用 ImageMagick 批量调整图像大小。 - 转换
file.jpg
-将其调整为416x416
图像尺寸file.jpg
。 - 将图像重命名为
classname_00x.jpg
格式。
例如,dec2f2eedda8e9.jpg
应该转换为burger_001.jpg
。 将所有图像保存在一个文件夹中。 由于我们的图像包含一个汉堡,炸薯条和一个组合,并且我们的文件总数为 100,因此对于图像文件名,请创建burger_001 …burger_030.jpg
,fries_031 …fries_060.jpg
和comb_061 …comb_100.jpg
三个类。
标注图像来创建.xml
文件
在本节中,我们将描述如何创建标注文件。 每个图像文件对应一个标注文件。 标注文件通常为.xml
格式。 此处描述了创建标注文件的步骤:
- 在此步骤中,使用
labelImg
创建标注文件。 此步骤已经在“第 7 章”,“使用 YOLO 的对象检测”中进行了讨论,但此处再次重复。 使用终端命令pip install labelImg
下载labelImg
。 - 下载后,只需在终端中键入
labelImg
即可打开。 - 定义源(
.jpg
文件)和目标(.xml
文件)目录。 - 选择每个图像并在其周围绘制一个矩形。 定义类名称并保存。
- 如果给定图像中有多个类别,则在每个图像周围绘制一个矩形,并为其分配相关的类别名称。
通常,人们会犯这样的错误:仅在一个类上绘制一个矩形,然后跳过另一个类。 这将导致在推理过程中仅检测到一个类别。
此屏幕快照显示了我们如何在一张图像中标记两个类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s03Lo1HH-1681784662633)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/850fcd9e-026d-4f49-b0bc-3497becfd97b.png)]
这显示了两个类别-burger
和fries
-以及如何使用labelImg
在它们周围绘制边框。 labelImg
的输出是.xml
文件,该文件存储在单独的文件夹中。
每个.xml
文件中都有相应的.jpg
文件。 因此,如果稍后手动更改labelImg
文件名,则文件系统将无法工作,您必须再次重新运行labelImg
。 同样,如果在labelImg
操作之后调整图像大小,则标注文件的位置将更改,并且您将必须重新运行labelImg
。
通过训练和测试文件夹分隔文件
在本节中,我们将数据集分为train
和test
文件夹。 这是必需的,因为train
模型使用train
数据集生成模型,并使用test
数据集进行验证。 请注意,有时test
和val
名称可以互换使用来表示同一事物。 但是总的来说,我们需要第三个文件夹来检查最终模型是否与该模型以前未见过的一些未知图像相对应。 包含这些图像的文件夹称为val
-稍后将进行讨论。
请按照此处列出的步骤将图像分成train
和test
文件夹。 请注意,这些任务将在 Google Colab 上完成:
- 如果执行上述步骤,则将有两个文件夹-一个用于图像,一个用于标注。 接下来,我们创建两个单独的文件夹-
train
和test
。 - 将所有
.jpg
和.xml
文件复制到任何文件夹中。 因此,现在该文件夹将包含背对背.jpg
和.xml
文件。 - 将文件名类的 70% 的文件(
.jpg
和相应的.xml
文件)复制到train
文件夹中。 因此,完成本练习后,train
文件夹中将有大约 140 个文件(70 个.jpg
文件和 70 个.xml
文件)。 - 将剩余的 30% 的文件复制到
test
文件夹中。 - 将
train
和test
文件夹都上传到data
下的 Google 云端硬盘。 - 创建一个标题为
val
的验证文件夹,并将所有类中的一些图像插入其中。
请注意,在此示例中,在train
和test
文件夹之间使用了 70/30 的比例,但是通常,数字范围可以从 90/10 到 70/30。
- 在“我的云端硬盘”下(如以下屏幕截图所示),创建一个名为
Chapter10_R-CNN
的文件夹,然后在其中创建一个名为data
的文件夹:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xi5RFMcy-1681784662633)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/81b9b12b-0335-4dab-9b85-eeb146b53bf1.png)]
- 创建
data
文件夹后,在 Google 云端硬盘中在其中创建两个名为annotations
和images
的新文件夹,如图所示。 下一个任务是填充这些目录。
此屏幕快照显示了Chapter10_R-CNN
中的目录结构和命名约定:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mbunY6S9-1681784662634)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/59e995d5-155b-49ca-8e54-76b27fe1e60e.png)]
如上图所示的目录结构应在 Google 云端硬盘中建立。 请按照此处描述的格式开始使用:
- INPUT 代表
images
文件夹,需要提供所有图像数据。 请记住要遵循前面的图中概述的命名约定,并将.jpg
文件和.xml
文件上传到相应的目录,如上图所示。
由于大小限制,我们无法将图像数据上传到 GitHub 站点。 因此,本部分中使用的图像可以从这里的 Kaggle 食品图像(用于汉堡和薯条样本)下载。 电话并上传。
annotations
是输出文件夹,应为空,并将在下一部分中填写。 不要将annotations
文件夹与标注图像混淆以创建.xml
文件。 所有.xml
文件都放在images
文件夹中。
配置参数并安装所需的包
现在我们的图像准备工作已经完成,我们将开始在 Google Colab 笔记本中进行编码。 第一步是参数配置和获取训练工作所需的包,这涉及模型的类型,训练参数等等。 请按照以下步骤执行此操作:
- 在继续下一步之前,请将
Chapter10_Tensorflow-Training_a_Object_Detector_GoogleColab.ipynb
Python 文件保存到 Google 云端硬盘,然后将其作为 Colab 笔记本打开。 - 运行单元格
Configure
参数,然后通过按Shift + Enter
安装所需的包。 - 如果一切正常,则应该在以下代码块中看到显示模型配置选择的输出。 以下输出从
config
参数创建测试模型,这是开始构建数据并准备进行测试之前的先决条件:
Running tests under Python 3.6.9: /usr/bin/python3
[ RUN ] ModelBuilderTest.test_create_experimental_model
[ OK ] ModelBuilderTest.test_create_experimental_model
[ RUN ] ModelBuilderTest.test_create_faster_R-CNN_model_from_config_with_example_miner
[ OK ] ModelBuilderTest.test_create_faster_R-CNN_model_from_config_with_example_miner
[ RUN ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_faster_R-CNN_with_matmul
[ OK ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_faster_R-CNN_with_matmul
[ RUN ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_faster_R-CNN_without_matmul
[ OK ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_faster_R-CNN_without_matmul
[ RUN ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_mask_R-CNN_with_matmul
[ OK ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_mask_R-CNN_with_matmul
[ RUN ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_mask_R-CNN_without_matmul
[ OK ] ModelBuilderTest.test_create_faster_R-CNN_models_from_config_mask_R-CNN_without_matmul
[ RUN ] ModelBuilderTest.test_create_rfcn_model_from_config
[ OK ] ModelBuilderTest.test_create_rfcn_model_from_config
[ RUN ] ModelBuilderTest.test_create_ssd_fpn_model_from_config
[ OK ] ModelBuilderTest.test_create_ssd_fpn_model_from_config
[ RUN ] ModelBuilderTest.test_create_ssd_models_from_config
[ OK ] ModelBuilderTest.test_create_ssd_models_from_config
[ RUN ] ModelBuilderTest.test_invalid_faster_R-CNN_batchnorm_update
[ OK ] ModelBuilderTest.test_invalid_faster_R-CNN_batchnorm_update
[ RUN ] ModelBuilderTest.test_invalid_first_stage_nms_iou_threshold
[ OK ] ModelBuilderTest.test_invalid_first_stage_nms_iou_threshold
[ RUN ] ModelBuilderTest.test_invalid_model_config_proto
[ OK ] ModelBuilderTest.test_invalid_model_config_proto
[ RUN ] ModelBuilderTest.test_invalid_second_stage_batch_size
[ OK ] ModelBuilderTest.test_invalid_second_stage_batch_size
[ RUN ] ModelBuilderTest.test_session
[ SKIPPED ] ModelBuilderTest.test_session
[ RUN ] ModelBuilderTest.test_unknown_faster_R-CNN_feature_extractor
[ OK ] ModelBuilderTest.test_unknown_faster_R-CNN_feature_extractor
[ RUN ] ModelBuilderTest.test_unknown_meta_architecture
[ OK ] ModelBuilderTest.test_unknown_meta_architecture
[ RUN ] ModelBuilderTest.test_unknown_ssd_feature_extractor
[ OK ] ModelBuilderTest.test_unknown_ssd_feature_extractor
----------------------------------------------------------------------
Ran 17 tests in 0.157s
OK (skipped=1)
创建 TensorFlow 记录
这是非常重要的一步,我们许多人为此奋斗。 请按照以下步骤创建您的tfRecord
文件。 您必须在上一步中安装所有必需的包,然后才能继续执行此步骤:
- 在上图中的
Chapter10_R-CNN
文件夹下,data
下有两个文件名为xml_to_csv.py
并生成tfrecord.py
。 这些文件应从本地驱动器复制到 Google 云端硬盘。 - 当您使用
pip install TensorFlow
或pip install tensorflow-gpu
安装 TensorFlow 时,它将在home
目录下创建一个models-master
目录。 在其中,导航到research
文件夹,然后导航到object_detection
文件夹,您将找到xml_to_csv.py
并生成tfrecord.py
。 如前所述,将它们复制并插入 Google 云端硬盘。 您还可以在本地运行以下步骤,但是使用 TensorFlow 2.0 在本地运行时,我注意到错误,因此对于本练习,我们将在 Google Colab 中运行它。 - 接下来,我们将 Google 云端硬盘中的
Chapter10_R-CNN
文件夹链接到您的 Colab 笔记本。 这是通过使用以下命令完成的:
from google.colab import drive
drive.mount('/content/drive')
- 完成上述步骤后,系统将提示您输入 Google Drive 密钥,然后在输入密钥后将 Google Drive 装入 Colab 笔记本。
- 接下来,我们使用以下命令从 Colab 笔记本转到 Google 云端硬盘
Chapter10_R-CNN
目录:
%cd /content/drive/My Drive/Chapter10_R-CNN
- 现在,您可以执行以下步骤来生成
tfRecord
文件。 - 完全按照所示输入命令。 此命令将所有
.xml
文件从train
数据转换为data/annotations
文件夹中的train_labels.csv
文件:
!python xml_to_csv.py -i data/images/train -o data/annotations/train_labels.csv -l data/annotations
- 此命令将所有
.xml
文件从test
数据转换为data/annotations
文件夹中的test_labels.csv
文件:
!python xml_to_csv.py -i data/images/test -o data/annotations/test_labels.csv
- 该命令从
train_labels.csv
生成train.record
文件,从train
文件夹生成图像jpg
文件。 它还会生成lable_map.pbtxt
文件:
!python generate_tfrecord.py --csv_input=data/annotations/train_labels.csv --output_path=data/annotations/train.record --img_path=data/images/train --label_map data/annotations/label_map.pbtxt
- 该命令从
test_labels.csv
生成test.record
文件,从test
文件夹生成图像jpg
文件。 它还会生成lable_map.pbtxt
文件:
!python generate_tfrecord.py --csv_input=data/annotations/test_labels.csv --output_path=data/annotations/test.record --img_path=data/images/test --label_map data/annotations/label_map.pbtx
- 如果一切顺利,那么前面的代码行将生成以下输出。 这表示成功生成了训练和测试
tfRecord
文件。 请注意,扩展名可以是tfRecord
或record
:
/content/drive/My Drive/Chapter10_R-CNN
Successfully converted xml to csv.
Generate `data/annotations/label_map.pbtxt`
Successfully converted xml to csv.
WARNING:tensorflow:From generate_tfrecord.py:134: The name tf.app.run is deprecated. Please use tf.compat.v1.app.run instead.
WARNING:tensorflow:From generate_tfrecord.py:107: The name tf.python_io.TFRecordWriter is deprecated. Please use tf.io.TFRecordWriter instead.
W0104 13:36:52.637130 139700938962816 module_wrapper.py:139] From generate_tfrecord.py:107: The name tf.python_io.TFRecordWriter is deprecated. Please use tf.io.TFRecordWriter instead.
WARNING:tensorflow:From /content/models/research/object_detection/utils/label_map_util.py:138: The name tf.gfile.GFile is deprecated. Please use tf.io.gfile.GFile instead.
W0104 13:36:52.647315 139700938962816 module_wrapper.py:139] From /content/models/research/object_detection/utils/label_map_util.py:138: The name tf.gfile.GFile is deprecated. Please use tf.io.gfile.GFile instead.
Successfully created the TFRecords: /content/drive/My Drive/Chapter10_R-CNN/data/annotations/train.record
WARNING:tensorflow:From generate_tfrecord.py:134: The name tf.app.run is deprecated. Please use tf.compat.v1.app.run instead.
WARNING:tensorflow:From generate_tfrecord.py:107: The name tf.python_io.TFRecordWriter is deprecated. Please use tf.io.TFRecordWriter instead.
W0104 13:36:55.923784 140224824006528 module_wrapper.py:139] From generate_tfrecord.py:107: The name tf.python_io.TFRecordWriter is deprecated. Please use tf.io.TFRecordWriter instead.
WARNING:tensorflow:From /content/models/research/object_detection/utils/label_map_util.py:138: The name tf.gfile.GFile is deprecated. Please use tf.io.gfile.GFile instead.
W0104 13:36:55.933046 140224824006528 module_wrapper.py:139] From /content/models/research/object_detection/utils/label_map_util.py:138: The name tf.gfile.GFile is deprecated. Please use tf.io.gfile.GFile instead.
Successfully created the TFRecords: /content/drive/My Drive/Chapter10_R-CNN/data/annotations/test.reco
准备模型并配置训练管道
接下来,使用以下命令下载并解压缩基本模型。 在“配置参数和安装所需包”部分的配置参数步骤中,已选择模型和相应的配置参数。 可以根据配置参数和批量大小选择四种不同的模型(SSD,Faster R-CNN 和 R-FCN 的两种变体)。 您可以从指示的批量大小开始,并在模型优化期间根据需要进行调整:
MODEL_FILE = MODEL + '.tar.gz'
DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/'
DEST_DIR = '/content/models/research/pretrained_model'
在这里,目标目录是 Google Colab 笔记本本身,content/models/research
目录就在其中-因此,无需自己创建一个目录。 当您安装所需的包部分时,便完成了此操作。
此步骤还将从您的label_map.pbtxt
文件中自动下载许多类,并调整大小,比例,长宽比和卷积超参数,以准备进行训练。
使用 TensorBoard 监控训练进度
TensorBoard 是用于实时监控和可视化训练进度的工具。 它可以绘制训练损失和准确率的图表,因此无需手动绘制。 TensorBoard 允许您可视化模型图并具有许多其他功能。 访问这里,以了解有关 TensorBoard 功能的更多信息。
在本地计算机上运行的 TensorBoard
通过添加以下代码行,可以将 TensorBoard 添加到模型训练中。 检查 GitHub 页面上提供的代码以获取确切位置:
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
history = model.fit(x=x_train, y=y_train, epochs=25, validation_data=(x_test, y_test), callbacks=[tensorboard_callback])
然后,可以在训练开始后通过在终端中键入以下内容来可视化 TensorBoard 图:
%tensorboard --logdir logs/fit
在 Google Colab 上运行的 TensorBoard
本节介绍如何在 Google Colab 上运行 TensorBoard。 这涉及以下步骤:
- 为了在 Google Colab 上运行 TensorBoard,必须从本地 PC 访问 TensorBoard 页面。 这是通过名为 ngrok 的服务完成的,该服务将您的本地 PC 链接到 TensorBoard。 Ngrok 使用以下两行代码下载并提取到您的 PC 中:
!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
!unzip ngrok-stable-linux-amd64.zip
- 接下来,使用以下代码打开 TensorBoard:
LOG_DIR = model_dir
get_ipython().system_raw(
'tensorboard --logdir {} --host 0.0.0.0 --port 6006 &
.format(LOG_DIR))
- 之后,调用
ngrok
以使用端口6006
启动 TensorBoard,该端口是用于通信和交换数据的迁移通信协议:
get_ipython().system_raw('./ngrok http 6006 &')
- 最后一步是使用以下命令设置公共 URL 以访问 Google Colab TensorBoard:
! curl -s http://localhost:4040/api/tunnels | python3 -c \
"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])"
训练模型
完成上述所有步骤后,我们已准备好进行最重要的步骤-训练自定义神经网络。
训练模型是通过以下五个步骤执行的,这些步骤也在代码中概述:
- 指定配置文件。
- 指定输出模型目录。
- 指定发送
STDERR
文件的位置。 - 指定训练步骤数。
- 指定验证步骤的数量:
!python /content/models/research/object_detection/model_main.py \
--pipeline_config_path={pipeline_fname} \
--model_dir={model_dir} \
--alsologtostderr \
--num_train_steps={num_steps} \
--num_eval_steps={num_eval_steps}
此代码的说明如下:
- 管道配置路径由
pipeline_fname
定义,这是模型和配置文件。 Model_dir
是training
目录。 注意TensorBoard LOG_DIR
也映射到model_dir
,因此 TensorBoard 在训练期间获取数据。- 训练和评估步骤的数量是在配置设置期间预先定义的,可以根据需要进行调整。
训练成功开始后,您将开始在 Jupyter 笔记本中查看消息。 在某些包上的某些警告被弃用之后,您将开始看到有关训练步骤的注解并成功打开了动态库:
INFO:tensorflow:Maybe overwriting train_steps: 1000
Successfully opened dynamic library libcudnn.so.7
Successfully opened dynamic library libcublas.so.10
INFO:tensorflow:loss = 2.5942094, step = 0
loss = 2.5942094, step = 0
INFO:tensorflow:global_step/sec: 0.722117
global_step/sec: 0.722117
INFO:tensorflow:loss = 0.4186823, step = 100 (138.482 sec)
loss = 0.4186823, step = 100 (138.482 sec)
INFO:tensorflow:global_step/sec: 0.734027
global_step/sec: 0.734027
INFO:tensorflow:loss = 0.3267398, step = 200 (136.235 sec)
loss = 0.3267398, step = 200 (136.235 sec)
INFO:tensorflow:global_step/sec: 0.721528
global_step/sec: 0.721528
INFO:tensorflow:loss = 0.21641359, step = 300 (138.595 sec)
loss = 0.21641359, step = 300 (138.595 sec)
INFO:tensorflow:global_step/sec: 0.723918
global_step/sec: 0.723918
INFO:tensorflow:loss = 0.16113645, step = 400 (138.137 sec)
loss = 0.16113645, step = 400 (138.137 sec)
INFO:tensorflow:Saving checkpoints for 419 into training/model.ckpt.
model.ckpt-419
INFO:tensorflow:global_step/sec: 0.618595
global_step/sec: 0.618595
INFO:tensorflow:loss = 0.07212131, step = 500 (161.657 sec)
loss = 0.07212131, step = 500 (161.657 sec)
INFO:tensorflow:global_step/sec: 0.722247
] global_step/sec: 0.722247
INFO:tensorflow:loss = 0.11067433, step = 600 (138.457 sec)
loss = 0.11067433, step = 600 (138.457 sec)
INFO:tensorflow:global_step/sec: 0.72064
global_step/sec: 0.72064
INFO:tensorflow:loss = 0.07734648, step = 700 (138.765 sec)
loss = 0.07734648, step = 700 (138.765 sec)
INFO:tensorflow:global_step/sec: 0.722494
global_step/sec: 0.722494
INFO:tensorflow:loss = 0.088129714, step = 800 (138.410 sec)
loss = 0.088129714, step = 800 (138.410 sec)
INFO:tensorflow:Saving checkpoints for 836 into training/model.ckpt.
I0107 15:44:16.116585 14036592158
INFO:tensorflow:global_step/sec: 0.630514
global_step/sec: 0.630514
INFO:tensorflow:loss = 0.08999817, step = 900 (158.601 sec)
loss = 0.08999817, step = 900 (158.601 sec)
INFO:tensorflow:Saving checkpoints for 1000 into training/model.ckpt.
Saving checkpoints for 1000 into training/model.ckpt.
INFO:tensorflow:Skip the current checkpoint eval due to throttle secs (600 secs).Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.505
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.915
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.493
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.200
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.509
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.552
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.602
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.611
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.600
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.611
SavedModel written to: training/export/Servo/temp-b'1578412123'/saved_model.pb
INFO:tensorflow:Loss for final step: 0.06650969.
Loss for final step: 0.06650969.
请注意前面显示的输出。 根据您的 CPU/GPU 功能,执行此步骤将花费不同的时间。 在前面的训练输出中要注意的最重要的事情是训练期间的准确率和召回率值。
运行推理测试
此步骤涉及导出训练有素的推理图并运行推理测试。 推断是使用以下 Python 命令完成的:
!python /content/models/research/object_detection/export_inference_graph.py
--input_type=image_tensor
--pipeline_config_path={pipeline_fname}
--output_directory={output_directory}
--trained_checkpoint_prefix={last_model_path}
此处,last_model_path
是model_dir
,其中在训练期间存储模型检查点,而pipeline_fname
是模型路径和配置文件。 检查点涵盖训练过程中模型使用的参数值。 下图显示了训练期间开发的四种不同模型的输出。 通过执行上述步骤并仅选择不同的模型类型,它们可以逐一运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6cvH4PD5-1681784662634)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/e37adfb1-d76d-4334-bd0c-a4449b18bf33.png)]
请注意,前面提到的带有代码块的模型针对四种不同的模型运行。 在运行下一个模型之前,请单击 Google Colab 页面顶部的“运行时”,然后选择“工厂重置运行时”,以便为新模型重新开始。 请注意,SSD 模型仍然无法正确检测对象,而 R-CNN 和 R-FCN 则可以正确检测汉堡和薯条。 这可能是由于汉堡和薯条的大小几乎相同,并且我们从 SSD 概述中了解到 SSD 可以更好地检测不同比例的图像。
设置 TensorBoard 后,可以在 TensorBoard 中可视化输出。
TensorBoard 具有三个选项卡-标量,图像和图。 标量包括 mAP(精度),召回率和损失值,图像包括先前的视觉图像,图包括 TensorFlow 图frozen_inference_graph.pb
文件。 请注意,精度和召回率之间的差异定义如下:
精度 = 真正 / (真正 + 假正)
召回 = 真正 / (真正 + 假负)
使用神经网络模型时的注意事项
请注意,我们仅使用 68 张图像来训练我们的神经网络,它给了我们很好的预测。 这提出了四个问题:
- 我们开发的模型在所有情况下都能正确预测吗? 答案是不。 该模型只有
burger
和fries
两类,因此它可以检测其他与汉堡形状类似的对象,例如甜甜圈。 要解决此问题,我们需要加载类似于burger
的图像并将其分类为非burger
,然后使用这些其他图像集训练模型。 - 为什么我们听到我们需要成千上万张图像来训练神经网络? 如果您是从头开始训练神经网络,或者甚至是使用迁移学习从另一个模型(例如 Inception 或 ResNet)中获取权重,但是该模型之前从未看到过您的新图像,那么您将需要至少 1,000 幅图像。 1,000 个来自 ImageNet 数据集,每个类具有 1,000 个图像。
- 如果我们需要数千张图像进行训练,那么为什么在我们的案例中它可以工作? 在我们的案例中,我们使用了迁移学习并下载了 ImageNet 数据集的权重。 ImageNet 数据集已经将
cheeseburger
作为一类,因此对少于 100 张图像的迁移学习效果很好。 - 在使用少于 1000 张图像开发模型的情况下,什么时候根本不会检测到任何物体? 在对象与 ImageNet 类中的任何对象都非常不同的情况下,例如,检测到车身上的刮擦,红外图像等时。
Mask R-CNN 概述和 Google Colab 演示
Mask R-CNN 由 Kaiming He,Georgia Gkioxari,Piotr Dollar 和 Ross Girshick 在 CVPR 2017 中提出。Mask R-CNN 使用 R-CNN 有效地检测图像中的对象,同时针对每个兴趣区域进行对象分割任务。 因此,分割任务与分类和边界框回归并行工作。 Mask R-CNN 的高级架构如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5SLMxjXQ-1681784662639)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/2884d889-f0b0-44e5-83cf-22ec8797f59a.png)]
Mask R-CNN 实现的详细信息如下:
- 掩码 R-CNN 遵循 Faster R-CNN 的一般两阶段原理,但进行了修改—第一阶段 RPN 与 Faster R-CNN 相同。 第二阶段,快速 R-CNN,它从兴趣区域(RoI)中进行特征提取,分类和边界框回归开始,还为每个 RoI 输出二进制掩码 。
- 遮罩代表输入对象的空间形状。 掩码 R-CNN 使用完全卷积网络进行语义分割,为每个 RoI 预测一个(
M x N
)掩码。 - 将特征映射划分为
M x N
网格后,将 RoI Align 应用于区域提议网络的输出,然后在每个箱子中应用2 x 2
箱子和四个采样点 ,使用双线性插值选择。 RoI Align 用于将提取的特征与输入对齐。 - 骨干神经网络通过提取第四阶段的最后卷积层来使用 ResNet-50 或 101。
- 重新调整训练图像的大小,使较短的边缘为 800 像素。 每个微型批量每个 GPU 具有两张图像,正样本与负样本的比例为 1:3。 训练持续进行 160,000 次迭代,学习率
0.02
高达 120,000 次迭代,然后下降到0.002
。 使用0.0001
的权重衰减和0.9
的动量。
Mask R-CNN 图像分割演示是用 Google Colab 编写的。
笔记本电脑加载示例图像并通过激活 TPU 创建 TensorFlow 会话。 然后加载预训练的模型蒙版 R-CNN,然后执行实例分割和预测。 该笔记本取自 Google Colab 网站,仅作了一项修改-图像加载函数。 下图显示了 Mask R-CNN 的输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pbLgGWsq-1681784662639)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/e44dbd61-bc59-4d04-8207-5fc4e0e34536.png)]
Mask R-CNN 在前面概述的 Coco 数据集上进行了训练。 因此,human
,car
和traffic light
已经是为此预定的类。 每个人,汽车和交通信号灯都使用边界框进行检测,并使用分段绘制形状。
开发对象跟踪器模型来补充对象检测器
对象跟踪从对象检测开始,为每次检测分配一组唯一的 ID,并在对象四处移动时保持该 ID。 在本节中,将详细描述不同类型的对象跟踪模型。
基于质心的跟踪
顾名思义,基于质心的跟踪涉及跟踪使用阈值处理开发的图像群集的质心。 在初始化时,将 ID 分配给边界框形心。 在下一帧中,通过查看两个帧之间的相对距离来分配 ID。 当对象相距很远时此方法有效,但是当对象彼此非常靠近时该方法不起作用。
SORT 跟踪
SORT 是由 Alex Bewley,Zongyuan Ge,Lionel Ott,Fabio Ramos 和 Ben Upcroft 在其名为《简单在线和实时跟踪》的论文中提出的。 本文使用 Faster R-CNN 进行检测,而卡尔曼过滤器和匈牙利算法用于多目标跟踪(MOT)进行实时。 跟踪实现的详细信息可以在这个页面中找到。
DeepSORT 跟踪
在 CVPR 2017 上,Nicolai Wojke,Alex Bewley 和 Dietrich Paulus 在他们的论文中提出了 DeepSORT 跟踪,其论文标题为《使用深度关联指标的简单在线和实时跟踪》。 可以在这个页面中找到该论文的详细信息。
DeepSORT 是 SORT 的扩展,并使用经过训练以区分行人的 CNN 将外观信息集成到边界框中。 跟踪实现的详细信息可以在这个页面中找到。
该架构的细节概述如下:
- 跟踪方案是在八维状态空间
(u, v, γ, h, x, y, γ, h)
上定义的,其中(u, v)
是边界框中心位置,γ
是长宽比,h
是高度。 - 卡尔曼过滤器根据当前位置和速度信息预测未来状态。 在 DeepSORT 中,基于位置和速度的卡尔曼过滤器用于查找下一个跟踪位置。
- 对于每个轨道
k
,在卡尔曼过滤器预测期间对帧数进行计数和递增,并在对象检测期间将其重置为0
。 删除在前三个帧内超过阈值或与检测无关的轨道。 - 预测的卡尔曼状态与新到达的测量值之间的关联通过两种状态(预测的测量值和新的测量值)之间的马氏距离和外观描述符之间的余弦相似度的组合来解决。
- 引入了一个匹配的级联,该优先级优先于更常见的对象。
- 计算 IoU 关联以说明场景中突然消失的情况。
- 减少深度和增加宽度的广泛 ResNet 神经网络已用于改善薄残差网络上的表现。 宽的 ResNet 层具有两个卷积层和六个残差块。
- DeepSort 使用对 1,251 位行人的 110 万张人类图像进行训练的模型,并为每个边界框提取 128 个暗淡向量,以进行特征提取。
OpenCV 跟踪方法
OpenCV 具有许多内置的跟踪方法:
- BOOSTING 跟踪器:基于 Haar 级联的旧跟踪器。
- MIL 跟踪器:比 BOOSTING 跟踪器具有更高的准确率。
- 核相关过滤器(KCF)跟踪器:这比 BOOSTING 和 MIL 跟踪器快。
- CSRT 跟踪器:这比 KCF 更为准确,但跟踪速度可能较慢。
- MedianFlow 跟踪器:当对象有规律的运动并且在整个序列中可见时,此跟踪器将起作用。
- TLD 跟踪器:请勿使用。
- MOSSE 跟踪器:非常快速的跟踪器,但不如 CSRT 或 KCF 准确。
- GOTURN 跟踪器:基于深度学习的对象跟踪器。
OpenCV 中上述方法的实现如下:
tracker = cv2.TrackerBoosting_create()
tracker = cv2.TrackerCSRT_create()
tracker = cv2.TrackerKCF_create()
tracker = cv2.TrackerMedianFlow_create()
tracker = cv2.TrackerMIL_create()
tracker = cv2.TrackerMOSSE_create()
tracker = cv2.TrackerTLD_create()
基于连体网络的跟踪
Luca Bertinetto,Jack Valmadre,Joao F. Henriques,Andrea Vedaldi 和 Philip HS Torr 在其具有里程碑意义的论文《用于目标跟踪的全卷积连体网络》中提出了基于连体网络的对象跟踪。 可以在这个页面上找到该论文的详细信息。
在本文中,作者训练了一个深度卷积网络以离线开发相似性函数,然后将其应用于实时对象跟踪。 相似度函数是连体 CNN,将测试边界框与训练边界框(真实情况)进行比较并返回高分。 如果两个边界框包含相同的对象且分数较低,则对象不同。
连体网络通过相同的神经网络传递两个图像。 它通过删除最后一个全连接层来计算特征向量,这在“第 6 章”,“使用迁移学习的视觉搜索”中进行了描述。 然后比较两个特征向量的相似性。 所使用的连体网络没有任何全连接层。 因此,仅使用卷积过滤器,因此网络相对于输入图像是完全卷积的。 全卷积网络的优点是它与大小无关。 因此,任何输入尺寸均可用于test
和train
图像。 下图说明了连体网络的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0hJ7r7gQ-1681784662639)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/c5197e16-6f1d-47e0-875c-e2e789f29750.png)]
在该图中,网络的输出是特征映射。 通过 CNN(f[θ]
)重复该过程两次,一次分别进行测试(x
)和训练(z
)。 图像,生成两个相互关联的特征映射,如下所示:
跟踪开始如下:
初始图像位置 = 先前的目标位置
位移 = 跨步乘以最大得分相对于中心的位置
新位置 = 初始位置 + 位移
因此,矩形边界框用于初始化目标。 在每个后续帧,使用跟踪来估计其位置。
基于 SiamMask 的跟踪
在 CVPR 2019 上,王强,张立,Luca Bertinetto,胡卫明和 Phillip H.S.Torr 在他们的论文《快速在线对象跟踪和分段:统一方法》中提出了 SiamMask。 有关本文的更多详细信息,请参见这里。
SiamMask 使用单个边界框初始化并以每秒 55 帧的速度跟踪对象边界框。
在此,将连体网络的简单互相关替换为深度相关,以生成多通道响应图:
- 使用简单的两层
1 x 1
卷积神经网络hf
设计w x h
二元掩码(每个特征映射一个)。 第一层具有 256 个通道,第二层具有1 x 1
通道。 - ResNet-50 用于 CNN,直到第三阶段结束为止,最后以
1 x 1
卷积层结束。 请注意,ResNet-50 具有四个阶段,但仅考虑了前三个阶段,并且对跨步 1 的卷积进行了修改,以将输出跨步减小到 8。 - 在 DeepLab 中使用了扩张的(无意义的)卷积(在 “第 8 章”,“语义分割和神经样式迁移”中进行了详细描述)以增加接收场。 ResNet 第三阶段的最终输出附加了具有 256 个输出的
1 x 1
卷积。
可在这里 上找到有关 SiamMask 实现以及训练的详细信息。 SiamMask 也可以在这个页面上使用。 请注意,为了使其成功运行,视频文件必须以人像开头。
总结
在本章中,您将从头到尾全面了解各种对象检测器方法以及使用自己的自定义图像训练对象检测器的实用方法。 学习到的一些关键概念包括如何与 Google Cloud 一起使用以评估对象检测器,如何使用labelImg
创建标注文件,如何将 Google Drive 链接到 Google Colab 笔记本以读取文件,如何生成 TensorFlow .xml
和.jpg
文件中的tfRecord
文件,如何开始训练过程并在训练过程中监控读数,如何创建 TensorBoard 以观察训练准确率,如何在训练后保存模型以及如何通过保存的模型进行推断。 使用这种方法,您可以选择对象类并创建用于推理的对象检测模型。 您还学习了各种对象跟踪技术,例如 Kalman 滤波和基于神经网络的跟踪,例如 DeepSORT 和基于连体网络的对象跟踪方法。 下一步,可以将对象检测模型连接到跟踪方法以跟踪检测到的对象。
在下一章中,我们将通过在边缘设备(例如手机)中优化和部署神经网络模型来学习边缘计算机视觉。 我们还将学习如何使用 Raspberry Pi 进行实时对象检测。
第 4 节:边缘和云端的 TensorFlow 实现
在本部分中,您将使用到目前为止获得的所有计算机视觉和 CNN 知识,在边缘设备中打包,优化和部署模型,以解决现实生活中的计算机视觉问题。 在本地计算机上训练大型数据集需要花费时间,因此您将学习如何打包数据并上传到云中的容器,然后开始训练。 您还将看到如何克服一些常见的错误以完成训练并成功生成模型。
在本节结束之前,您将能够执行以下操作:
- 了解边缘设备如何使用各种硬件加速和软件优化技术基于神经网络模型以最小的延迟进行推理(第 11 章)
- 了解 MobileNet 模型的理论,因为它的速度通常会部署在边缘设备中(第 11 章)
- 使用 Intel OpenVINO 工具包和 TensorFlow Lite 在 RaspBerry Pi 中部署神经网络模型进行对象检测(第 11 章)
- 通过在 Android Studio 和 Xcode 中使用 TensorFlow Lite 部署模型来在 Android 手机和 iPhone 上执行对象检测(第 11 章)
- 使用 Create ML 训练自定义对象检测器,并使用 Xcode 和 Swift 将其部署在 iPhone 上(第 11 章)
- 对各种云平台的基础结构有一个总体了解- Google 云平台(GCP), Amazon Web Services(AWS) ,以及 Microsoft Azure 云平台(第 12 章)
- 为使用 GCP,AWS 和 Azure 的自定义对象检测开发端到端机器学习平台(第 12 章)
- 了解如何使用 TensorFlow 进行大规模训练和打包(第 12 章)
- 使用 GCP,AWS 和 Azure 执行可视搜索(第 12 章)
本节包括以下章节:
- “第 11 章”,“通过 CPU/GPU 优化在边缘设备上进行深度学习”
- “第 12 章”,“用于计算机视觉的云计算平台”
十一、带有 CPU/GPU 优化的边缘设备上的深度学习
到目前为止,我们已经学习了如何通过预处理数据,训练模型以及使用 Python PC 环境生成推论来开发深度学习模型。
在本章中,我们将学习如何采用生成的模型并将其部署在边缘设备和生产系统上。 这将导致完整的端到端 TensorFlow 对象检测模型实现。 本章将讨论许多边缘设备及其标称性能和加速技术。
特别是,使用 TensorFlow Lite 和 Intel 开放视觉推断和神经网络优化(VINO)架构,并部署到 Raspberry Pi,Android 和 iPhone。 尽管本章主要关注 Raspberry Pi,Android 和 iPhone 上的对象检测,但我们将介绍的方法可以扩展到图像分类,样式迁移和所考虑的任何边缘设备的动作识别。
本章分为以下几节:
- 边缘设备上的深度学习概述
- 用于 GPU/CPU 优化的技术
- MobileNet 概述
- 使用 Raspberry Pi 进行图像处理
- 使用 OpenVINO 进行模型转换和推理
- TensorFlow Lite 的应用
- 使用 TensorFlow Lite 在 Android 上进行对象检测
- 使用 TensorFlow Lite 在 Raspberry Pi 上进行对象检测
- 使用 TensorFlow Lite 和 Create ML 在 iPhone 上进行对象检测
- 各种标注方法的摘要
边缘设备上的深度学习概述
对于计算机而言,边缘是查看事物并测量参数的最终设备。 在边缘设备上进行深度学习意味着将 AI 注入到边缘设备中,以便与视觉一起还可以分析图像并报告其内容。 用于计算机视觉的边缘设备的示例是照相机。 边缘计算使本地图像识别快速有效。 摄像头内的 AI 组件由功能强大的微型处理器组成,该处理器具有深度学习功能。
取决于所使用的硬件和软件平台的选择,边缘的 AI 可以执行三种独立功能的组合:
- 硬件加速使设备运行更快
- 软件优化可减小模型尺寸并删除不必要的组件
- 与云交互来批量处理图像和张量
这样做的好处是提高了速度,减少了带宽,增加了数据保密性和网络可伸缩性。 这是通过在相机内部嵌入一个控制器来赋予相机所需的处理能力来完成的。
边缘计算意味着将工作负载从云转移到设备。 这就需要高效的边缘设备,优化的软件来执行检测而不会出现明显的延迟,以及高效的数据传输协议,以将选择的数据发送到云中进行处理,然后将输出反馈到边缘设备以进行实时决策。 选择正确的边缘设备取决于您的应用要求及其与子系统其余部分的接口方式。 边缘设备的一些示例如下:
- NVIDIA Jetson Nano
- Raspberry Pi + Intel 神经网络棒
- Coral 开发板 + Coral USB 加速器
- Orange Pi + Intel 神经网络棒
- ORDOID C2
- Android 手机
- iOS 手机
下表总结了前面列出的各种边缘设备的性能规格。 您可以使用此表来确定选择过程:
装置 | GPU | CPU | 内存 | 加速器 |
---|---|---|---|---|
NVIDIA Jetson Nano 69 毫米 x 45 毫米 | 128 核 NVIDIA Maxwell | 四核 ARM Cortex A57 | 4 GB RAM,16 GB 存储 | 并行处理器 |
Raspberry Pi 4 85 毫米 x 56 毫米 | 1.5 GHz 时的 ARM Cortex A72 | 4 GB RAM,32 GB 存储 | ||
Coral 开发板 48 毫米 x 40 毫米 | 集成的 GC7000 Lite 图形 | 四核 Cortex-A53,加上 Cortex-M4F | 1 GB LPDDR4 | Google Edge TPU ML 加速器协处理器 |
Orange Pi 85 毫米 x 55 毫米 | ARM Mali-400 MP2 GPU @ 600MHz | 4 个 Cortex-A7 @ 1.6 GHz | 1 GB DDR3 SDRAM | |
ORDOID C2 85 毫米 x 56 毫米 | Mali 450MP3 | ARM Cortex-A53 四核 @ 1.5 GHz | 2 GB DDR3 SDRAM | |
英特尔神经网络棒 | 英特尔 Movidius Myriad X 视觉处理单元(VPU),具有 16 个处理核心和一个网络硬件加速器 | 英特尔 OpenVINO 工具包 | ||
Coral USB 加速器 | Google Edge TPU ML 加速器协处理器,支持 AUTOML Vision Edge | TensorFlow Lite 模型支持 | ||
Android Pixel XL 155 毫米 x 76 毫米 | Ardeno 530 | 2 个 2.15 GHz Kryo 和 2 个 1.6 GHz Kryo | 4 GB 内存 | |
iPhone XR 155 毫米 x 76 毫米 | A12 仿生芯片 | A12 仿生芯片 | 3 GB 内存 |
用于 GPU/CPU 优化的技术
中央处理器(CPU)主要执行串行处理,而图形处理器(GPU)并行运行进程并且可以一次执行大量操作,从而加快了处理速度。 GPU 中的数据称为线程。 使用计算统一设备架构(CUDA)和开放计算语言(OpenCL)对 GPU 进行编程。 CPU 执行许多不同类型的计算,而 GPU 专门处理给定的计算,例如图像处理。 为了使边缘设备提供无延迟的结果,它们必须伴随加速器,GPU 和软件优化。
以下是一些通常用于 GPU/CPU 优化的方法:
- 模型优化方法,例如图像大小,批量归一化,梯度下降等。
- 基于幅度的权重修剪通过将模型权重清零来使模型稀疏,从而使其更易于压缩。 请参阅以下链接以了解修剪技术。
- GPU 内存分区,例如 NVIDIA Jetson Nano。
- 使用用于英特尔神经网络棒的通用 API,在 CPU,GPU 和 FPGA 上进行异构计算。
- SWAP 空间为 RAM 内存分配磁盘空间。
- 将张量处理单元(TPU)与 CPU 或 GPU 结合使用。 CPU 依次执行算术运算,而 GPU 一次执行多个算术运算。 TPU 由 Google 开发,用于加速神经网络处理。 在 TPU 中,算术运算直接相互连接,而无需使用任何内存。
- 量化,即将权重从 32 位转换为 8 位。
- iOS 手机使用不同的金属来访问 GPU,以加快图像处理速度。 有关更多详细信息,请参阅这里。
- 对于 Android 手机,请参考 VR 性能基准以了解可用的 GPU/CPU 优化方法。
MobileNet 概述
Google 的一个团队在 CVPR 2017 中的题为《MobileNets:针对移动视觉应用的高效卷积神经网络》中介绍了 MobileNet。 您可以在这个页面上找到此 MobileNet 论文。
MobileNet 提出了一种深度可分离的卷积架构,该架构缩小了神经网络模型,以便可以处理边缘设备的资源限制问题。 MobileNet 架构包括两个主要部分:
- 深度可分离卷积
- 逐点
1 x 1
卷积
请注意,我们在“第 4 章”,“图像深度学习”和“第 5 章”,“神经网络架构和模型”中描述了1 x 1
卷积的重要性。 您可能需要重新阅读这些章节。
下图显示了深度卷积的工作方式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2izNPwOe-1681784662640)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/08af9c03-40d5-4011-b437-39eb0e08a60c.png)]
在上图中,我们可以看到以下内容:
- 与普通卷积相比,我们减少了运算数量。
- 在 MobileNet 中,卷积层之后是批量归一化和 ReLU 非线性,最后一层除外,最后一层连接到 softmax 层进行分类。
- 可以通过深度乘法和分辨率乘法来减少 MobileNet 架构。
使用 Raspberry Pi 的图像处理
Raspberry Pi 是没有 GPU 的单板微型计算机,可以连接到外部相机和其他传感器模块,并且可以用 Python 编程以执行计算机视觉工作,例如目标检测。 Raspberry Pis 具有内置的 Wi-Fi,因此它们可以无缝连接到互联网以接收和传输数据。 由于其纤巧的外形和强大的计算能力,Raspberry Pi 是用于物联网和计算机视觉工作的边缘设备的完美示例。 可以在这个页面上找到有关 Raspberry Pi 的详细信息。 下图显示了 Raspberry Pi 的完整设置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KvYBmKz0-1681784662640)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/2dab1ebe-b2b9-4fb6-b3f4-948c143b26cd.png)]
以下各节将介绍 Raspberry Pi 的详细硬件设置。
请注意,此图像将在以下设置部分中多次列出。
Raspberry Pi 硬件设置
以下是开始 Raspberry Pi 设置工作之前要考虑的一些重要点:
- 订购最新版本的 Raspberry Pi 4 –您可以直接从 Raspberry Pi 或从任何在线商店获取。
- 获得具有 4 GB RAM 和 32 GB MicroSD 卡的 Raspberry Pi。 在大多数情况下,Raspberry Pi 都带有用 NOOBS 编程的 MicroSD 卡。 订购前请检查一下。
- 如果您的 Raspberry Pi 没有随附编程的 MicroSD 卡,请购买 32 GB 的 MicroSD 卡,然后通过转到这里在其上安装 NOOBS。 为此,您必须在用于 PC 的 MicroSD 适配器中安装 MicroSD 卡,然后使用常规 PC 将 NOOBS 下载到该卡上。 编程后,从适配器中卸下 MicroSD 卡,然后将其插入 Raspberry Pi MicroSD 插槽,该插槽位于 Raspberry Pi 下方,在 USB 插槽的对角位置,靠近电源按钮。 有关更多信息,请参见上一节中显示的照片。
- 大多数 Raspberry Pi 都不随附相机模块,因此请单独订购。 摄像头模块端口位于 HDMI 端口旁边,HDMI 端口上有一个黑色塑料夹。 相机随附白色带状电缆。 您可以向上拉照相机模块中的黑色塑料夹,然后将白色带状电缆完全插入其中,以使发亮的表面朝向旁边的 HDMI 端口。 插入带状电缆后,将塑料夹完全向下推以将其关闭,以使带状电缆牢固地连接到摄像头模块端口。 有关更多信息,请参见上一节中的照片。
- 将鼠标电缆,键盘电缆和 HDMI 电缆连接到外接显示器。 请注意,这是可选的,因为您可以使用 PC 通过 Wi-Fi 连接来连接 Raspberry Pi。
- 购买 Intel Neural Network Stick 2 并将其插入 USB 端口之一。 请注意,英特尔神经网络棒占用了额外的宽度,因此您必须具有所有三个 USB 端口(神经网络棒,用于键盘的 USB 和用于鼠标的 USB)的创造力。
- 所有连接完成后,连接电源。 Raspberry Pi 中的红灯会亮起,旁边的绿灯会偶尔闪烁,表明 microSD 卡已打开电源。 这表明一切正常。 下一节将讨论如何设置相机。
Raspberry Pi 相机软件设置
在本节中,我们将研究为了建立用于计算机视觉的 Raspberry Pi 而需要的 Python 中的各个代码段。
我们可以将相机设置为视频播放器。 在 Raspberry Pi 终端中一一使用以下命令。 这些命令将进行必要的包更新,并启动新的 Raspbian 安装:
$sudo apt update
$sudo apt full-upgrade
sudo raspi-config</code></pre></div></div><p>输入最后一个命令后,Raspberry Pi 中将出现一些对话框。 选择必要的接口选项,选择一个摄像机,然后单击“是”是否要启用摄像机接口? 然后,重新启动 Raspberry Pi,并在启动后在终端中输入以下命令:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">raspivid -o video.h264 -t 10000
您会注意到视频录制了 10 秒钟并以video.h264
格式保存。 第一次执行此操作时,您会发现相机未对准焦点。 调整相机上的圆帽(取下盖子后),直到其对准焦点。
到此结束如何设置相机软件。 如果要了解有关此过程的更多信息,请参考这里。
在 Raspberry Pi 中安装 OpenCV
有关详细说明,请转到这里。
在安装过程中,我发现必须在多个页面之间导航才能正确处理所有问题。 以下是对我有用的分步说明。 欢迎您使用官方网站或此处给出的说明以使所有东西正常运行:
以下每一行都是单独的指令。 这意味着要输入一个命令,请按Enter
并等待其显示在控制台中,表明已完成,然后再输入下一个命令。
- 在终端中输入以下命令以安装 OpenCV 所需的组件:
$sudo su
$apt update && apt upgrade –y
apt install build-essential</code></pre></div></div><ol class="ol-level-0"><li>安装 CMake 来管理构建过程:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">wget https://github.com/Kitware/CMake/releases/download/v3.14.4/cmake-3.14.4.tar.gz
$tar xvzf cmake-3.14.4.tar.gz
cd ~/cmake-3.14.4</code></pre></div></div><ol class="ol-level-0"><li>安装任何其他依赖项,例如<code>bootstrap</code>:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">./bootstrap
$make –j4
make install</code></pre></div></div><ol class="ol-level-0"><li>从 Raspberry Pi 驱动器中的源代码安装 OpenCV:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">git clone https://github.com/opencv/opencv.git
$cd opencv && mkdir build && cd build
$cmake –DCMAKE_BUILD_TYPE=Release –DCMAKE_INSTALL_PREFIX=/usr/local ..
$make –j4
make install</code></pre></div></div><p>上面的命令将安装 OpenCV。</p><ol class="ol-level-0"><li>要验证安装过程,请在保持当前终端打开的同时打开另一终端,然后输入以下命令:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">python3
>>> import cv2
>>> cv2.__version__
这应该显示系统上安装的最新 OpenCV 版本。
在 Raspberry Pi 中安装 OpenVINO
OpenVINO 是 Intel 的商标,代表 Open Visual Inference 和 Neural Network Optimization 工具包。 它为开发人员提供了基于 Intel 硬件的深度学习加速工具包,例如 CPU(Intel Core 和 Xeon 处理器),GPU(Intel Iris Pro 图形和 HD 图形),VPU(Intel Movidius 神经计算棒)和 FPGA(Intel Arria 10GX)。 。
要在桌面上下载 OpenVINO,请转到这里。
下载 OpenVINO 之后,您将必须输入您的姓名和电子邮件。 然后,您将能够下载 OpenVINO。 按照说明解压缩文件并安装依赖项。 请注意,此过程不适用于 Raspberry Pi。 因此,对于 Raspberry Pi,请使用以下命令:
$cd ~/dldt/inference-engine
$mkdir build && cd build
$cmake -DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_FLAGS='-march=armv7-a'
-DENABLE_MKL_DNN=OFF
-DENABLE_CLDNN=OFF
-DENABLE_GNA=OFF
-DENABLE_SSE42=OFF
-DTHREADING=SEQ
..
$make
前面的命令将在终端中返回一系列显示。
安装 OpenVINO 工具包组件
要安装 OpenVINO 工具包组件,请转到这里。
已列出以下步骤作为参考:
- 打开一个新的终端窗口,输入
sudo su
,然后按Enter
。 - 单击以下链接并下载
R3 l_openvino_toolkit_runtime_raspbian_p_2019.3.334.tgz
。 请注意,p_
和before.tgz
之后的数字在将来的版本中可能会更改。 - 创建一个安装文件夹:
$sudo mkdir -p /opt/intel/openvino
- 解压缩下载的文件:
$sudo tar -xf l_openvino_toolkit_runtime_raspbian_p_2019.3.334.tgz --
$strip 1 -C /opt/intel/openvino
- 接下来,安装 CMake(如果尚未安装):
sudo apt install cmake
通过设置环境变量,每次启动终端时,OpenVINO 都会被初始化。 这使您不必每次都记住命令提示符。
设置环境变量
您可以在以下步骤的帮助下本地设置环境变量或全局设置环境变量:
- 要在本地设置它,请在终端中运行以下命令:
$source /opt/intel/openvino/bin/setupvars.sh
- 要在全局设置它,请在终端中运行以下命令:
$echo "source /opt/intel/openvino/bin/setupvars.sh" >> ~/.bashrc
- 要测试所做的更改,请打开一个新的终端。 您将看到以下输出:
[setupvars.sh] OpenVINO environment initialized
Pi$raspberripi: $
Type sudo su and you should get
root@raspberripi:
添加 USB 规则
需要 USB 规则才能在 Intel Movidius 神经计算棒上进行推理。 按着这些次序:
- 以下命令将帮助您将任何当前 Linux 用户添加到该组:
$sudo usermod -a -G users "$(whoami)"
- 现在,重新启动 Raspberry Pi,然后再次登录:
sh /opt/intel/openvino/install_dependencies/install_NCS_udev_rules.sh
使用 Python 代码运行推理
完成所有安装过程后,下一个任务是使用通过相机模块连接到 Raspberry Pi 的 Intel Movidius 神经计算棒进行推理。 此处的摄像头模块是边缘设备,而带有英特尔 Movidius 神经计算棒的 Raspberry Pi 是处理器单元。
请注意,Raspberry Pi 本身无法通过神经网络执行推理,因为处理速度非常慢。 使用英特尔 OpenVINO 神经计算棒,您会看到很少的延迟。 作为比较,请参考“使用 TensorFlow Lite 在 Raspberry Pi 上进行对象检测”,其中使用 tflite 在没有神经网络棒的情况下将 TensorFlow 模型部署到 Raspberry Pi。 您会注意到,在这种情况下,延迟是很大的。
让我们看一下以下命令:
$mkdir build && cd build
$cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=armv7-a" /opt/intel/openvino/deployment_tools/inference_engine/samples
$make -j2 object_detection_sample_ssd
$wget --no-check-certificate https://download.01.org/opencv/2019/open_model_zoo/R1/models_bin/face-detection-adas-0001/FP16/face-detection-adas-0001.bin
$wget --no-check-certificate https://download.01.org/opencv/2019/open_model_zoo/R1/models_bin/face-detection-adas-0001/FP16/face-detection-adas-0001.xml
运行openvino_fd_myriad.py
文件中提供的示例代码,如下所示:
python3 openvino_fd_myriad.py
请参阅以下 GitHub 页面以获取完整代码。 另外,查看out.png
文件以查看在图像上绘制的边界框。
高级推理
到目前为止,我们刚刚使用 OpenVINO 工具包执行了面部检测。 在本节中,我们将学习如何使用连接到 Raspberry Pi 的 Intel Movidius 神经网络棒执行各种计算机视觉任务,例如行人检测,车辆和自行车检测,车牌检测,年龄和性别识别,面部标志识别 ,情感识别,姿势估计,动作识别,注视识别等。
英特尔开源技术中心提供了我们将使用的所有bin
和xml
文件的列表。 。
请注意,当您单击上一个链接时,将看到四个标记为R1, R2, R3, and R4
的文件夹。 单击一个具有最新日期的日期,在这种情况下为R1
。 在以下屏幕截图中可以看到:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXi2bz2M-1681784662640)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/1f5f007f-c2c0-46bc-8934-ac59097065c8.png)]
然后,单击最新文件夹,在这种情况下为models_bin
。 这将打开一个对话框,显示FP16
,FP32
或INT8
。 对于某些模型,不提供INT8
。
现在,让我们尝试了解这些参数的含义,以便我们可以根据自己的具体应用选择合适的参数。 FP16
将 16 位而不是 32 位用于FP32
,从而减少了训练和推理时间。 另一方面,INT8
使用 8 位整数对神经网络进行权重,梯度和激活的训练。 因此,在这三种方法中,INT8
应该是最快的一种,英特尔声称它仍然保持准确率。
如果您想了解有关英特尔使用的 8 位训练方法的更多信息,请参阅标题为《神经网络的 8 位训练的可扩展方法》的论文,该论文发表在这里。 为了在 Raspberry Pi 等边缘设备上更快地进行处理,建议的方法是使用FP16
或INT8
(如果有)。
先前描述的开放模型动物园具有各种预先构建的模型,例如用于人脸检测,人检测,自行车检测等的模型。 这些模型已经过训练,因此我们将在本章中仅出于推理目的使用这些模型。 如果您想了解训练方法,则可以按照“第 10 章”,“使用 R-CNN,SSD,和 R-FCN”。
接下来,我们将看一些将模型分为四种类型的表。
人脸检测,行人检测和车辆检测
下表描述了各种面部检测,人员检测以及车辆和自行车检测模型。 请仔细注意表中列出的每个模型的输入和输出,因为需要在 Python 代码中输入这些信息以进行推断:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mPaWIIfq-1681784662640)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/fe5c3606-c529-47cc-90c8-1fbb9a3cf358.png)]
我们可以看到,尽管模型类型不同,但输入本质上是相同的。 唯一的区别是输入图像的尺寸。 输出也相同–它们都生成一个矩形边界框。
地标模型
下表描述了用于年龄性别和情感识别,面部标志识别,车辆颜色和类型识别以及人的属性(例如衬衫,帽子和背包)的模型。 请注意表中列出的每个模型的输入和输出,因为这需要在 Python 代码中输入以进行推断:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxYDuPfs-1681784662640)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/4bfb353a-f606-47ac-bced-ec27c98aea28.png)]
在这里,输入是相同的:不同模型的尺寸不同,但是输出却不同。 对于地标,输出可以是面部轮廓的 5 点或 35 点。 对于人员属性,输出可以是八个属性中每个属性的二进制结果。 车辆属性可以是颜色或类型,而情感属性将导致五个类别中每个类别的概率。
动作识别模型
下表描述了用于姿势估计和动作识别的模型。 请注意表中列出的每个模型的输入和输出,因为这需要在 Python 代码中输入以进行推断:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZncke4q-1681784662641)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/ec8456e7-7202-4546-b63c-329915441c14.png)]
上表显示,所有模型的输入结构均相同,只是图像形状有所变化。 姿势识别的输出显示三个角度:偏航,横摇和俯仰。
车牌,注视和人员检测
最后,下表显示了车牌,注视估计和人员检测的多输入 Blob:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C7ZM5hnS-1681784662641)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/aab4bbfe-5f81-4980-aae3-a30bbeb9c4a4.png)]
以下代码概述了前两个表的主要组成部分; 即,用于面部检测,人物检测,汽车检测和地标检测。 让我们来看看:
- 请参阅以下 GitHub 链接以提取代码。
- 导入 OpenCV 和视频捕获后,可以使用以下命令加载模型。 它将加载人脸检测模型:
cvNet = cv2.dnn.readNet('face-detection-adas-0001.xml', 'face-detection-adas-0001.bin')
cvNet.setPreferableTarget(cv2.dnn.DNN_TARGET_MYRIAD)
- 以下命令可用于加载界标检测模型。 可以使用此命令打开列出的任何其他模型。 要记住的唯一重要的事情是,模型应该位于执行以下代码的 Python 所在的目录中:
cvLmk = cv2.dnn.readNet('facial-landmarks-35-adas-0002.xml','facial-landmarks-35-adas-0002.bin')
cvLmk.setPreferableTarget(cv2.dnn.DNN_TARGET_MYRIAD)
- 接下来,我们使用以下命令读取视频帧并定义该帧的行和列:
ret, frame = cam.read()
rows = frame.shape[0]
cols = frame.shape[1]
- 接下来,我们使用 OpenCV 的
blobFromImage
函数从给定大小和深度的帧中提取一个四维斑点。 请注意,斑点的大小应等于上表中列出的相应模型中指定的输入大小。 对于人脸检测,斑点输入大小为(672, 384)
,因此斑点表达式编写如下:
cvNet.setInput(cv2.dnn.blobFromImage(frame, size=(672, 384), ddepth=cv2.CV_8U))
cvOut = cvNet.forward()
对于界标检测,斑点输入大小为(60, 60)
,因此斑点表达可以表示为:
cvLmk.setInput(cv2.dnn.blobFromImage(frame, size=(60, 60), ddepth=cv2.CV_8U))
lmkOut = cvLmk.forward()
完成前面的步骤后,我们可以继续并绘制输出以进行可视化。 这是通过带有嵌套循环的两个for
语句执行的:
- 第一个
for
语句使用xmin, ymin, xmax, and ymax
查找矩形边界框坐标,如果confidence > 0.5
则使用cv2.rectangle
创建矩形。 - 第二个
for
语句在面边界框内绘制 35 个圆,其x
和y
坐标如下:
x = xmin + landmark output (i) * (xmax-xmin)
y = ymin + landmark output (i) * (ymax-ymin)
现在,我们可以使用cv2.circle
绘制圆。 下面的代码总结了这一原理,在其中绘制了面部标志。 请注意我们前面讨论的两个for
语句:
# Draw detected faces on the frame.
for detection in cvOut.reshape(-1,7):
confidence = float(detection[2])
xmin = int(detection[3] * cols)
ymin = int(detection[4] * rows)
xmax = int(detection[5] * cols)
ymax = int(detection[6] * rows)
if confidence > 0.5 :
frame = cv2.rectangle(frame, (xmin, ymin), (xmax, ymax), color=(255, 255, 255),thickness = 4)
for i in range(0, lmkOut.shape[1], 2):
x, y = int(xmin+lmkOut[0][i]*(xmax-xmin)), ymin+int(lmkOut[0][i+1]*(ymax-ymin))
# Draw Facial key points
cv2.circle(frame, (x, y), 1, color=(255,255,255),thickness = 4)
尽管此处描述的代码讨论了面部标志和面部检测,但是可以更新相同的 Python 代码,以便我们可以执行其他任何类型的检测,例如车牌,人,自行车等。 您需要做的就是通过更改设置的输入来更改输入,然后调整for
语句值。 此面部关键点检测示例是一个涉及面部和界标检测的复杂示例,这就是为什么使用两个for
循环语句的原因。 例如,在车牌检测中,您只需要使用一个for
循环语句。
现在,让我们学习使用 OpenVINO 进行推理。
使用 OpenVINO 的模型转换和推理
本节讨论如何使用预训练模型或定制训练模型来使用 OpenVINO 进行推理。 推理是使用模型执行对象检测或分类的过程,分为三个步骤:
- 使用来自 ncappzoo 的预训练模型进行推理。
- 将定制模型转换为 IR 格式以进行推断。
- 流程图中涉及的所有步骤的摘要。
以下各小节将详细讨论这些步骤。
使用 ncappzoo 在终端中运行推理
如前所述,OpenVINO 为 Raspberry Pi 安装的工具包与在普通 PC 上的安装方法不同。 Raspberry Pi 的安装不包括 Model Optimizer。 神经计算应用动物园(NCPAppZoo)是一个开放源代码存储库。 让我们看一下如何使用 ncappzoo:
- 要使用 ncappzoo,请克隆 OpenVINO 的开源版本和深度学习开发工具包(DLDT),然后更改 PYTHONPATH。 这样,模型优化器将安装在 Raspberry Pi 中。 以下代码块显示了这些步骤:
cd ~ git clone https://github.com/opencv/dldt.git dldt/model-optimizer pip3 install -r requirements_tf.txt
- 现在,使用以下命令克隆
repo
:
$git clone https://github.com/movidius/ncappzoo.git
- 转到
/ncappzoo/apps/
,找到相关的app
文件夹目录,然后执行以下命令:
$make run
这将打开一个窗口,我们可以在该窗口上显示图像。
转换预训练模型来进行推断
本部分描述了转换自定义 TensorFlow 模型的步骤,它们使用我们在“第 6 章”,“使用迁移学习的视觉搜索”中开发的 TensorFlow Keras 对象分类模型,或使用 TensorFlow 对象检测 API,就像我们在上一章中所做的那样。 如果您已经计划使用来自英特尔开放源技术中心的经过预先训练的优化模型,那么上一节中描述的步骤将起作用。 在下一节中,我们将描述如何使用两种类型的 TensorFlow 模型执行转换。
转换使用 Keras 开发的 TensorFlow 模型
本节介绍如何将 TensorFlow 模型转换为 OpenVINO IR 格式。 有关更多信息,请参考以下链接。
这些步骤可以总结如下:
- 配置模型优化器。 如本章开头所述,必须对部署在边缘设备上的任何模型进行优化,这涉及在不牺牲精度的情况下删除所有不必要的组件。 以下代码在全局范围内执行此任务:
<INSTALL_DIR>/deployment_tools/model_optimizer/install_prerequisites directory and run: $install_prerequisites.sh
- 转换为冻结模型。 请注意,我们在“第 6 章”,“使用迁移学习的视觉搜索”中开发的模型并未冻结。
- 将冻结的 TensorFlow 模型转换为 IR 形式。 推理引擎读取模型的中间表示(IR)。 IR 是 OpenVINO 特定的图形表示。 IR 表示的输出是我们已经熟悉的
xml
文件和bin
文件。 转换是通过mo.py
工具完成的,如以下代码所示:
Go to the <INSTALL_DIR>/deployment_tools/model_optimizer directoryin the Terminal and execute
$python3 mo_tf.py --input_model <INPUT_MODEL>.pb
在冻结模型开发过程中指定以下参数并理解它们非常重要,因为mo.py
工具有时会在冻结模型中找不到时产生错误:
input_model
:正在使用的预训练模型的名称input_shape
:例如[1,300,300,3]
转换使用 TensorFlow 对象检测 API 开发的 TensorFlow 模型
本节介绍如何转换使用 TensorFlow 对象检测 API 创建的冻结图。 如果使用 TensorFlow 对象检测 API 开发模型,则详细过程与我们在上一节中介绍的过程不同。 可以在这里中找到更多信息。
我们已经冻结了使用 TensorFlow 对象检测 API 在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN”进行对象检测的模型。 请按照以下步骤进行转换:
- 转换之前,请参考以下链接来配置模型优化器。
- 现在,我们准备进行转换。 准备三个文件,如下所示:
- 模型的冻结推理图:这是一个带有
.pb
扩展名的文件,是通过使用自定义图像训练模型(R-CNN,SSD 或 R-FCN)而生成的。 在此示例中,它是frozen_inference_graph_fasterRCNN.pb
。 - 配置
json
文件:这是相应的json
文件,该文件描述了冻结的 TensorFlow 图的自定义属性,节点,端口,端点和起点。 - 用于生成模型的配置文件:该文件与在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN”。 例如,对于 R-CNN,我们使用了
faster_rcnn_inception_v2_pets.config.
完成上述步骤后,在终端中执行以下代码:
$python3 mo_tf.py --input_model frozen_inference_graph_fasterRCNN.pb --transformations_config faster_rcnn_support_api_v1.14.json --tensorflow_object_detection_api_pipeline_config faster_rcnn_inception_v2_pets.config
在这里,您需要将扩展名为.pb
的文件替换为扩展名为.pb
的特定模型文件名。 转换的结果将是xml
和bin
文件。
有了xml
和bin
文件后,我们就可以使用 Python 文件和“高级推断”部分中所述的说明来测试模型。
如果在调色时遇到问题,可以使用下面的 linbke 中显示的 OpenVINO 论坛,以查看类似问题的答案,也可以发布您的问题。
OpenVINO 模型推断过程总结
前面描述的整个模型推断过程可以用流程图表示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RiTXuWNQ-1681784662641)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/07f2001b-42f3-4d51-9779-d69cb44501e8.png)]
上图表明该过程可以分为三个关键部分:
- 预处理步骤:在这里,我们安装 OpenCV 并设置环境变量。
- 模型准备:在这里,我们将模型转换为优化的模型格式。
- 推论:这可以分为两种独立的方法–通过在终端上执行推论,方法是转到相应的控制器并执行
make run
或使用 Python 代码执行推论。 我发现在 Intel PC 上,所有这些步骤都很容易执行。 但是,在 Raspberry Pi 环境中,使用make Run
命令在终端中进行操作会导致不同类型的错误。 例如,有时找不到.bin
或.xml
文件。 其他时间,环境变量未初始化或找不到CMakeLists.txt
文件。 执行提供的 Python 代码不会在 Raspberry Pi 中产生任何这些问题。 这也使我们对计算机视觉环境有了更好的了解,因为我们要做的只是获取模型,了解输入和输出,然后生成一些代码以便我们可以显示结果。
在继续下一节之前,让我们总结到目前为止所学的模型优化技术:
1)批量归一化操作与卷积操作融合-OpenVINO 使用它
2)将步长大于 1 并且过滤器大小为 1 的卷积移动到上层卷积层。 添加池化层以对齐输入形状-OpenVINO 使用它
3)用两个小过滤器替换大过滤器,例如将3 x 3 x 3
替换为#32
,将3 x 3 x 1
替换为#3
,将1 x 1 x 3
替换为#32
-MobileNet 使用它。
TensorFlow Lite 的应用
TensorFlow Lite 是用于边缘设备推理的 TensorFlow 深度学习框架。 与 OpenVINO 相似,TensorFlow Lite 具有内置的预训练深度学习模块。 或者,可以将现有模型转换为 TensorFlow Lite 格式以进行设备上推理。 目前,TensorFlow Lite 为具有内置或外部摄像头的 PC,Android 设备,iOS 设备,Raspberry Pi 和微型微控制器提供推理支持。 访问这里了解有关 TensorFlow Lite 的详细信息。
TensorFlow Lite 转换器采用 TensorFlow 模型并生成FlatBuffer tflite
文件。 FlatBuffer
文件是高效的跨平台库,可用于访问二进制序列化数据而无需解析。 序列化的数据通常是文本字符串。 二进制序列化数据是以字符串格式写入的二进制数据。 有关FlatBuffer
的详细信息,请参考以下链接。
TensorFlow 输出模型可以是以下类型:
- SavedModel 格式:
tf.saved_model
执行保存的模型,输出为saved_model.pb
。 它是完整的 TensorFlow 格式,其中包括学习的权重和图结构。 tf.keras
模型格式:tf.kears
模型是tf.keras.model.compile
文件,我们在“第 4 章”,“图像深度学习”和“第 6 章”,“使用迁移学习的视觉搜索”。- 具体函数:具有单个输入和输出的 TensorFlow 图。
将 TensorFlow 模型转换为 tflite 格式
本节将描述如何将 TensorFlow 模型转换为tflite
格式。 如果我们不这样做,那么我们开发的模型可以在本地 PC 中用于推理,但不能部署到边缘设备进行实时推理。 将针对此转换描述三种方法:
- Python API,在本地 PC 中用于
tflite
转换 - 使用
tflite
转换的 Google Colab - Google Colab 使用
toco
由于这是对象检测转换,因此我们的模型是根据 TensorFlow 对象检测 API 开发的,因此我们将在 Google Colab 中使用toco
方法。
Python API
Python API 使我们可以轻松使用 TensorFlow Lite 转换器。 在本节中,我们将描述使用 tflite 转换器的 Python API。 有关更多信息,请参考以下链接。
根据所使用的转换器类型,建议了三种方法–保存的模型,Keras 模型或具体函数。 以下代码显示了如何从 Python API 调用tf.lite.TFLiteConverter
来转换三个模型(保存模型,Keras 模型或具体函数)中的每个模型:
$import tensorflow as tf
$converter = tf.lite.TFLiteConverter.from_saved_model(export_dir)
$converter = tf.lite.TFLiteConverter.from_keras_model(model)
$converter = tf.lite.TFLiteConverter.from_concrete_functions([concrete_func])
tflite_model = converter.convert()
接下来,我们将学习如何使用 TensorFlow 对象检测 API 转换在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN 的对象检测”中开发的训练模型。 Google Colab 使用两种不同的方法-tflite_convert
和toco
。
TensorFlow 对象检测 API – tflite_convert
在以下代码中,我们定义了冻结模型.pb
文件和相应的tflite
文件的位置。 然后,我们将三个 RGB 轴的每一个的输入彩色图像的大小调整为(300, 300)
,并将图像转换为归一化张量,然后将其变为转换的输入数组。 有四个输出数组,它们的定义如下:
TFLite_Detection_PostProcess
—检测盒TFLite_Detection_PostProcess:1
-检测类别TFLite_Detection_PostProcess:2
-检测分数TFLite_Detection_PostProcess:3
-检测次数
!tflite_convert \
--graph_def_file=/content/models/research/fine_tuned_model/tflite_graph.pb \
--output_file=/content/models/research/fine_tuned_model/burgerfries.tflite \
--output_format=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' \
--change_concat_input_ranges=false \
--allow_custom_ops
TensorFlow 对象检测 API – TOCO
TOCO 代表 TensorFlow 优化转换器。 要了解对 TOCO 的详细了解,请访问以下 GitHub 页面。
以下代码描述了如何使用 TOCO 转换 TensorFlow 模型。 除了使用toco
而不是tflite
之外,代码的第一部分与之前的内容相同。 下一部分使用量化推断类型。 量化是一个过程,用于减小模型大小,同时改善硬件加速延迟。 有多种量化方法,如这个页面中所述。
在这种情况下,我们使用完整的整数量化。 没有使用反量化,但是平均值和标准差值用于确定推理代码中的定点乘数:
"!toco \\\n",
"--graph_def_file=\"/content/models/research/fine_tuned_model/tflite_graph.pb\" \\\n",
"--output_file=\"/content/models/research/fine_tuned_model/burgerfries_toco.tflite\" \\\n",
"--input_shapes=1,300,300,3 \\\n",
"--input_arrays=normalized_input_image_tensor \\\n",
"--output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' \\\n",
"--inference_type=QUANTIZED_UINT8 \\\n",
"--mean_values=128 \\\n",
"--std_dev_values=128 \\\n",
"--change_concat_input_ranges=false \\\n",
"--allow_custom_ops"
可以在以下 GitHub 链接中找到用于训练和转换的 Google Colab 笔记本的详细信息。
注意,在两个模型之间,我们使用了 TOCO。 原因是使用 tflite 时,转换后的模型不会在 Android 手机上检测到边界框。
TensorFlow 模型可以表示为已保存的模型或 Keras 模型。 以下代码显示了如何将模型另存为已保存的模型或 Keras 模型:
- 保存的模型:保存的模型包括 TensorFlow 权重和检查点。 它由
model.save
函数启动:
tf.saved_model.save(pretrained_model, "/tmp/mobilenet/1/")
tf.saved_model.save(obj, export_dir, signatures=None, options=None)
- Keras 模型:以下代码描述了如何使用
history.fit
命令编译 Keras 模型并准备进行训练。 请注意,我们在“第 4 章”,“图像深度学习”和“第 6 章”,“使用迁移学习的视觉搜索”中对此进行了编码练习。 :
model.compile(loss='sparse_categorical_crossentropy', optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train, batch_size=64, epochs=20)
model.save('path_to_my_model.h5')
模型优化
可以通过训练后量化来执行模型优化(也称为量化),以提高 CPU/GPU 性能,而不会牺牲准确率。 可以使用以下方法执行优化过程:
- 8 位精度的浮点(针对大小进行优化)
- 使用微控制器的整数输入和输出的完整量化
- 两者都有 - 动态量化为 8 位,但任何输出均以浮点形式存储
- 修剪是另一种动态优化方法,可在训练过程中从神经网络中消除低值权重。 可以通过以下代码行启动它:
from tensorflow_model_optimization.sparsity import keras as sparsity pruning_params = { 'pruning_schedule': sparsity.PolynomialDecay(initial_sparsity=0.50, final_sparsity=0.90, begin_step=end_step/2, end_step=end_step, frequency=100) }
l = tf.keras.layers
sparsity.prune_low_magnitude(l.Conv2D(64, (3, 3), activation='relu'),**pruning_params
有关详细信息,请访问 TensorFlow 网站。
请注意,在上一节中讨论了使用 Google Colab 对使用 TOCO 的对象检测模型进行的模型优化。
在以下代码中,我们正在优化保存的模型的大小,从而将最终输出模型减小到其原始大小的 1/3 或 1/4:
import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_quant_model = converter.convert()
以下代码描述了完整的整数量化以及大小的优化:
import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_quant_model = converter.convert()
使用 TensorFlow Lite 的 Android 手机上的对象检测
本节将介绍部署 TensorFlow lite 转换模型所需的步骤。 或者,您可以按照这个页面上的说明来构建示例应用。 有关 Android 手机上对象检测的详细流程图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hJgTizD0-1681784662641)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/20e25d76-69c4-408e-959e-e79140a129bb.png)]
我们需要两个文件:
- TensorFlow Lite 转换为
.tflite
格式的文件 - 更新的 labelmap
.txt
文件显示了该类
如果我们导出.tflite
文件,则直接来自 Google Colab,如“TensorFlow 对象检测 API – TOCO”部分中所述。 lablemap.txt
文件来自label_map.pbtxt
文件,仅列出了类的名称。
可以在以下 GitHub 页面上找到示例文件。
在 Android 手机中采用tflite
模型并生成推理的步骤如下:
- 在汉堡和薯条示例中,
.txt
文件将具有一列和两行,如下所示:
burger
fries
- 将这两个文件放在 PC 的同一目录中。 打开 Android Studio。 如果您以前从未使用过 Android Studio,则必须从这里下载。 请按照网站上提供的下载说明进行操作。
- 下载后,在 Mac 或 Windows 上,双击打开它。 对于 Linux,您必须转到终端并导航到
android-studio/bin
目录并键入./studio.h
。 - 通过在终端中键入以下内容来下载一些示例示例:
git clone https://github.com/tensorflow/examples
。 - 打开 Android Studio 并打开一个现有项目,将文件夹设置为
examples/lite/examples/object_detection/android
。 - 在 Android Studio 项目中,转到应用,然后转到资产,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-phCuhJkE-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/780b2705-5d24-4741-9bdc-51821712e470.png)]
- 右键单击“资产”,然后从菜单列表中选择在文件中显示。 将我们在第一步中创建的
.tflite
和.txt
文件拖放到资产目录中。 关闭文件夹,然后返回 Android Studio。 - 双击
.txt
文件将其打开,并在顶部添加新行。 用???
填充它。 因此,.txt
文件将为这两个类提供三行:
???
Burger
fries
- 选择
Java
,然后选择跟踪,然后双击DetectorActivity
。 将.tflite
和.txt
文件的名称更改为其实际名称,如以下屏幕截图所示。 然后,点击build gradle
:
请注意,对于.txt
文件,请保留路径,即file:///android_asset/burgerfries_labelmap.txt
。 稍后,我们将提到,如果未使用toco
生成.tflite
文件,则保留先前的路径将导致应用崩溃。 为了防止崩溃,您可以仅保留文件名(例如burgerfries_labelmap.txt
)。 但是,请注意,这不会为检测到的图像创建边界框。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhXbaHE7-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/91b37b72-690b-46c9-b2d8-7dbb92c321db.png)]
- 注释掉
///apply from download_model.gradle
。 验证依赖性是否出现,如前面的屏幕快照所示。 - 现在,使用 USB 电缆将 Android 设备连接到 PC。 转到您的设备,然后在“设置”下单击“开发人员选项”以确保其打开。 然后,打开 USB 调试。 对于许多 Android 手机,此选项会自动显示。
- 单击顶部的“生成”,然后单击“创建项目”。 在 Android Studio 完成编译后(查看屏幕底部以查看所有活动是否已完成),单击“运行”,然后单击“运行应用”。 该应用将下载到您的设备上。 设备上会出现一个选项框。 选择
ok
即可运行该应用。 以下是该应用工作的图像:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NTZ2j6Sn-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/ae5a9279-2ad0-40da-869f-8e2738873476.png)]
如我们所见,该电话能够以非常高的准确率清晰地检测汉堡和薯条的真实图像。 至此,Android 应用部署练习结束。
使用 TensorFlow Lite 的 Raspberry Pi 上的对象检测
TensorFlow Lite 下列出的 Python quickstart
包描述了如何为 Raspberry Pi 安装 TensorFlow Lite 包。 但是,有几个值得注意的例外。 因此,我们在此处列出了整个过程:
- 首先,请安装 TensorFlow Lite 解释器。 Raspberry Pi 已安装 ARM7 和 Python3.7,因此在终端中运行以下两个命令:
$sudo su
$pip3 install tflite_runtime-1.14.0-cp37-cp37m-linux_armv7l.whl
- 根据 TensorFlow Lite 官方文档,需要在
label_image.py
文件中进行一些更改:
$import tflite_runtime.interpreter as tflite,
$interpreter = tf.lite.Interpreter(model_path=args.model_file)
请注意,当在 Raspberry Pi 4 中进行了这些更改并且在终端中通过键入python3 label_image.py
执行代码时,将发生错误,指出即使安装了 Python,也找不到 TensorFlow Lite 解释器。 对 Raspberry Pi 3 重复了上述步骤,没有发生错误。
- 接下来,按照以下链接提供的步骤安装 TensorFlow Lite 目录和文件。
- 如果一切顺利,则应该在 Raspberry Pi 中有一个名为
pi/examples/lite/examples
的目录。 在此文件夹中,您应该具有诸如image_classification
,object_detection
,image_segmentation
,posenet
和style_transfer
等目录。 - 接下来,我们将在 Raspberry Pi 上执行两个示例-一个用于图像分类,另一个用于对象检测。
图片分类
现在,让我们执行以下步骤进行图像分类:
- 使用文件管理器转到
image_classification
目录,即pi/examples/lite/examples/image_classification/raspberry_pi
。 您将看到一个名为classify_picamera.py
的文件。 现在,转到这里并下载对象检测模型以及名为mobilenet_v2_1.0_224.tflite
和labels_mobilenet_v2_1.0_224.txt
的label
文件文件夹。 将这些文件复制到pi/examples/lite/examples/image_classification/raspberry_pi
中。 - 接下来,使用
pi/examples/lite/examples/image_classification/raspberry_pi
使用终端转到目录并执行以下命令:
$Python3 classify_picamera.py –model mobilenet_v2_1.0_224.tflite –labels labels_ mobilenet_v2_1.0_224.txt
- 您应该看到 Raspberry Pi 相机模块亮起并开始对图像进行分类。
对象检测
在 Raspberry Pi 上安装 TensorFlow lite 之后,我们现在可以执行对象检测。 按着这些次序:
- 使用文件管理器进入对象检测目录,即
pi/examples/lite/examples/object_detection/raspberry_pi
。 您将看到一个名为detect_picamera.py
的文件。 - 现在,转到这里并下载名为
coco_ssd_mobilenet_v1_1.0_quant_2018_06_29
的对象检测模型和标签文件文件夹。 在此文件夹中,您将看到两个文件:detect.tflite
和labelmap.txt
。 - 将这些文件复制到
pi/examples/lite/examples/object_detection/raspberry_pi
中。 - 接下来,使用
pi/examples/lite/examples/object_detection/raspberry_pi
使用终端转到对象检测目录,并执行以下命令:
$Python3 detect_picamera.py –model detect.tflite –labels labelmap.txt
现在,您应该看到 Raspberry Pi 摄像头模块亮起并开始在图像周围显示边框。
- 接下来,将
burgerfries.tflite
和labelmap
文件复制到文件夹中。 然后,更改前面命令行中显示的 Python 路径以反映您的新文件名并执行它。 以下图像是用于object_detection
的图像:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-paeP5Qz6-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/c324b898-4e23-407f-aa23-2a59ee6f2915.png)]
这里有几件事要注意:
- 我在 Raspberry Pi 中使用了广角相机,无法正确检测食物。
- 我转移到常规的 Raspberry Pi 相机上,能够检测到上图中看到的内容。
- 此处显示的检测效果不如使用手机时好,并且存在时滞。
该示例清楚地显示了相同模型在不同设备上的行为方式不同。
在 2020 TensorFlow 开发峰会上,TensorFlow 工程师宣布将显着改善延迟-浮点 CPU 执行为 55 ms 至 37 ms,定量定点 CPU 执行为 36 ms 至 13 ms,OpenCL 为 20 ms 至 5 ms 浮动 16 GPU 执行,2 ms 用于量化定点 Edge TPU 执行。 在进行此更改之前,对仅具有 CPU 的 Raspberry Pi 进行了测试。 因此,由于上述更改,您应该在 Raspberry Pi 上看到性能上的改进。 TF Lite 2.3 将带来进一步的改进。
使用 TensorFlow Lite 和 Create ML 的 iPhone 上的对象检测
到目前为止,我们已经学习了如何将 TensorFlow 模型转换为 tflite 格式并在 Android 手机和 Raspberry Pi 上进行推理。 在本节中,我们将使用 tflite 模型并在 iPhone 上执行推理。 iPhone 或 iPad 上的对象检测可以遵循两种不同的路径,如以下小节所述。
适用于 iPhone 的 TensorFlow Lite 转换模型
在本节中,我们将描述如何在 iPhone 上使用 tflite 模型进行对象检测。 有关详细信息,请参阅以下 GitHub 页面上概述的步骤。
本质上,该过程可以分为以下步骤:
- 此过程应在装有最新版本 Xcode 的 macOS 上完成。 您还应该具有 Apple Developer 证书。
- 在终端中,运行 Xcode 的命令行工具(
run xcode-select --install
)。 请注意,即使您已经安装了 Xcode,也需要完成此步骤。 - 在终端中输入
git clone
https://github.com/tensorflow/examples.git
。 - 通过在终端中输入
$sudo gem install cocoapods
来安装cocoapods
。 - 调用将安装 TensorFlow 示例的最终目录
examples-master
或examples
。 相应地更改以下文件夹地址。 - 在终端中,键入以下命令:
$cd examples-master/lite/examples/object_detection/ios
$pod install
- 前面的过程将执行三个主要任务:
- 在 Xcode 中安装 TensorFlow Lite
- 在文件夹中创建一个名为
ObjectDetection.xcworkspace
的文件 - 自动启动 Xcode 并打开
ObjectDetection
文件
以下屏幕截图显示了在 pod 安装过程中您将在终端中看到的注解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMdbINQu-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/adf11341-f850-4b43-a95a-f7e54b7ce588.png)]
- 在 Xcode 的签名部分,选择您的开发团队。
- 对应用进行以下更改:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ipjCfFni-1681784662642)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/2656ddf2-bd05-41dc-9d0b-66ffe9300a5a.png)]
前面的屏幕快照中描述的更改说明了如何用您的更改替换基线detect.tflite
和labelmap.txt
文件。 请注意,如果您不进行任何更改,而是通过将手机连接到 macOS 来运行 Xcode,则它将显示一个常规检测器,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-psdOCr0e-1681784662643)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/a50bc42d-3a36-4c41-a6b6-6ad55a96cc2c.png)]
要更改您的特定模型,请右键单击以删除旧模型,然后通过拖放安装新模型。 对代码内的文件名进行必要的更改,如“步骤 4”中所示。 以下屏幕截图显示了您将看到的输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mV00ejfG-1681784662643)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/364bb991-2fdb-4ba9-9877-5b59a39d0714.png)]
即使图像已旋转,前面的屏幕截图也清楚地显示出很好的检测效果。
Core ML
Core ML 是 Apple 的机器学习框架,该框架集成了来自 TensorFlow 等各种来源的神经网络模型,并在必要时进行了转换,然后优化了 GPU/CPU 性能以进行设备上的训练和推理,同时最大程度地减小了应用尺寸和功耗。 在 WWDC 2019 中引入的 Core ML 3 更新了设备上特定用户数据的神经网络模型,从而消除了设备到云的交互并最大程度地提高了用户隐私。 有关更多信息,请访问这里。 Core ML 本身建立在诸如 Accelerate 和 BNNS 以及 Metal Performance Shaders 之类的低级基元之上。 所有 Core ML 模型均具有.mlmodel
扩展名。
Core ML 的核心部分是 Create ML,它是用于图像分类和对象检测的 Apple 机器学习框架。 该系统类似于 TensorFlow,但使用零编码生成模型更容易。 在 macOS 上,打开 Xcode 并输入.mlmodel
,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVezoIcL-1681784662643)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/6612fd63-f175-4a05-950b-6c9880a8387c.png)]
现在,Create ML 中的整个模型开发过程仅涉及三个步骤:
- 准备数据 – 即输入文件
- 将数据拖到 Core ML 中,然后单击“训练”
- 保存模型(请注意,我找不到找到保存到桌面的方法,因此我通过电子邮件将其发送给自己并保存了文件)并分析了数据
以下屏幕截图显示了“创建 ML”中的训练过程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uipAowNB-1681784662643)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/157a82ce-0a7f-4cab-a372-d87cb608f1b5.png)]
有关上述屏幕截图的一些关键要点如下:
- 最终的训练损失为 0.83,这表明结果非常好–任何低于 1 的值都应表明检测良好。 请注意,仅使用 68 张图像即可获得该图像,这表明我们不需要大量图像即可开发出良好的神经网络模型。
- 请注意,与 TensorFlow 相比,使用 Create ML 开发模型非常容易-绝对零编码,无需转换,也无需前往单独的站点即可查看图表。 一切都紧凑且易于使用。
开发模型后,将其移植到以下用 Swift 编写的视觉框架。 它将检测带有边界框的对象。
以下是有关应用开发的一些注意事项:
- 您必须具有 Apple 开发人员帐户和团队才能登录 Xcode。
- 您需要删除现有模型并将最新模型拖到 Xcode 中,如以下屏幕截图的左侧所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yTkQDwzL-1681784662643)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/3d776c62-9329-4302-9faa-20f56dffad73.png)]
- 完成此操作后,转到
ViewController.swift
,并将默认模型名称重命名为您的模型名称,如上图右侧所示。 最后,建立模型并在 iPhone 上运行。
以下屏幕截图显示了模型输出。 它显示了我们使用 Create ML 开发的模型与我们使用 TensorFlow 开发并转换为.tflite
形式的模型提供的检测结果的比较:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJ6QyFKb-1681784662644)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/a67c4a1b-181e-4def-942f-cbf53fa7f94f.png)]
将 TensorFlow 模型转换为 Core ML 格式
转换器仅转换 TensorFlow 模型的一部分。 完整的 MobileNet-SSD TF 模型包含四个子图:Preprocessor
,FeatureExtractor
,MultipleGridAnchorGenerator
和Postprocessor
。 Core ML 工具仅转换模型中的FeatureExtractor
子图; 其他任务必须由开发人员自行转换。
各种标注方法的摘要
图像标注是对象检测或分割的核心部分。 就神经网络开发中的手动工作而言,此部分最繁琐。 先前,我们描述了用于标注的三个工具:LebelImg
,VGG Image Annotator
和RectLabel
。 但是,还有许多其他工具可用,例如 Supervisely 和 Labelbox。 其中一些工具会执行半自动标注。 最大的挑战是创建 100,000 个标注,并在像素级精度内正确地进行标注。 如果标注不正确,则开发的模型将不正确,并且在 100,000 张图像中找到不正确的标注就像在大海捞针中找针。 对于大型项目工作,标注工作流可以分为两类:
- 将标注工作外包给第三方
- 自动或半自动标注
在下一节中,我们将讨论这两种方法。
将标注工作外包给第三方
许多企业将标签工作作为其核心业务模型之一。 每个云服务提供商都与人类标签商合作,为神经网络开发工作执行准确的图像标签服务。 以下是有关在哪里可以找到第三方数据标签服务的一些信息。 请注意,此列表并不全面,因此请在此列表之外进行自己的研究,以找到适合您需求的数据标签服务:
- Google Cloud –数据标签。 有关详细信息,请转到这里。
- Amazon Sagemaker 真实情况–使用 Amazon Mechanical Turk 进行数据标记。 有关详细信息,请转到这里。
- Hive AI 数据标签服务。 有关详细信息,请转到这里。
- Cloud Factory 数据标签服务。 有关详细信息,请转到这里。
数据标记服务的成本可能会很高。
自动或半自动标注
在本节中,我们将讨论一个完全免费的自动标注工具,该工具应减少人工标记的程度。 这是英特尔的计算机视觉标注工具(CVAT)工具,它非常有前途,仅通过加载模型即可执行完整的自动标注作为起点。 您可以在这个页面中找到有关该工具的更多信息。 。
该工具能够为边界框,多边形和语义分段创建标注,并且还可以执行自动标注。 该工具可以将标注输出为 VOC XML,JSON TXT 或 TFRecord 文件。 这意味着,如果您使用该工具,则无需将图像转换为 TFRecord 形式–您可以直接训练神经网络。 请按照以下步骤学习如何使用该工具:
- 执行必要的安装。 所有说明均在终端中执行,包括安装 Docker,构建 Docker 映像以及克隆 CVAT 源代码。 可以在这个页面中找到更多信息。
- 通过转到这里,安装已在 coco 数据集上训练的 Faster R-CNN ResNet 初始 Atrous 模型。
- 安装 OpenVINO 模型。 如果您使用的是 TensorFlow,则无需安装 OpenVINO 模型-只需直接转到“步骤 4”。 但是,如果要使用 Intel Open Model Zoo 中的模型或您自己的自定义模型,请遵循此链接上的说明。
- 打开谷歌浏览器,然后输入
localhost:8080
。 这将打开 CVAT。 请注意,CVAT 当前仅可在 Google Chrome 浏览器上使用。 - 从下拉列表中选择模型,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfTatTT0-1681784662644)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/e1fb61bb-7fa6-41d3-ad83-b03c9723a6e1.png)]
对于 TensorFlow,只有一种模型可供选择。 但是,您仍然需要从下拉列表中选择类,如前面的屏幕快照所示。 请注意,您可以选择多个类别,但不会显示选定的类别。
- 通过给它命名来创建任务。 然后,命名所有类并添加所有图像,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9AgA9JNS-1681784662644)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/80fc9121-fc2a-4d57-8659-2dc90d4c28e8.png)]
如前面的屏幕快照所示,已上传了九张图像。 然后,单击“提交”按钮,这将创建任务。 您可以将不同的人分配给不同的任务。
- 在“任务”下,在操作旁边的新菜单栏上单击鼠标左键,然后选择“自动标注”。 您将看到一个菜单栏,显示其进度。
- 完成自动标注后,单击“作业编号” –您会注意到所有图像都有标注。 以下屏幕截图显示了所有上传的九张图像的自动标注报告:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tw3lM5C6-1681784662644)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/cbcf29f5-1fe4-4588-952f-56e2e5b75956.png)]
在前面的示例中,我们一次批量加载了所有九个图像,以演示自动化过程的有效性。 它正确检测了所有物体(汽车,人,卡车和摩托车)。 在某些情况下,该模型没有绘制交通信号灯和停车标志。 因此,在此示例中,只有交通信号灯和停车标志需要手动标注; 我们可以将工具用于所有其他对象。 接下来,我们以 VOC XML 格式获取该工具的输出,并将图像以及.xml
文件加载到标签边界框的labelImg
工具中。 以下屏幕截图显示了结果。 请注意,这是上述屏幕快照的左下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-865cnxPA-1681784662645)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/94644d6e-9a04-4733-b4b8-7dc42b806a4e.png)]
数据显示贴标工作非常准确。 该工具不断更新。 与其他任何工具一样,如果遇到此处未涉及的任何问题,请提交工作单。
我发现了与该工具有关的一个问题:输出不一致表示对于某些图像,它将绘制边界框标注,而对于其他图像,则不会。 我通过移至另一台 Linux PC 并重新安装 CVAT 来解决了此问题。 要在当前 PC 上解决此问题,可以在当前 CVAT 目录中卸载 Docker,删除 CVAT 文件夹,并确保端口8080
没有被其他程序调用。 然后,您可以重新安装 CVAT。
总结
在本章中,您学习了如何在网络的最远端开发和优化卷积神经网络模型。 神经网络的核心是需要训练的大量数据,但最终,它提供了一个模型,该模型无需人工干预即可完成任务。 在前面的章节中,我们了解了必要的理论和实现的模型,但从未进行任何实际练习。 在实践中,摄像机可以用于监视,监视机器性能或评估手术过程。 在每种情况下,嵌入式视觉都用于实时设备上数据处理,这需要在边缘设备上部署更小,更有效的模型。
在本章中,您了解了各种单板计算机和加速器的性能,从而使您能够针对特定应用选择哪种设备做出明智的决定。 然后,我们学习了如何使用 OpenVINO 工具包和 TensorFlow Lite 来设置 Raspberry Pi 并在其上部署神经网络。 我们这样做是为了进行设备上的推断。 之后,我们学习了如何将 TensorFlow 模型转换为 TensorFlow Lite 模型并将其部署在 Android 和 iOS 设备上。 我们还了解了 Apple 的 Core ML 平台,并使用 Create ML 训练神经网络以开发对象检测器模型。 然后,我们将其与 TensorFlow Lite 对象检测器模型进行了比较。 我们在本章结束时概述了图像标注和自动标注方法。
在下一章中,我们将学习如何使用云处理来训练神经网络,然后将其部署在设备上。
十二、用于计算机视觉的云计算平台
云计算使用互联网从远程硬件普遍访问数据。 此类数据存储是使用云平台完成的。 对于计算机视觉,数据主要是图像,标注文件和结果模型。 云平台不仅存储数据,而且还执行训练,部署和分析。 云计算与边缘计算的不同之处在于,我们无需在基础设施上进行投资,就可拥有几乎瞬时的分析速度。
在本章中,您将学习如何在 Google Cloud Platform(GCP), Amazon Web Services(AWS)和 Microsoft Azure 云平台中打包应用以进行训练和部署。 您将学习如何准备数据,上传到云数据存储以及如何监视训练。 您还将学习如何将图像或图像向量发送到云平台进行分析并获得 JSON 响应。 本章讨论单个应用以及如何在计算引擎上运行分布式 TensorFlow。 训练结束后,本章将讨论如何评估模型并将其集成到应用中以进行大规模操作。
本章分为以下几节:
- 在 GCP 中训练对象检测器
- 在 AWS SageMaker 云平台中训练对象检测器
- 在 Microsoft Azure 云平台中训练对象检测器
- 大规模训练和包装
- 基于云的视觉搜索背后的总体思路
- 分析各种云平台中的图像和搜索机制
在 GCP 中训练对象检测器
在前两章中,我们学习了如何设置 Google Colab 以使用 SSD,R-CNN 和 R-FCN 以及 Inception 和 MobileNet 作为骨干预训练网络来训练自定义对象检测器。 我们的网络用于检测汉堡和薯条。 在本节中,我们将学习如何使用 GCP 执行相同的任务。 您也可以在这里。
我从上一篇文章开始,但是发现必须精简许多部分,并且需要添加其他详细信息才能使其在我的 Ubuntu PC 上运行。 以下小节提供了使用 GCP 训练目标探测器的分步过程。
请注意,本节涉及许多将本地终端连接到 GCP 的大步骤,有时信息流可能会造成混乱。建议您在本节开始之前仔细阅读本节结尾处提供的流程图。 在 AWS Sagemaker 云平台上训练对象检测器,以了解一般的信息流。
在 GCP 中创建项目
在本节中,将在 GCP 中创建一个项目。 一个项目包括账单,数据存储,API,认证和团队成员信息,以开始您的训练工作。 GCP 是 Google 的机器学习平台,用于存储,构建,训练和部署模型。 通过转到这里登录到 GCP 控制台。
首先,使用您的 Gmail ID 和密码登录,您将看到以下控制台:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yHgep4kW-1681784662645)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/e8a37646-4f8b-4083-b963-59c1bc6ce5a4.png)]
进入控制台后,请花一些时间来熟悉各种选项。 特别是,您必须填写有关帐单,API 和项目设置的信息。 以下小节概述了详细的说明。
GCP 设置
转到这里设置 GCP 并使用您的 Gmail 帐户登录。 在上一节的屏幕快照中,有三个矩形框,它们是您需要设置的三个主要部分。 步骤概述如下:
- 首先,单击“转到项目设置”,为项目命名,然后分配团队成员(如果要由多个人从事该项目)。
- 然后,点击左侧的帐单并提供您的信用卡信息。 在撰写本文时,Google 提供了 300 美元的免费试用额度,但您仍需要提供信用卡信息。
- 完成此操作后,单击“API 和服务”,然后单击“启用 API 和服务”,然后在“机器学习”下选择“AI 平台训练和预测 API”。
- 单击“启用”,将启用 API。 以下屏幕截图显示了启用后的 AI Platform Training&Prediction API:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dlZt6CS-1681784662645)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/de81e552-ecaf-4070-8cbd-63f8c8b1072c.png)]
Google Cloud Storage 存储桶设置
存储桶是保存数据的容器。 所有云服务提供商都有存储桶。 存储桶的格式与 PC 的目录结构相同。 存储桶可以包含图像(.jpg
文件),标注,TFRecord,检查点文件和模型输出。 在本部分中,我们将学习如何安装 Google Cloud Storage(GCS)存储桶以存储训练和测试数据。
使用 GCP API 设置存储桶
要使用 GCP API 设置存储桶,请按照以下步骤操作:
- 注册帐单后,向下滚动左侧菜单,单击“存储”,然后单击“创建桶”,并为其命名:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aUN5tiuw-1681784662645)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/aace5356-40d0-4073-876f-b3e7d9dcc187.png)]
- 创建存储桶后,下一个任务是在存储桶中创建一个名为
data
的文件夹,然后将文件上传到其中。 请看以下屏幕截图,了解如何执行此操作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXllbR9T-1681784662646)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/0ac81fac-f1a8-4470-bd25-2834d6b1c56e.png)]
如前面的屏幕快照所示,首先创建一个名为data
的文件夹。 然后,单击“数据”,单击“上载文件”,然后上载test.record
,train.record
,label_map.pbtxt
,pipeline.config
和model.ckpt*
(三个文件)。 我们将在下一节中介绍如何获取这些文件。
使用 Ubuntu 终端设置存储桶
此过程涉及到设置 Google Cloud SDK,然后将 Google Cloud 项目和存储桶链接到您的终端,以便您可以在那里上传文件。 请记住,训练将由终端命令启动,因此,即使您使用前面的 API 进行了设置,您仍然需要执行以下部分中显示的步骤(从“开始设置 Google Cloud SDK”部分)以将终端链接到 GCP。
设置 Google Cloud SDK
Google Cloud SDK 是一组命令行工具,使您的 PC 可以与 Google Cloud 进行交互。 由于在本节中,我们将使用 Ubuntu 终端与 Google Cloud 进行交互,因此我们需要首先设置 SDK。 在终端中输入以下命令:
$ echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
$ sudo apt-get update && sudo apt-get install google-cloud-sdk
$ gcloud init
在前面的代码的前三行中,我们获得了 SDK 列表,然后使用apt-key
对包进行认证,然后安装 SDK。 在第四行中,我们将使用gcloud.init
设置gcloud
配置。
同样,如前所述,如果您在遵循本节时遇到任何困难,可以查看本节末尾提供的流程图,以了解一般的信息流。
接下来,我们将您的本地 PC 链接到 Google Cloud 项目。
将您的终端链接到 Google Cloud 项目和存储桶
在上一节的步骤中,我们设置了 Google Cloud SDK。 现在,我们需要执行最重要的步骤,这是将 Ubuntu 终端接到 Google Cloud 项目以及您之前创建的存储桶。
为什么需要将 Ubuntu 终端链接到 Google Cloud 项目? 答案是我们使用本地 PC 上的终端启动训练命令,但是我们的数据存储在 GCP 的存储桶中,并且模型将在 GCP 中生成。 因此,我们需要将 PC 终端连接到 GCP 以完成训练任务。
在终端中按顺序输入以下步骤:
- 设置项目,在本例中为
rcnn-trainingpack
:
$ gcloud config set project rcnn-trainingpack
- 要打开存储桶,请输入
gsutil
Python 命令,如下所示:
$ gsutil mb gs://krish_burgerfries
- 接下来,我们设置环境变量以定义存储桶和文件所属的项目:
$ export PROJECT="rcnn-trainingpack"
$ export YOUR_GCS_BUCKET="krish_burgerfries"
- 通过输入以下命令来添加特定于 TPU 的服务帐户:
张量处理单元(TPU)是 Google 开发的一种 AI 加速器,用于快速处理大量数据以训练神经网络。
$ curl -H "Authorization: Bearer $(gcloud auth print-access-token)"
https://ml.googleapis.com/v1/projects/${PROJECT}:getConfig
前面的命令会将以下输出返回到“终端”窗口。 请注意,服务名称和项目名称将与您的应用不同:
{"serviceAccount": "service-444444444444@cloud-ml.google.com.iam.gserviceaccount.com", "serviceAccountProject": "111111111111", "config": {"tpuServiceAccount": "service-111111111111@cloud-tpu.iam.gserviceaccount.com" }}
{"serviceAccount": "service-444444444444@cloud-ml.google.com.iam.gserviceaccount.com",
"serviceAccountProject": "111111111111",
"config": {
"tpuServiceAccount": "service-111111111111@cloud-tpu.iam.gserviceaccount.com" }}
- 通过键入整个
tpuServiceAccount
路径,将 TPU 帐户导出为环境变量,如下所示:
export TPU_ACCOUNT="service-111111111111@cloud-tpu.iam.gserviceaccount.com"</code></pre></div></div><ol class="ol-level-0"><li>将<code>ml.serviceAgent</code>角色授予 TPU 帐户:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> gcloud projects add-iam-policy-binding PROJECT --member serviceAccount:TPU_ACCOUNT --role roles/ml.serviceAgent
这将在终端中产生一系列注解,从Updated IAM policy for the project [rcnn-trainingpack]
开始。
安装 TensorFlow 对象检测 API
现在我们已经将终端链接到存储桶和 Google Cloud 项目,下一步是将其链接到 TensorFlow 对象检测 API。 请遵循这里提供的一组说明。
前面的安装链接包含许多未在此处列出的代码行。 您将能够正确执行大多数代码。 此过程的最后两行代码描述如下:
# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:'pwd':'pwd'/slim
python object_detection/builders/model_builder_test.py
该说明说,前面的步骤对于成功安装至关重要。 但是,如果您的 PC 上安装了 TensorFlow 2.0,则可能会出现以下错误:
AttributeError: module 'tensorflow' has no attribute 'contrib'
即使此错误已解决,也会导致另一个与 TensorFlow 2.0 与 TensorFlow 对象检测 API 不兼容有关的错误。 因此,我们将改为描述替代路径。 另一种选择是使用这里,类似于我们在第 10 章“使用 R-CNN,SSD 和 R-FCN 进行对象检测”,和第 11 章“在具有 CPU/GPU 优化功能的边缘设备上进行深度学习”中使用 TensorFlow 1.15 在 Google Colab 中运行它。
准备数据集
如“使用 GCP API”部分设置存储桶中所述,我们需要填充以下bucket: test.record
,train.record
,label_map.pbtxt
,pipeline.config
和model.ckpt*
(三个文件 )。 在下面的小节中,我们将说明如何填充这些内容。
TFRecord 和标记地图数据
TFRecord 文件是高效的 TensorFlow 文件格式,用于以单一二进制格式存储图像和标注文件,以供 TensorFlow 模型超快速读取。 TFRecord 已在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN”的对象检测中引入。 在本节中,我们将描述如何准备数据然后上传。
数据准备
首先,从“第 10 章”,“使用 R-CNN,SSD 和 R-FCN 进行对象检测”,和“第 11 章”,“通过 CPU/GPU 优化在边缘设备上进行深度学习”的 Google Colab 项目中复制 TFRecord 文件(即train.record
和test.record
),并将其放入 PC 上的目录中。 同样,将label_map.pbtxt
复制到同一目录中的pbtxt
文件中。
数据上传
在这里,我们将看一下使用终端的数据上传方法:
- 借助以下命令,我们将
train.record
上传到 GCP。 这将使用gsutil
Python 命令将文件从本地目录复制到 GCS 存储桶。 确保还包括该子目录。 例如,在这种情况下,YOUR_GCS_BUCKET
将是您的存储桶的名称; 如果为burgerfries
,则命令将为burgerfries/data</code>,其中<code>data</code>是<code>burgerfries</code>下的子目录,文件存储在其中:</li></ol><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> gsutil -m cp -r /Documents/chapter12_cloud_computing/burgerfries/annotation/train.record gs://${YOUR_GCS_BUCKET}/data/
Copying file:///Documents/chapter12_cloud_computing/burgerfries/annotation/train.record [Content-Type=application/octet-stream]...
\ [1/1 files][ 2.6 MiB/ 2.6 MiB] 100% Done- 接下来,以下命令将用于将
test.record
上传到 GCP:
代码语言:javascript复制gsutil -m cp -r /Documents/chapter12_cloud_computing/burgerfries/annotation/test.record gs://{YOUR_GCS_BUCKET}/data/
Copying file:///Documents/chapter12_cloud_computing/burgerfries/annotation/test.record [Content-Type=application/octet-stream]...
\ [1/1 files][ 1.1 MiB/ 1.1 MiB] 100% Done
Operation completed over 1 objects/1.1 MiB.- 以下命令将帮助我们将
label_map.pbtxt
上传到 GCP:
代码语言:javascript复制gsutil -m cp -r /Documents/chapter12_cloud_computing/burgerfries/annotation/label_map.pbtxt gs://{YOUR_GCS_BUCKET}/data/
Copying file:///Documents/chapter12_cloud_computing/burgerfries/annotation/label_map.pbtxt [Content-Type=application/octet-stream]...
/ [1/1 files][ 75.0 B/ 75.0 B] 100% Done
Operation completed over 1 objects/75.0 B.如果您不使用终端,则只需使用 Google Cloud 存储桶中的 Upload 命令上传文件,如“使用 GCP API”部分的屏幕截图所示。
model.ckpt
文件在本节中,我们将学习如何下载预训练模型的检查点文件。 检查点是模型的权重。 这些权重将被上传到 GCS 存储桶,以使用迁移学习来开始训练:
- 转到 TensorFlow Model Zoo GitHub 页面并下载适当的
model.tar
文件。 - 以下是我们下载的相应文件的解压缩版本:
代码语言:javascript复制ssd_mobilenet_v1_0.75_depth_300x300_coco14_sync_2018_07_03.tar.gz
检查点捕获模型使用的所有参数的确切值。 解压缩文件时,您会注意到文件类型如下:
model.ckpt.data-00000-of-00001
:一个二进制数据文件,其中包含训练变量权重,梯度等的值model.ckpt.index
:描述每个检查点的索引值的二进制文件model.ckpt.meta
:描述保存的图结构; 它是一个协议缓冲区Checkpoint
:记录最新的检查点文件
模型配置文件
模型
config
文件是一个文本文件,定义了模型的以下重要特征:- 模型名称
- 类别数
- 图像最小/最大尺寸
- 模型参数
- 检查点,TFRecord 和
map.pbtxt
的位置
在训练期间,模型使用
config
文件输入和设置参数。 您可以在 TensorFlow 目录中的以下路径下找到config
文件的列表:代码语言:javascript复制models-master/research/object-detection/samples/configs
请注意,在撰写本文时,仅在 TensorFlow 1.x 中提供了先前的目录,而在 2.x 中则没有。 因此,如果您的 PC 上安装了 TensorFlow 2.0,请使用下面讨论的替代步骤来获取
config
文件。或者,您可以转到这里,然后在文本编辑器中复制
config
文件。 也可以从前面的链接下载相应的.config
文件。以下列表显示了
config
文件中需要进行的更改:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8b4ZlGUO-1681784662646)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/0dc98ffc-6a1c-4f80-b1f8-22e5f52388e3.png)]
在前面的列表中,所有更改都用矩形标记。 左侧列表显示原始
config
文件,右侧列表显示更改的config
文件。 这里,假设TFRecord
文件名是train.record
和test.record
,pbtxt
文件名是label_map.pbtxt
,并且 Google 存储驱动器中的路径是krish_burgerfries/data
。 如果文件名或路径不同,则可以进行相应更改。现在,通过在终端中键入以下命令转到 TensorFlow
research
目录:代码语言:javascript复制$cd models-master/research
有关包对象检测 API,
pycocotools
和tf-slim
的信息,请参见以下命令:代码语言:javascript复制models-master/research$ bash object_detection/dataset_tools/create_pycocotools_package.sh /tmp/pycocotools models-master/research$ python setup.py sdist models-master/research$ (cd slim && python setup.py sdist)
在云端训练
完成上述所有步骤后,我们将准备进行训练。 如前所述,通过执行以下命令在终端中开始训练:
- 该命令很长,但是将其复制到文本编辑器,仅将
{YOUR_GCS_BUCKET}
更改为burgerfries
(在您的情况下,如果名称不同,则将其更改为该名称)。 完成后,将其粘贴到终端中并点击Enter
:
代码语言:javascript复制$ gcloud ml-engine jobs submit training `whoami`_object_detection_`date +%s` --job-dir=gs://${YOUR_GCS_BUCKET}/train --packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz,/tmp/pycocotools/pycocotools-2.0.tar.gz --module-name object_detection.model_tpu_main --runtime-version 1.15 --scale-tier BASIC_TPU --region us-central1 -- --model_dir=gs://${YOUR_GCS_BUCKET}/train --tpu_zone us-central1 --pipeline_config_path=gs://${YOUR_GCS_BUCKET}/data/pipeline.config
- 与训练一样,在以下命令的帮助下执行验证。 该命令又很长,但是将其复制到文本编辑器,仅将
{YOUR_GCS_BUCKET}
更改为burgerfries
(在您的情况下,如果名称不同,则将其更改为该名称)。 完成此操作后,将其粘贴到终端中,然后单击Enter
:
代码语言:javascript复制$ gcloud ml-engine jobs submit training `whoami`_object_detection_eval_validation_`date +%s` --job-dir=gs://${YOUR_GCS_BUCKET}/train --packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz,/tmp/pycocotools/pycocotools-2.0.tar.gz --module-name object_detection.model_main --runtime-version 1.15 --scale-tier BASIC_GPU --region us-central1 -- --model_dir=gs://${YOUR_GCS_BUCKET}/train --pipeline_config_path=gs://${YOUR_GCS_BUCKET}/data/pipeline.config --checkpoint_dir=gs://${YOUR_GCS_BUCKET}/train
- 训练开始后,您可以通过执行以下命令来评估训练工作:
代码语言:javascript复制$ gcloud ai-platform jobs describe krishkar_object_detection_1111111111
在此,末尾的数字对于您的应用将有所不同,并将在终端中显示出来。 键入前面的命令后,您可以在这个页面中检查训练作业。
请注意,URL 的
xxxxx
和1111111111
部分只是示例; 您的值将有所不同,并会在终端中显示出来。在 TensorBoard 中查看模型输出
在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN”进行对象检测中,我们学习了如何使用 Google Colab 在 TensorBoard 中查看 TensorFlow 模型输出结果。 在本节中,我们将向您展示如何通过在终端中执行命令从云平台启动 TensorBoard:
- 让我们从终端中输入以下命令开始:
代码语言:javascript复制tensorboard --logdir=gs://${YOUR_GCS_BUCKET}/train
运行上述命令后,如果遇到错误,例如
ValueError: Duplicate plugins for name projector
,则从这里并将其保存到您的目录中。- 在终端中,转到
diagnose_tensorboard.py
的安装目录并执行以下命令:
代码语言:javascript复制$ python diagnose_tensorboard.py
它将运行并提供可能的修复建议。 就我而言,它要求以下修复:
代码语言:javascript复制### Suggestion: Fix conflicting installations
"Conflicting package installations found. Depending on the order of installations and uninstallations, behavior may be undefined. Please uninstall ALL versions of TensorFlow and TensorBoard, then reinstall ONLY the desired version of TensorFlow, which will transitively pull
in the proper version of TensorBoard. (If you use TensorBoard without TensorFlow, just reinstall the appropriate version of TensorBoard directly.)Namely:
pip uninstall tb-nightly tensorboard tensorflow-estimator tensorflow-estimator-2.0-preview tensorflow-gpu tf-nightly-gpu-2.0-preview
pip install tensorflow # or
tensorflow-gpu
, ortf-nightly
, ..."- 根据建议执行命令,TensorBoard 将正常工作。
- 导航到
localhost:6006
以查看 TensorBoard 结果。
在 TensorBoard 中,您将看到所用神经网络的图以及在测试图像上显示边界框的图像。 请注意,在 TensorFlow 中,我们没有上传图像,但是它是从
TFRecord
文件获取图像的。 TensorBoard 还显示准确率和精度数据,如下所示:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V8KG4dPK-1681784662646)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/1299acd6-8cd6-4a62-962a-73b8b3b0fcfd.png)]
精度数据不高,但可以通过添加更多图像来改进-在我们的示例示例中,我们仅使用 68 张图像进行训练。
现在我们已经创建了模型并观察了其输出,在下一部分中,我们将描述如何打包模型,以便您可以将其部署在边缘设备(例如手机)上以进行实时显示。 在此处打包模型意味着冻结模型,这意味着该模型不再受训练。
模型输出和到冻结图的转换
到目前为止,我们已经学习了如何将 TFRecord 格式的图像上传到 GCP,然后使用 SSD MobileNet 模型来训练针对汉堡和薯条的自定义模型。 在本节中,我们将回顾模型输出的组成部分,并学习如何冻结模型。 冻结模型涉及以某种格式保存 TensorFlow 图和权重,以后可用于推断。 模型输出存储在
train
文件夹中,并且包含以下文件:graph.pbtxt
:这是一个文本文件,描述了 TensorFlow 图上每个节点的值,列表和形状model.ckpt-xxxx.data-00000-of-00001
:这是一个二进制文件,指示所有变量文件的值model.ckpt-xxxx.index
:这是一个代表表的二进制文件,其中每个键是张量的名称及其值model.ckpt-xxxx.meta
:这描述了保存的图结构train_pipeline.config
:此文本文件描述了模型参数-在模型配置文件的前两个部分中也有说明
请注意,在前面的步骤中,我仅以
xxxx
为例。 您的值将有所不同。 输入该信息而不是xxxx
。抓取最新的数据文件(单击鼠标右键并下载),因此,在本示例中,抓取包含
-2000
的文件。下一个任务是将检查点输出转换为冻结的推理图。 下节介绍了三种方法:
- 从 TensorFlow Core 执行
freeze_graph.py
:
代码语言:javascript复制$ python freeze_graph.py --input_graph=train_graph.pbtxt -- input_checkpoint=train_model.ckpt-2000 -- output_graph=frozen_graph.pb --output_node_name=softmax
- 从 TensorFlow Python 工具执行
freeze_graph
:
代码语言:javascript复制import tensorflow as tf
from tensorflow.python.tools import freeze_graph
checkpoint_path = './'+'train_model'+'.ckpt-2000'
freeze_graph.freeze_graph('train_graph.pbtxt', "", False, checkpoint_path, "output/softmax", "save/restore_all", "save/Const:0",'frozentensorflowModel.pb', True, "")对于上述两种方法,我们都会得到两种类型的错误:
代码语言:javascript复制IndexError: tuple index out of range
AttributeError: module 'tensorflow_core.python.pywrap_tensorflow' has no attribute 'NewCheckpointReader'- 从终端在
tflite graph.py
上执行export
函数,然后下载相关文件:
代码语言:javascript复制export CONFIG_FILE=gs://{YOUR_GCS_BUCKET}/data/pipeline.config
export CHECKPOINT_PATH=gs://{YOUR_GCS_BUCKET}/train/model.ckpt-2000
export OUTPUT_DIR=/tmp/tflite</code></pre></div></div><ol class="ol-level-0"><li>然后,根据这个页面中的描述,从 Docker 文件在终端中执行以下命令。</li></ol><p>Docker 是一种虚拟机,使开发人员可以将应用及其所有组件打包在一起。 对于 TensorFlow,使用 Docker 的优势是将 TensorFlow 安装与 PC 操作系统隔离。 这种隔离消除了我们之前观察到的许多与 TensorFlow 相关的错误:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> python object_detection/export_tflite_ssd_graph.py
--pipeline_config_path=$CONFIG_FILE
--trained_checkpoint_prefix=$CHECKPOINT_PATH
--output_directory=$OUTPUT_DIR
--add_postprocessing_op=true在以下部分中,我们将描述“第 11 章”,“在具有 CPU/GPU 优化功能的边缘设备上进行深度学习”提及的
tflite
转换过程。从 Google Colab 执行导出 tflite
graph.py
在“第 10 章”,“使用 R-CNN,SSD 和 R-FCN 的对象检测”和“第 11 章”,“在具有 CPU/GPU 优化的边缘设备上进行深度学习”,我们使用 Google Colab 将检查点转换为冻结图。 我们将在此处使用相同的方法,除了我们将导入配置,检查点和输出目录,如下所示:
代码语言:javascript复制CONFIG_FILE = '/content/sample_data/train_pipeline.config'
CHECKPOINT_PATH = '/content/sample_data/train_model.ckpt-2000'
OUTPUT_DIR = '/content/sample_data'将文件上传到 Google 云端硬盘,然后将其拖到 Google Colab 中名为
sample_data
的文件夹中。 您可以创建一个不同的名称来代替sample_data
。 之后,执行以下代码:请注意,如果您没有通过将文件拖到 Google Colab 中来携带文件,而是将 Google Colab 链接到文件所在的 Google 云端硬盘,则可能会产生错误,因为在此期间无法找到文件来执行。
代码语言:javascript复制import re
import numpy as np
!python /content/models/research/object_detection/export_tflite_ssd_graph.py
--input_type=image_tensor
--pipeline_config_path={CONFIG_FILE}
--output_directory={OUTPUT_DIR}
--trained_checkpoint_prefix={CHECKPOINT_PATH}
--add_postprocessing_op=true可以在以下 GitHub 链接中找到此转换的代码。
因此,总而言之,下图表示在 GCP 上训练自定义对象检测器的流程图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrJbWqvp-1681784662646)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/771c10ac-1d93-40f9-947b-66b2d1e90f73.png)]
首先创建一个项目,然后创建账单,设置 API 和存储桶,准备 TensorFlow 对象检测 API,准备和上传数据集,然后开始训练。 虚线矩形内的两个圆角矩形表示完成同一任务的两种不同方法。 训练完成后,涉及的步骤包括生成冻结图,转换
tflite
表单并部署到移动设备。 部署到移动设备的过程与“第 11 章”,“具有 CPU/GPU 优化功能的边缘设备上的深度学习”中的方法相同,因此在此不进行描述。在 AWS SageMaker 云平台中训练对象检测器
AWS 是用于在云中执行各种任务的 Amazon 云平台。 AWS SageMaker 是机器学习平台,用于使用 AWS 交互式平台训练和部署模型。 AWS SageMaker 与 AWS S3 存储桶进行交互以存储和检索数据。 下一节将介绍训练对象检测器的分步过程。
设置 AWS 账户,账单和限额
通过与 AWS 支持联系,将服务限制增加到
ml.p3.2xlarge
或类似的值。 请注意,实例类型最多可能需要两个工作日才能获得批准,因此请进行相应的计划。 如果不这样做,则会出现以下错误:代码语言:javascript复制ResourceLimitExceeded
用于训练作业使用情况的帐户级别服务限制
ml.p3.2xlarge
为零实例,当前利用率为零实例,请求增量为一个实例。 请联系 AWS 支持以请求增加此限制。将
.xml
文件转换为 JSON 格式AWS SageMaker 标注数据使用 JSON 格式而不是我们之前使用的
.xml
。 通过以下步骤将.xml
文件转换为 COCO JSON 格式:- 从这里下载或克隆存储库。
- 克隆存储库并下载后,进入终端
voc2coco.py
Python 文件所在的目录。 - 创建一个名为
trainxml
的目录,其中包含所有.xml
文件。 该目录应与voc2coco.py
位于相同的主目录中。 - 在同一主目录中,创建一个名为
trainlist.txt
的文件,该文件应列出所有.xml
文件名。 您可以在终端中复制此文件,然后将所有.xml
文件复制并粘贴到文本文件中以创建此类文件。 - 接下来,创建一个
classname.txt
文件,该文件应列出training
文件夹中的所有类。 在此示例中,它将有两行-burger
和fries
。 - 然后,从主目录下的终端运行 Python 代码,如下所示:
代码语言:javascript复制$ python voc2coco.py --ann_dir trainxml --ann_ids trainlist.txt --labels classname.txt --output train_cocoformat.json
最终输出是
cocoformat.JSON
文件,它是所有.xml
文件的一个组合 JSON 文件。- 将
COCO JSON
文件转换为单个 JSON 文件。 - 然后,使用
Chapter12_cocojson_AWSJSON_train.ipynb
Jupyter 笔记本将COCO JSON
文件转换为单个 JSON 文件。 可以在这个页面上找到此文件。 这是对 Amazon 提供的对象检测代码的修改。 此代码不是从 GitHub 页面获取COCO JSON
文件,而是从本地驱动器获取上一步中创建的cocoformat.JSON
文件,然后将其转换为生成的文件夹中的多个.JSON
文件。
将数据上传到 S3 存储桶
S3 存储桶是用于在 AWS 中存储数据的云存储容器。 本节介绍如何将数据从我们的 PC 上传到 S3 存储桶:
- 创建一个主文件夹以指示项目数据。
- 在该文件夹中,上传四个文件和一个输出文件夹,如下所示:
train_channel
:train
图片.jpg
文件train_annotation_channel
:train
标注.JSON
文件。 每个文件对应于每个train
图像。validation_channel
:validation
图片.jpg
文件validation_annotation_channel
:validation
标注.JSON
文件。 每个文件对应于每个validation
图像。
- 创建一个输出文件夹来存储检查点和输出模型文件。
创建笔记本实例并开始训练
让我们按照以下步骤操作:
- 选择实例类型(选择用于加速计算的实例,例如
ml.p2.nxlarge
,其中n
可以为 1、2、8,依此类推)。 请注意,如果实例类型是标准类型(例如ml.m5.nxlarge
)或计算优化型(例如ml.c5.nxlarge
),则训练将失败。 因此,如前所述,请求增加服务限制。 - 选择最大运行时间-从 1 小时开始,对于非常大的作业,增加它。
- 为前面描述的四个通道中的每个通道分配一个到 S3 存储桶的路径,以便算法知道从何处提取数据。
- 将路径分配到前面提到的输出文件夹。 在前面的代码块中显示了输出路径的示例。 在这种情况下,
sample1
是 S3 存储桶名称,DEMO
是其中包含sample1
的文件夹,其中有六个文件夹-两个数据文件夹,其中包括.jpg
图像,两个标注文件夹由.json
文件,输出和检查点文件组成。 请注意,路径必须正确; 否则,可能会产生错误:
代码语言:javascript复制s3://sample1/DEMO/s3_train_data/ s3:// sample1/DEMO/s3_train_annotation/ s3:// sample1/DEMO/s3_validation_data/ s3:// sample1/DEMO/s3_validation_annotation/ s3:// sample1/DEMO/s3_checkpoint/ s3:// sample1/DEMO/s3_output_location/
- 通过 Python 笔记本或通过训练 API 设置训练。
- 训练结束后,输出将存储在先前代码中定义的
s3_output_location
中,作为model.tar.gz
文件。 检查点将存储在前面代码中定义的s3_checkpoint
位置。 - 下一步将是建立推理模型。 AWS 拥有详细的推理分步说明,可在这个页面中找到。
修复训练中的一些常见故障
以下是一些在训练过程中失败的原因及其解决方法:
- 故障 1 - s3 存储桶相关问题:在输入数据源中给定的
s3://DEMO-ObjectDetection/s3_train_data/
S3 URL 上找不到 S3 对象。 请确保存储桶位于所选区域(us-east-1
)中,对象存在于该 S3 前缀下,并且arn:aws:iam::11111111:role/service-role/AmazonSageMaker-ExecutionRole-xxxxxxx
角色对DEMO-ObjectDetection
存储桶具有s3:ListBucket
权限。 或者,来自 S3 的The specified bucket does not exist
错误消息。 解决方案:更改 S3 存储桶路径,如前所述。 对train
,validation
,annotation
和image
数据文件各重复一个。 - 故障 2 - 批量大小问题:
ClientError
:validation
集没有足够的带标注文件。 请确保带有有效标注的文件数量大于mini_batch_size
,并且实例中的 GPU 数量更大。 解决方案:要记住的重要一点是批量大小必须小于validation
文件的数量。 因此,如果validation
文件的数量为 32,批量大小为 32,则将微型批量大小从 32 更改为 12,以解决此错误。 - 故障 3 - 内容类型问题:
ClientError
:无法初始化算法。train_annotation
通道的ContentType
为空。 请为train_annotation
频道设置内容类型(由KeyError
引起)。 由u'train_annotation'
引起。 解决方案:确保内容类型不为空白。 将内容类型更改为application/x-image
。 - 故障 4 - 通道命名问题:
ClientError
:无法初始化算法。 无法验证输入数据配置(由ValidationError
引起)。 由u'train'
引起的是必需属性。 无法验证架构中的u'required'
:{u'$schema'
:u'http://json-schema.org/draft-04/schema#', u'additionalProperties':
False
,u'definitions': {u'data_channel': {u'properties': {u'ContentType': {u'type': u'string'}
,u'RecordWrapperType': {u'enum': [u'None', u'RecordIO'], u'type': u'string'}, u'S3DistributionType': {u'enum': [u'FullyReplicated', u'ShardedByS3Key'], u'type': u'string'}
。 解决方案:AWS 希望通道名称为train_validation
,train_annotation
和validation_annotation
。 如果您附加了_channel
(train_channel
,validation_channel
,train_annotation_channel
和validation_annotation_channel
),则将导致错误。 因此,要解决此问题,请从文件名中删除_channel
。
如果在此过程中遇到问题,请通过创建故障单来联系 AWS 支持人员。 解决所有错误后,成功的训练将具有以下参数:
base_network
是resnet-50
early_stopping
是false
early_stopping_min_epochs
是10
early_stopping_patience
是5
early_stopping_tolerance
是0.0
epochs
是30
freeze_layer_pattern
是false
image_shape
是300
label_width
是350
learning_rate
是0.001
lr_scheduler_factor
是0.1
mini_batch_size
是12
momentum
是0.9
nms_threshold
是0.45
num_classes
是2
num_training_samples
是68
optimizer
是sgd
overlap_threshold
是0.5
use_pretrained_model
是1
weight_decay
是0.0005
请注意,训练的输出将与检查点一起保存在 S3 输出位置。
完成上述练习后,您将熟悉在 GCP 和 AWS 中训练神经网络模型。 接下来,我们将使用 Microsoft Azure 云平台进行训练。
在 Microsoft Azure 云平台中训练对象检测器
在本节中,我们将使用 Azure 自定义视觉来训练对象检测器。 可以在这个页面中找到有关使用 Microsoft Azure 云平台训练对象检测器的详细说明:。
下一节将详细介绍训练对象检测器时的各种过程。
创建一个 Azure 帐户并设置 Custom Vision
在本节中,我们将设置一个 Azure 帐户和一个 Azure Custom Vision 平台。 以下步骤将帮助您配置 Azure 帐户并注册 Custom Vision 平台。 如针对 GCP 所述,此过程对于任何云平台都是相同的-设置帐单信息并设置项目-如以下屏幕快照所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RvNSTbT4-1681784662646)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/18daf432-57e5-48ea-9197-7a17a673a4b8.png)]
设置训练的具体步骤如下:
- 注册一个 Microsoft 帐户并设置帐单信息。 在撰写本文时,Microsoft 将免费为美国地区的首次用户提供 200 美元的赠金(请针对您所在的地区进行检查)。
- 设置订阅。 在“订阅”选项卡中,单击“添加”,然后为您的订阅命名并设置帐单信息。
- 设置项目,然后选择并创建项目,并为其命名。
- 设置资源,然后从菜单中选择“资源”组。
- 选择“对象检测”,然后完成所有这些操作,然后使用“Custom Vision”创建对象检测。
设置帐户设置是非常重要的部分,如果操作不正确,将花费相当长的时间。 设置帐户后,接下来的步骤实际上将很快进行。
上传训练图像并标记它们
在本节中,我们将训练图像上传到 Azure Custom Vision 平台。 按着这些次序:
- 单击“添加图像”,然后添加所有
train
和validation
图像。 - 添加它们后,您的图像将显示在未标记的部分。
- 请注意,您将无处上载在先前项目中创建的标注
.xml
或.JSON
文件,但不要担心,Azure 使标记图像非常简单。 - 首先,请标注大约 10%(或大约 20)的图像。 您会注意到,即使在此之前,边界框也会自动转到感兴趣的对象,您要做的就是调整其大小。 如果找不到对象,请添加边界框并编写相应的类。 以下屏幕截图显示了智能标签选项:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiDeXjPe-1681784662647)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/43aff5f4-c9b9-4b3a-84e5-21ad7115bd41.png)]
- 标记图像后,它们将移至标记的部分。 在标记了 10%(或大约 20)张图像后,请对这些图像进行快速训练。 训练完成后,返回未加标签的图像,然后使用智能贴标签器选项标记所有未加标签的图像。
- 执行上一步后,您会注意到许多图像将被自动标记。 如果您认为标签正确无误,请接受更改,然后调整边界框的大小和位置。 如果图像具有多个类别,并且智能标签仅捕获其中的几个类别,请手动标记其他类别。 用这种方法标注大约 100 张图像后,就可以开始训练(如果有更多图像,则进行快速训练,如果最大图像数为 100,则进行高级训练),然后使用新生成的模型来训练其他图像。
- 继续前面的过程,直到所有图像都被标记。 然后,开始训练并使用高级训练选项。 以小时为单位设置时间(从 1 小时开始),以后再根据需要增加时间。 在云端的训练非常快-在不到 10 分钟的时间内即可训练约 100 张图像。
训练完成后,您将能够看到表现指标。 请注意,在上述快速训练之后,您将能够看到此内容。 以下屏幕截图显示了针对新训练的模型的精度,召回率和 mAP 方面的表现参数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEWeFnji-1681784662647)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/08e3cdba-f27b-48a0-b2bc-a781720d41c9.png)]
请注意,随着模型看到的图像越来越多,上一个屏幕快照中显示的 Precision 值可能会降低。 因此,在 20 张图像上开发的模型比在 100 张图像上开发的模型具有更高的精度。 这是因为在 20 张图像上开发的模型具有较少的训练误差,但具有较高的测试误差(在
test
图像中,无法识别汉堡-仅识别薯条)。 mAP 数是 11 个等距召回级别(0,0.1,…,1)上的平均平均精度。 mAP 值不受图像添加的影响。Performance
参数显示burger
和fries
的值。- 现在,让我们带回旧的
validation
图像并查看结果。 为此,请单击顶部的“预测”,然后插入validation
图像。 它将在类周围绘制一个边界框,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eza1NNI8-1681784662647)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/f4081282-39a6-4a90-9178-05b09c7064ed.png)]
- 如图所示,预测是正确的。 接下来,我们将导出模型。 为此,请单击“导出”,如以下屏幕截图所示。 请注意,如果单击
TF
,则可以选择导出为 TensorFlow Lite 或 TensorFlow。 同样,如果您单击iOS
,则可以选择导出为 CoreML:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-liLKQpbF-1681784662647)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/1e616edb-4ec6-4f40-94ce-48dd5a30ed0e.png)]
上面的屏幕截图显示了 TensorFlow Lite 中可用的各种导出选项。
大规模训练和包装
TensorFlow 有一个名为
tf.distribute.Strategy
的 API,可在多个 GPU 之间分配训练。 在这个页面上详细介绍了针对 Google Cloud 的大规模训练。使用
tf.distribute.Strategy
API 涵盖了使用 TensorFlow 进行分布式训练。 使用此 API,可以使用多个 GPU 或 TPU 分发 TensorFlow 训练。 有关分布式训练的详细概述(包括示例),请访问这里。也可以在云计算引擎中设置分布式训练。 为了启用此功能,请在 GCP 中启用 Cloud Shell。 在 TensorFlow 集群中,设置一个主服务器和多个工作程序的虚拟机实例,并在每个这些计算机上执行训练作业。 有关详细信息,您可以转到这里。
应用包装
应用打包涉及将代码,
TFRecord
文件和模型.confg
文件上传到 GCP,模型在训练期间可以访问。 在“在 GCP 中训练对象检测器”的部分中,我们通过使用gcloud
打包应用在 GCP 中进行了训练,如下所示:代码语言:javascript复制$ gcloud ml-engine jobs submit training `whoami`_object_detection_`date +%s` --job-dir=gs://${YOUR_GCS_BUCKET}/train --packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz,/tmp/pycocotools/pycocotools-2.0.tar.gz --module-name object_detection.model_tpu_main --runtime-version 1.15 --scale-tier BASIC_TPU --region us-central1 -- --model_dir=gs://${YOUR_GCS_BUCKET}/train --tpu_zone us-central1 --pipeline_config_path=gs://${YOUR_GCS_BUCKET}/data/pipeline.config
请注意,在前面的训练中,我们使用了
gcloud ml-engine
,它可以让您管理 AI 平台作业和训练模型。 还有另一个名为gcloud ai-platform
的平台,也可以用来打包您的应用,如下所示:代码语言:javascript复制gcloud ai-platform jobs submit training $JOB_NAME \ --staging-bucket $PACKAGE_STAGING_PATH \ --job-dir $JOB_DIR \ --package-path $TRAINER_PACKAGE_PATH \ --module-name $MAIN_TRAINER_MODULE \ --region $REGION \ -- \
--user_first_arg=first_arg_value
--user_second_arg=second_arg_value前面的代码的解释如下:
--staging-bucket
:这是暂存training
包的云存储路径--job-dir
:这是输出文件位置的云存储路径--package-path
:这指定应用目录的本地路径--module-name
:这指定应用模块的名称--job-dir
标志:这是作业目录
基于云的视觉搜索背后的总体思路
在 “第 6 章”,“使用迁移学习的视觉搜索”中,我们学习了如何在本地 PC 上进行视觉搜索。 该方法使用通过神经网络(例如 VGG16 或 ResNet)传递图像,并通过删除最后一个全连接层然后将其与数据库中已知类别的其他图像进行比较以将其转换为图像向量,以找到最近的邻居。 匹配,然后显示结果。
在示例中,我们从 200 张图像开始,但是如果图像数量达到 100 万张并且必须从网页访问结果,则在本地存储图像将毫无意义。 在这些情况下,云存储是最佳的。 在那种情况下,我们可以将图像向量存储,而不是将图像存储在云中,然后在用户上传图像时,将图像转换为向量并将其发送到云中进行处理。 在云中,我们执行 K 近邻搜索以找到并显示最接近的匹配项。 使用 REST API 或消息队列遥测传输(MQTT)服务将图像向量上传到云中。 每个服务都有自己的安全性验证。
在这里,我们将讨论将图像发送到云服务并以 JSON 消息形式接收的基本编码基础架构:
- 客户端请求基础结构:以下代码描述了如何将图像 URL 作为 POST 请求发送到外部 Web 服务器。 此处,
api_host
是 Web 服务器地址。headers
文件是操作参数,在这种情况下为图像。image_url
是实际的图像位置:
代码语言:javascript复制api_host = 'https://…/'
headers = {'Content-Type' : 'image/jpeg'}
image_url = 'http://image.url.com/sample.jpeg'
img_file = urllib2.urlopen(image_url)
response = requests.post(api_host, data=img_file.read(),
headers=headers, verify=False)
print(json.loads(response.text))- 服务器端请求的基础结构:以下代码描述了典型的服务器端代码。 数据库侧的服务器将使用
request.files.get
方法请求图像(图片),并且picture.save
用于保存图像:
代码语言:javascript复制@app.route('/', methods=['POST'])
def index():
picture = request.files.get('file')
picture.save('path/to/save')
return 'ok', 200前面的代码架构展示了 REST API 方法从云发送和接收图像的基础。 GCP,AWS 和 Azure 具有适当的 API,可以执行视觉搜索,面部识别和许多其他任务。 在以下部分中,将对此进行详细描述。 每个云平台都有自己的向云发送图像数据的方式,这可能彼此不同,但是基本原理与前一个相同。 云网页将以 JSON 格式包含具有可视搜索结果的图像信息,该图像信息可以使用云服务器 URL 和认证方法从本地 PC 访问。
分析各种云平台中的图像和搜索机制
在本节中,我们将讨论使用三种不同的云平台(GCP,AWS 和 Azure)的可视搜索任务。 我们已经在“第 6 章”,“使用迁移学习进行视觉搜索”中,其中我们学习了如何将图像向量与 PC 目录中的大量图像进行比较,来查找基于欧几里得距离的最接近的匹配。 在本部分中,您将学习如何使用 REST API 从 PC 上载图像到云,云搜索引擎将搜索最接近的图像并将其显示。 因此,所有繁重的工作将由云引擎来完成。
请注意,在本节中,介绍了视觉搜索的基本概念。 内容可以更深入,您可以从 GCP,AWS 或 Azure 获取云 API,并将其插入用 Python,C++ 或 JavaScript 编写的应用中,以调用云引擎并执行搜索。
使用 GCP 的视觉搜索
GCP 具有视觉 API,可以执行基于云的图像信息,包括面部检测和图像内容分析。 有关更多详细信息,请访问这里。 在以下屏幕截图中查看为沙发上传的示例结果; 检测连同视觉上类似图像的几个示例一起进行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iR4weSm3-1681784662647)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/5b0384ab-24ec-41f1-acbc-c5dc5d54730d.png)]
正如我们在“第 6 章”,“使用迁移学习进行视觉搜索”时一样,对于视觉上相似的图像,必须在图像类内进行搜索。 如果图像不是来自网络,则很可能会检测到不同类别的相似视觉图像,如此处的沙发示例所示。 但是,如果图像是从网上获取的,则匹配是精确的或非常接近的。
在上一节中,我们学习了如何使用 GCP 进行训练。 AutoML Vision 是轻松完成此任务的另一种方法。 有关详细的分步说明,请转到这里。
要进行视觉搜索,请转到这里。
当您尝试使用 Python 脚本中的 API 时,您将需要以下内容:
- 一个 Google Cloud 帐户,用于设置项目并启用计费。
- 启用 Cloud Vision 产品搜索 API。
- Google 应用凭据 - 密钥文件。
- 选择一个服务帐户并创建它,以便将密钥下载到您的 PC。
- 通过导出以下三个项目在终端中设置环境变量:
GOOGLE_APPLICATION_CREDENTIAL
:PC 中的关键路径PROJECT_ID
LOCATION_ID
- 创建
request.json
,然后您将收到一个response.json
文件。
使用 AWS 的视觉搜索
AWS 有许多用于计算机视觉的工具。 其中,两个主要工具是 Amazon Rekognition 和 AWS SageMaker。访问 AWS 网站以获取更多满足您需求的工具。 AWS Rekognition 是用于图像和视频分析的基于云的软件即服务(SaaS)平台。 它具有许多功能,例如面部检测和分析,面部搜索和验证以及名人识别。 就像 Google Cloud Vision API 一样,您可以上传图像,它可以提供图像信息的详细信息,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-76CguLCo-1681784662648)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/f1ec323c-a06f-49f0-8be7-fd520d866ed4.png)]
在前面的屏幕截图中,正确检测了沙发以及不同的类别以及边界框和图像信息的相应 JSON。 您还可以上传面部图像,它可以提供有关面部表情,年龄和性别的详细信息,以及两个角度不同的面部是否属于同一个人,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Den1Kl8n-1681784662648)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/master-cv-tf-2x/img/e39e0b60-60d7-4f93-819b-290e1117ed5b.png)]
请注意,面部识别系统能够检测到属于同一个人的两张脸,无论有无太阳镜,它们都是从不同角度拍摄的。
AWS Rekognition 还可以使用
boto
分析本地 PC 上的图像,如这里所述。训练期间引入了 AWS SageMaker。 通过将图像转换为向量,它也可以用于执行视觉搜索。 有关详细练习,请参阅这个页面中描述的 Python 笔记本。
请注意,执行此操作的最佳方法是从 AWS SageMaker 笔记本实例运行此操作。 将此文件(在上一链接中列出)上载到 Jupyter 笔记本,然后选择 MXNet Python 包。 引用您的 S3 存储桶并执行单元。 分析代码并将其与我们在“第 6 章”,“使用迁移学习的视觉搜索”中学到的内容进行比较。 您将看到基本原理是相同的,只是分析是在云平台上完成的,因此它将具有在“第 6 章”,“使用迁移学习的视觉搜索”中不必处理的多个认证级别。
使用 Azure 的视觉搜索
Azure 是 Microsoft 的云机器学习平台,用于构建,管理和部署应用。 与 GCP 和 AWS 一样,Azure 具有许多功能,但我们对计算机视觉工作感兴趣的功能是 Azure AI 和 Azure 机器学习。 在 AI 和机器学习中,与计算机视觉相关的应用是 Azure Bot 服务,Azure 认知搜索,Bing 图像搜索,Bing 视觉搜索和计算机视觉。 例如,如果要执行视觉搜索,请转到这里。
在 Azure 云平台中进行可视搜索的基本步骤如下:
- 获取一个 Azure 帐户,然后选择定价信息。
- 获取您的订阅密钥。
- 选择 PC 上
test
图像的路径。 - 以
request.post
的形式发送搜索请求:
代码语言:javascript复制response = requests.post(BASE_URI, headers=HEADERS, files=file)
response.raise_for_status()在前面的代码中,
raise_for_status
方法表示如果请求不成功,则会引发异常,例如404 Client Error: NOT FOUND
。注意-由于必须提供信用卡详细信息进行计费,因此云平台的使用可能会变得昂贵。 要注意的关键是,即使您完成了训练工作并关闭了 PC,除非完全关闭云平台中的项目,否则您将继续产生费用。
总结
在本章中,您学习了如何将图像数据发送到云平台进行分析。 在之前的章节中,我们学习了如何在本地 PC 上进行训练,但是在本章中,您学习了如何使用云平台执行相同的任务,以及如何使用 Google Cloud Shell for distribution 在多个实例中触发训练。
本章包含许多示例和链接,通过查看这些链接并进行练习,您将获得更多知识。 然后,我们学习了如何将图像发送到云平台进行实例分析。 图像内容分析已扩展到可以在云平台中执行可视搜索。 我们还学习了如何使用所有三个云平台-GCP,AWS 和 Azure。 请记住,即使您尚未接受训练,也要确保在完成任务后关闭项目,以免产生不必要的费用。
- 接下来,以下命令将用于将