IOS目标检测(翻译)

原文链接:目标检测

目标检测

目标检测是在图片中对目标进行分类和定位。给定一幅图片,检测器会对目标进行预测,如下图所示:
在这里插入图片描述
该模型是用来检测动物面部。并通过圈在目标周围的边界框对目标进行注释

入门实例

在该例子中,目标是预测图片中的汽车和自行车以及它们在图片中的位置(可以跳转到 数据准备 来了解怎么获取 ig02.sframe)

1import turicreate as tc 2 3# Load the data 4data = tc.SFrame('ig02.sframe') 5 6# Make a train-test split 7train_data, test_data = data.random_split(0.8) 8 9# Create a model 10model = tc.object_detector.create(train_data) 11 12# Save predictions to an SArray 13predictions = model.predict(test_data) 14 15# Evaluate the model and save the results into a dictionary 16metrics = model.evaluate(test_data) 17 18# Save the model for later use in Turi Create 19model.save('ig02.model') 20 21# Export for use in Core ML 22model.export_coreml('MyCustomObjectDetector.mlmodel') 23 24

数据采集

这个例子假设数据已经存在了,在我们创建模型之前,我们需要给数据打标签。数据应该是由图片和正确的注释(目标的标签和边界框)组成。我们拥有越多的数据,我们的预测就会越好。预测的数据是要和标记出来的数据一样的,你标记的数据是什么样子,预测出来的数据就会是什么样子。如下图所示:
在这里插入图片描述
在这个例子中,我们选择球和杯子作为识别目标,因此我们会标记球和杯子。在这个场景里,我们不检测水果,所以我们不会标记它们。首先你应该确定要检测哪些类别。如果训练集中的所有类别的目标都需要标记,反而每个类别的样本会变少。然而,你可以尽可能的在图片上标记目标,但是在使用 classes参数传递要create的标签列表时,此列表中未涵盖的目标类别会自动忽略。
上面图片的注释是一个字典类型,每个字典代表一个边界框

1[{'coordinates': {'height': 104, 'width': 110, 'x': 115, 'y': 216}, 2 'label': 'ball'}, 3 {'coordinates': {'height': 106, 'width': 110, 'x': 188, 'y': 254}, 4 'label': 'ball'}, 5 {'coordinates': {'height': 164, 'width': 131, 'x': 374, 'y': 169}, 6 'label': 'cup'}] 7 8

可选项'type': 'rectangle'显示的表明该字典表示边界框。如果定义其他类型,目标检测器将忽略该字典。边界框由四个值(x,y,width,height)定义,其中(0,0)是左上角。边界框的中心是(x,y)。
在这里插入图片描述
习惯上将边界框围绕在检测目标周围。但是,这仅仅只是一个惯例,训练数据的边界框和目标的关系完全取决于你如何标记。如果仅需要预测目标的中心点,那么在训练数据里可以随意设置 widths/heights的值(例如100)。
一张图片中含有多少个边界框取决于你。但是,一定要保持目标概念一致,如果你要检测人,则图片中的每个人都应该被标记,一旦存在某些人没有被标记。模型可能就会不准确,为什么有的人被标记(目标存在),而有些人没有被标记(目标不存在)。如果需要,你完全可以选择没有任何目标,没有任何边界框的图片来作为负类。这可能是减少误报的有效方法。例如,如果你训练一个模型来检测球,并且训练集没有包括其他圆形物体,你可能会发现模型开始给类似于球的物体高置信度。在上面的图片中,即使没有明确标记苹果和橘子,但是它们的存在也有助于防止此类错误。
边界框列表数据存储在图片旁边的SFrame中

