欢迎关注AI科技大本营掘金专栏,持续获得更多干货内容。
【导读】这是一篇关于使用基于深度学习的目标检测来实现监控系统的快速教程。在教程中通过使用 GPU 多处理器来比较不同目标检测模型在行人检测上的性能。
监控是安保和巡逻的一个组成部分,大多数情况下,这项工作都是在长时间去观察发现那些我们不愿意发生的事情。然而突发事件发生的低概率性无法掩盖监控这一平凡工作的重要性,这个工作甚至是至关重要的。
如果有能够代替我们去做“等待和监视”突发事件的工具那就再好不过了。幸运的是,这些年随着技术的进步,我们已经可以编写一些脚本来自动执行监控这一项任务。在深入探究之前,需要我们先考虑两个问题。
机器是否已经达到人类的水平?
任何熟悉深度学习的人都知道图像分类器的准确度已经赶超人类。图1显示了近几年来对于人类、传统计算机视觉 (CV) 和深度学习在 ImageNet 数据集上的分类错误率。
图 1 人类、深度学习和 CV 在 ImageNet 上分类错误率
与人类相比,机器可以更好地监视目标,使用机器进行监视效率更高,其优点可总结如下:
重复的任务会导致人类注意力的下降,而使用机器进行监视时并无这一烦恼,我们可以把更多的精力放在处理出现的突发事件上面。
当要监视的范围较大时,需要大量的人员,固定相机的视野也很有限。但是通过移动监控机器人 (如微型无人机) 就能解决这一问题。
此外,同样的技术可用于各种不受限于安全性的应用程序,如婴儿监视器或自动化产品交付。
那我们该如何实现自动化?
在我们讨论复杂的理论之前,先让我们看一下监控的正常运作方式。我们在观看即时影像时,如果发现异常就采会取行动。因此我们的技术也应该通过仔细阅读视频的每一帧来发现异常的事物,并判断这一过程是否需要报警。
大家可能已经知道了,这个过程实现的本质是通过目标检测定位,它与分类不同,我们需要知道目标的确切位置,而且在单个图像中可能有多个目标。为了更好的区分我们举了一个简单形象的例子如图2所示。
图2 分类、定位、检测和分割的示例图
为了找到确切的位置,我们的算法应该检查图像的每个部分,以找到某类的存在。自2014年以来,深度学习的持续迭代研究引入了精心设计的神经网络,它能够实时检测目标。图3显示了近两年R-CNN、Fast R-CNN 和 Faster R-CNN 三种模型的检测性能。
图3 R-CNN、Fast R-CNN 和 Faster R-CNN 性能
这里有几种在内部使用的不同方法来执行相同任务的深度学习框架。其中最流行的是 Faster-RCNN、YOLO 和 SSD。图4展示了 Faster R-CNN、R-FCN 和 SSD 的检测性能。
图4 Faster R-CNN、R-FCN 和 SSD 的检测性能,速度与准确性的权衡,更高的 mpA 和更低的 GPU 时间是最佳的。
每个模型都依赖于基础分类器,这极大影响了最终的准确性和模型大小。此外,目标检测器的选择会严重影响计算复杂性和最终精度。在选择目标检测算法时,速度、精度和模型大小的权衡关系始终存在着。
在有了上面的学习了解后,接下来我们将学习如何使用目标检测构建一个简单而有效的监控系统。
我们先从由监视任务的性质而引起的限制约束开始讨论起。
深度学习在监控中的限制
在实现自动化监控之前,我们需要考虑以下几个因素:
1.即时影像
为了在大范围内进行观察,我们可能需要多个摄像头。而且,这些摄像头需要有可用来存储数据的地方 (本地或远程位置)。图5为典型的监控摄像头。
图5 典型的监控摄像头
高质量的视频比低质量的视频要占更多的内存。此外,RGB 输入流比 BW 输入流大3倍。由于我们只能存储有限数量的输入流,故通常情况下我们会选择降低质量来保证最大化存储。
因此,可推广的监控系统应该能够解析低质量的图像。同时我们的深度学习算法也必须在低质量的图像上进行训练。
2.处理能力
在哪里处理从相机源获得的数据是另一个大问题。通常有两种方法可以解决这一问题。
集中式服务器处理
来自摄像机的视频流在远程服务器或集群上逐帧处理。这种方法很强大,使我们能够从高精度的复杂模型中获益。但这种方法的缺点是有延迟。此外,如果不用商业 API,则服务器的设置和维护成本会很高。图6显示了三种模型随着推理时间的增长内存的消耗情况。
图6 内存消耗与推理时间(毫秒),大多数高性能模型都会占用大量内存
分散式边缘处理
通过附加一个微控制器来对相机本身进行实时处理。优点在于没有传输延迟,发现异常时还能更快地进行反馈,不会受到 WiFi 或蓝牙的限制 (如 microdrones)。缺点是微控制器没有 GPU 那么强大,因此只能使用精度较低的模型。使用板载 GPU 可以避免这一问题,但是太过于昂贵。图 7 展示了目标检测器 FPS 的性能。
图 7 各类目标检测器 FPS 的性能
训练监控系统
在接下来的内容里我们将会尝试如何使用目标检测进行行人识别。使用 TensorFlow 目标检测 API 来创建目标检测模块,我们还会简要的阐述如何设置 API 并训练它来执行监控任务。整个过程可归纳为三个阶段 (流程图如图8所示):
数据准备
训练模型
推论
图8 目标检测模型的训练工作流程
▌第1阶段:数据准备
第一步:获取数据集
监控录像是获取最准确数据集的来源。但是,在大多数情况下,想要获取这样的监控录像并不容易。因此,我们需要训练我们的目标检测器使其能从普通图像中识别出目标。
图9 从数据集中提取出带标注的图像
正如前面所说,我们的图像质量可能较差,所以所训练的模型必须适应在这样的图像质量下进行工作。我们对数据集中的图像 (如图9所示) 添加一些噪声或者尝试模糊和腐蚀的手段,来降低数据集中的图片质量。
在目标检测任务中,我们使用了 TownCentre 数据集。使用视频的前3600帧进行训练,剩下的900帧用于测试。
第二步:图像标注
使用像 LabelImg 这样的工具进行标注,这项工作虽然乏味但也同样很重要。我们将标注完的图像保存为 XML 文件。
第三步:克隆存储库
运行以下命令以安装需求文件,编译一些 Protobuf 库并设置路径变量
pip install -r requirements.txt
sudo apt-get install protobuf-compiler
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
复制代码
第四步:准备所需的输入
首先,我们需要给每个目标一个标签,并将文件中每个标签表示为如下所示的 label_map.pbtxt
item {
id: 1
name: ‘target’
}
复制代码
接下来,创建一个包含 XML 和图像文件名称的文本文件。例如,如果数据集中有 img1.jpg, img2.jpg, 和 img1.xml, img2.xml ,则 trainval.txt 文件的表示应如下所示:
img1
img2
复制代码
将数据集分为两个文件夹 (图像与标注)。将 label_map.pbtx 和 trainval.txt放在标注文件夹中,然后在标注文件夹中创建一个名为 xmls 的子文件夹,并将所有 XML 文件放入该子文件夹中。目录层次结构应如下所示:
-base_directory
|-images
|-annotations
||-xmls
||-label_map.pbtxt
||-trainval.txt复制代码
第五步:创建 TF 记录
API 接受 TPRecords 文件格式的输入。使用 creat_tf_record.py 文件将数据集转换为 TFRecords。我们应该在 base directory 中执行以下命令:
python create_tf_record.py \
--data_dir=`pwd` \
--output_dir=`pwd`
复制代码
在该程序执行完后,我们可以获取 train.record 和 val.record 文件。
▌第2阶段:训练模型
第1步:模型选择
如前所述,速度与准确度两者不可得兼,从头开始创建和训练目标检测器是非常耗时的。因此, TensorFlow 目标检测 API 提供了一系列预先训练好的模型,我们可以根据自己的使用情况进行微调,该过程称为迁移学习,它可以大大提高我们的训练速度。
图10 MS COCO 数据集中一组预训练过的模型
从图 10 中下载一个模型,并将内容解压缩到 base directory 中。可获取模型检查点,固定推理图和 pipeline.config 文件。
第2步:定义训练工作
我们必须在 pipleline.config 文件中定义“训练工作”,并将该文件放到 base directory 中。该文件中最重要的是后几行——我们只需将突出显示的值放到各自的位置。
gradient_clipping_by_norm: 10.0
fine_tune_checkpoint: "model.ckpt"
from_detection_checkpoint: true
num_steps: 200000
}
train_input_reader {
label_map_path: "annotations/label_map.pbtxt"
tf_record_input_reader {
input_path: "train.record"
}
}
eval_config {
num_examples: 8000
max_evals: 10
use_moving_averages: false
}
eval_input_reader {
label_map_path: "annotations/label_map.pbtxt"
shuffle: false
num_epochs: 1
num_readers: 1
tf_record_input_reader {
input_path: "val.record"
}
}
复制代码
第3步:开始训练
执行以下命令以启动训练工作,建议使用具有足够大的 GPU 计算机,以便加快训练过程。
python object_detection/train.py \
--logtostderr \
--pipeline_config_path=pipeline.config \
--train_dir=train复制代码
▌第3阶段:推论
第1步:导出训练模型
在模型使用之前,需要将训练好的检查点文件导出到固定推理图上,实现这个过程并不困难,只需要执行以下代码 (用检查点替换“xxxxx”)
python object_detection/export_inference_graph.py \
--input_type=image_tensor \
--pipeline_config_path=pipeline.config \
--trained_checkpoint_prefix=train/model.ckpt-xxxxx \
--output_directory=output
复制代码
该程序执行完后,我们可得到 frozen_inference_graph.pb 以及一堆检查点文件。
第2步:在视频流上使用
我们需要从视频源中提出每一帧,这可以使用 OpenCV 的 VideoCapture 方法完成,代码如下所示:
cap = cv2.VideoCapture()
flag = True
while(flag):
flag, frame = cap.read()
## -- Object Detection Code --
复制代码
第一阶段使用的数据提取代码会使我们的测试集图像自动创建“test_images”文件夹。我们的模型可以通过执行以下命令在测试集上进行工作:
python object_detection/inference.py \
--input_dir={PATH} \
--output_dir={PATH} \
--label_map={PATH} \
--frozen_graph={PATH} \
--num_output_classes=1 \
--n_jobs=1 \
--delay=0
复制代码
实验
正如前面所讲到的,在选择目标检测模型时,速度与准确度不可得兼。对此我们进行了一些实验,测量使用三种不同的模型检测到人的 FPS 和数量精确度。此外,我们的实验是在不同的资源约束 (GPU并行约束) 条件下操作的。
▌设置
我们的实验选择了以下的模型,这些模型可以在 TensorFlow 目标检测API 的Zoo 模块中找到。
Faster RCNN with ResNet 50
SSD with MobileNet v1
SSD with InceptionNet v2
所有的模型都在 Google Colab 上进行了 10k 步训练,通过比较模型检测到的人数与实际人数之间的接近程度来衡量计数准确度。在一下约束条件下测试 FPS 的推理速度。
Single GPU
Two GPUs in parallel
Four GPUs in parallel
Eight GPUs in parallel
结果
下面的 GIF 是我们在测试集上使用 FasterRCNN 输出的片段。
▌训练时间
图11展示了以10 k步 (单位:小时) 训练每个模型所需的时间 (不包括参数搜索所需要的时间)
图11 各模型训练所需时间
▌速度 (每秒帧数)
在之前的实验中,我们测量了3种模型在5种不同资源约束下的 FPS 性能,其测量结果如图12所示:
图12 使用不同 GPU 数量下的 FPS 性能
当我们使用单个 GPU 时,SSD速度非常快,轻松超越 FasterRCNN 的速度。但是当 GPU 个数增加时,FasterRCNN 很快就会追上 SSD 。
为了证明我们的结论:视频处理系统的速度不能高于图像输入系统的速度,我们优先读取图像。图13展示了添加延迟后带有 NobileNet +SSD 的 FPS 改进状况,从图13中可看出当我们加入延迟后,FPS 迅速增加。
图13 增加不同延迟后模型的 FPS 改进状况
▌计数准确性
我们将计数准确度定义为目标检测系统正确识别出人脸的百分比。图14是我们每个模型精确度的表现,从图14中可看出 FasterRCNN 是准确度最高的模型,MobileNet 的性能优于 InceptionNet。
图 14 各模型计数精确度
Nanonets
看到这里相信大家都有一个共同的感受——步骤太多了吧!是的,如果是这样的一个模型在实际工作即繁重又昂贵。
为此,更好的解决方案就是使用已部署在服务器上的 API 服务。Nanonets 就提供了这样的一个 API,他们将 API 部署在带有 GPU 的高质量硬件上,以便开发者不用为性能而困扰。
Nanonets 可以减少工作的流程的方法在于:我将现有的 XML 注释转换成 JSON 格式并提供给 Nanonets API。所以当不想进行手动注释数据集时,可以直接请求 Nanonets API来为数据添加注释。
上图表示为减少后的工作流程
Nanonets 的训练时间大约花了 2 个小时,就训练时间而言,Nanonets 是明显的赢家,并且在准确性方面 Nanonets 也击败了 FasterRCNN。
FasterRCNN Count Accuracy = 88.77%
Nanonets Count Accuracy = 89.66%
复制代码
自动监控的可信度有多高?
深度学习是一种令人惊叹的工具。但是我们在多大程度上可以信任我们的监控系统并自动采取行动?在以下几个情况下,自动化过程时需要引起注意。
▌可疑的结论
我们不知道深度学习算法是如何得出结论的。即使数据的馈送过程很完美,也可能存在大量虚假的成功例子。虽然引导反向传播在一定程度上可以解释决策,但是关于这方面的研究还有待我们进一步的研究。
▌对抗性攻击
深度学习系统很脆弱,对抗性攻击类似于图像的视错觉。计算出的不明显干扰会迫使深度学习模型分类失误。使用相同的原理,研究人员已经能够通过使用 adversarial glasses 来规避基于深度学习的监控系统。
▌误报
另一个问题是,如果出现误报我们该怎么做。该问题的严重程度取决于应用程序本身。例如边境巡逻系统的误报可能比花园监控系统更重要。
▌相似的面孔
外观并不像指纹一样独一无二,同卵双胞胎是最好的一个例子。这会带来恨大的干扰。
▌数据集缺乏多样性
深度学习算法的好坏和数据集有很大关联,Google 曾将一个黑人错误归类为大猩猩。
注:鉴于 GDPR 和以上原因,关于监控自动化的合法性和道德性问题是不可忽视的。此教程也是出于并仅用于学习分享目的。在教程中使用的公开数据集,所以在使用过程中有责任确保它的合法性。
原文链接
https://medium.com/nanonets/how-to-automate-surveillance-easily-with-deep-learning-4eb4fa0cd68d
作者 | Bharath Raj
译者 | 孤鸿
编辑 | Jane
出品 | AI 科技大本营(rgznai100 )