1+------------------------+-------------------------------+ 2| image | annotations | 3+------------------------+-------------------------------+ 4| Height: 375 Width: 500 | [{'coordinates': {'y': 204... | 5| Height: 375 Width: 500 | [{'coordinates': {'y': 148... | 6| Height: 334 Width: 500 | [{'coordinates': {'y': 146... | 7| Height: 500 Width: 345 | [{'coordinates': {'y': 321... | 8| Height: 480 Width: 500 | [{'coordinates': {'y': 301... | 9| Height: 375 Width: 500 | [{'coordinates': {'y': 121... | 10| Height: 335 Width: 500 | [{'coordinates': {'y': 119... | 11| Height: 335 Width: 500 | [{'coordinates': {'y': 150... | 12| Height: 500 Width: 333 | [{'coordinates': {'y': 235... | 13| Height: 333 Width: 500 | [{'coordinates': {'y': 120... | 14+------------------------+-------------------------------+ 15[1821 rows x 2 columns] 16 17

整理数据时,请记住模型在解释任务时可能非常真实。请牢记以下注意事项:

  • 1、数据应该变化。在不同的环境中使用不同的角度、比例和亮度下的目标图片。如果你只有同一姿势下的目标图片(例如,相机中的人脸),则在测试时,模型无法检测到其他姿势的情况(例如,看着别处的人脸)。除非你特别希望检测器具有这种行为,否则你需要更改训练数据的姿势。如果你需要检测目标的各种类型(例如杯子或者狗),则应该包括各种类型的杯子和狗
  • 2 数据应该在实际场景中获取。例如,如果仅在仓库内拍摄产品的图片,则如果用户在商店内进行预测,则可能效果不佳。

你可能希望每个目标类别至少需要30个样本(边界框),但是对于许多具有挑战性的任务而言,这仍然太少了。如果想要获得高质量的结果,每个类别应该有接近200个样本。
整理好数据后,我们需要可视化检查图片的边界框是否符合预期。

1data['image_with_ground_truth'] = \ 2 tc.object_detector.util.draw_bounding_boxes(data['image'], data['annotations']) 3data.explore() 4 5

在这里插入图片描述

模型创建

标记数据准备好后,我们可以轻松的创建模型

1model = tc.object_detector.create(data, feature='image', annotations='annotations') 2 3

创建模型可能需要花费一些时间。如果你无法使用GPU,则训练好一个模型会花费一天的时间,模型训练进度将被持续打印以使你了解所需的时间。训练的迭代次数是根据数据集的大小自动确定的。如果你要降低迭代次数使模型训练的更快,则可以通过手动传递max_iterations进行更改。这可能导致模型的预测结果较差。可以肯定的是我们将很快讨论如何对模型进行量化评估。在此之前,让我们对没有被模型训练的图片做一下预测

预测

如果images是tc.Image实例列表,我们可以做出如下预测:

1test = tc.SFrame({'image': images}) 2test['predictions'] = model.predict(test) 3 4

新列predictions和ground truth annotations是一样的格式,唯一的区别是边界框字典现在包含一个预测置信度的字段

1[{'confidence': 0.7225357099539148, 2 'coordinates': {'height': 73.92794444010806, 3 'width': 90.45315889211807, 4 'x': 262.2198759929745, 5 'y': 155.496952970812}, 6 'label': 'dog', 7 'type': 'rectangle'}, 8 {'confidence': 0.5670584769557776, 9 'coordinates': {'height': 82.3002741887019, 10 'width': 96.48565420737631, 11 'x': 85.07887845066891, 12 'y': 237.6466784964736}, 13 'label': 'dog', 14 'type': 'rectangle'}] 15 16

你也可以使用可视化目标注释的函数来可视化预测值

1test['image_with_predictions'] = \ 2 tc.object_detector.util.draw_bounding_boxes(test['image'], test['predictions']) 3test[['image', 'image_with_predictions']].explore() 4 5

另一种检查预测的方法是将它们转换为stacked格式,每一行代表一个边界框(请参阅高级用法)

评估

图片分类中,预测得分达到90%精确度意味着我们可以期望模型在10张图片中预测的9张都是正确的。对于模型检测,我们使用mean average precision(mAP)来评估模型,这个指标不是很直观,使用这个指标的主要优点如下所示:

  • 1、

它是介于0和1(或0%和100%)之间的值,越高越好。

  • 2、定量指标主要用来作为不同模型之间的相对衡量(训练时间、样本规模等)。单一的值不会使你觉得检测器在当前的使用场景里表现的是否足够好。依赖定性指标就会出现上面所说的问题。但是,如果你训练一个新的模型可以将mAP指标从47%提升到55%,则你就可以知道新模型更加强大,而没有必要通过查看图片做出艰难的判断。

我们将在高级用法部分中更详细的介绍该指标,我们也将介绍如何使用Core ML将检测器部署到iOS和macOS中。

使用GPUs

GPU可以更快的创建目标检测模型。如果你有macOS 10.14 或者更高版本,则Turi Create将自动使用可用的独立GPU(不支持即成的Intel GPU)如果你的Linux计算机拥有NVIDIA GPU,你可以将Ture Create设置使用GPU,请参阅说明
使用turicreate.config.set_num_gpus函数可以控制是否使用GPUs

1# Use all GPUs (default) 2turicreate.config.set_num_gpus(-1) 3 4# Use only 1 GPU 5turicreate.config.set_num_gpus(1) 6 7# Use CPU 8turicreate.config.set_num_gpus(0) 9 10

代码交流 2021