使用Amazon SageMaker和Amazon Rekognition构建和训练计算机视觉模型,以检测图像中的汽车位置
使用Amazon SageMaker和Amazon Rekognition构建计算机视觉模型,检测汽车位置
计算机视觉(CV)是机器学习(ML)和深度学习最常见的应用之一。应用案例包括自动驾驶汽车、社交媒体平台上的内容审查、癌症检测和自动缺陷检测。Amazon Rekognition是一个完全托管的服务,可以执行CV任务,如物体检测、视频片段检测、内容审查等,从数据中提取洞察力,无需任何先前的ML经验。在某些情况下,可能需要与该服务一起使用更定制的解决方案来解决一个非常特定的问题。
在本文中,我们将讨论CV可以应用于一些场景,其中对象的姿势、位置和方向很重要。一个这样的应用案例是面向客户的移动应用程序,需要上传图像。这可能是出于合规原因,或为了提供一致的用户体验和提高参与度。例如,在在线购物平台上,产品在图像中显示的角度会影响购买该产品的比率。一个这样的案例是检测汽车的位置。我们演示如何将众所周知的ML解决方案与后处理结合起来,以解决这个问题在AWS Cloud上。
我们使用深度学习模型来解决这个问题。训练姿势估计的ML算法需要很多专业知识和定制训练数据。这两个要求都很难和昂贵。因此,我们提供了两个选项:一个不需要任何ML专业知识,使用Amazon Rekognition;另一个使用Amazon SageMaker来训练和部署定制的ML模型。在第一个选项中,我们使用Amazon Rekognition来检测车轮。然后,我们使用基于规则的系统从车轮位置推断出车的方向。在第二个选项中,我们使用Detectron模型来检测车轮和其他车辆部件。这些再次用于使用基于规则的代码推断出车的位置。第二个选项需要ML经验,但也更可定制。它可以用于图像的进一步后处理,例如裁剪整个汽车。这两个选项都可以在公开可用的数据集上进行训练。最后,我们展示了如何使用Amazon API Gateway和AWS Amplify等服务将这个车辆姿势检测解决方案集成到现有的Web应用程序中。
解决方案概述
下图说明了解决方案架构。
解决方案由Amplify中的模拟Web应用程序组成,用户可以上传图像并调用Amazon Rekognition模型或自定义Detectron模型来检测汽车的位置。对于每个选项,我们在API Gateway后面配置了一个AWS Lambda函数,该函数暴露给我们的模拟应用程序。我们将Lambda函数配置为使用在SageMaker中训练的Detectron模型或Amazon Rekognition运行。
先决条件
在进行本教程之前,您应具备以下先决条件:
AWS帐户。
具有部署和配置基础设施的权限的AWS Identity and Access Management(IAM)用户,例如PowerUserAccess(请注意,用于生产就绪应用程序的权限需要进一步限制,并且取决于与其他服务的可能集成)。
在开发环境中拥有Docker(本地计算机或从SageMaker笔记本实例部署解决方案的地方)。
安装了AWS Cloud Development Kit(AWS CDK)。可以使用npm按照我们的GitHub存储库中的说明进行安装。
使用Amazon Rekognition创建无服务器应用程序
我们的第一个选项演示了如何使用Amazon Rekognition在图像中检测车辆方向。思路是使用Amazon Rekognition来检测车辆和车轮的位置,然后进行后处理以从这些信息中推断出车辆的方向。整个解决方案使用Lambda部署,如GitHub存储库所示。该文件夹包含两个主要文件:一个定义了在我们的Lambda函数中运行的Docker镜像的Dockerfile,以及app.py
文件,它将是Lambda函数的主入口点。
Lambda函数期望接收一个包含头部和正文的事件,其中正文应该是需要作为base64解码对象标记的图像。给定图像,通过Boto3从Lambda函数调用Amazon Rekognition的detect_labels
函数。该函数返回图像中每个对象的一个或多个标签,以及作为响应的一部分的所有检测到的对象标签的边界框详细信息,以及分配标签的置信度,检测到的标签的祖先标签,标签的可能别名和检测到的标签所属的类别等其他信息。根据Amazon Rekognition返回的标签,我们运行函数label_image
,它根据检测到的车轮计算车辆角度,如下所示:
n_wheels = len(wheel_instances)
wheel_centers = [np.array(_extract_bb_coords(wheel, img)).mean(axis=0)
for wheel in wheel_instances]
wheel_center_comb = list(combinations(wheel_centers, 2))
vecs = [(k, pair[0] - pair[1]) for k,pair in enumerate(wheel_center_comb)]
vecs = sorted(vecs, key = lambda vec: np.linalg.norm(vec[1]))
vec_rel = vecs[1] if n_wheels == 3 else vecs[0]
angle = math.degrees(math.atan(vec_rel[1][1]/vec_rel[1][0]))
wheel_centers_rel = [tuple(wheel.tolist()) for wheel in
wheel_center_comb[vec_rel[0]]]
请注意,该应用程序要求图像中只有一辆车,并且如果不符合该条件则返回错误。但是,后处理可以被调整以提供更细粒度的方向描述,涵盖多辆车辆或计算更复杂对象的方向。
改进车轮检测
为了进一步提高车轮检测的准确性,可以使用Amazon Rekognition Custom Labels。类似于使用SageMaker进行微调以训练和部署自定义机器学习模型,您可以使用自己标记的数据,使Amazon Rekognition在几个小时内为您生成一个自定义图像分析模型。使用Rekognition Custom Labels,您只需要一小组与您的用例相关的训练图像,例如具有特定角度的汽车图像,因为它使用Amazon Rekognition上的现有能力,可以在许多类别的数千万图像上进行训练。 Rekognition Custom Labels可以通过仅点击几下并对我们用于标准Amazon Rekognition解决方案的Lambda函数进行小的调整来进行集成。
使用SageMaker训练作业训练模型
在我们的第二个选项中,我们在SageMaker上训练一个自定义的深度学习模型。我们使用Detectron2框架对汽车部件进行分割。然后使用这些分割部分推断汽车的位置。
Detectron2框架是一个提供最先进的检测和分割算法的库。Detectron提供了多种在著名的COCO(上下文中的常见对象)数据集上训练的Mask R-CNN模型。为了构建我们的汽车对象检测模型,我们使用迁移学习对预训练的Mask R-CNN模型在汽车部件分割数据集上进行微调。该数据集允许我们训练一个能够检测车轮以及其他汽车部件的模型。这些额外的信息可以在相对于图像的车辆角度计算中进一步使用。
数据集包含用于对象检测和语义分割任务的汽车部件的注释数据:大约500张轿车,皮卡车和运动型多功能车(SUV)的图像,以多个视图(前视图,后视图和侧视图)拍摄。每个图像由18个实例掩码和边界框注释,表示汽车的不同部件,如车轮,镜子,灯光,前后玻璃。我们修改了车轮的基本注释,使得每个车轮被视为一个单独的对象,而不是将图像中所有可用的车轮视为一个对象。
我们使用Amazon Simple Storage Service(Amazon S3)存储用于训练Detectron模型的数据集以及训练后的模型工件。此外,运行在Lambda函数中的Docker容器存储在Amazon Elastic Container Registry(Amazon ECR)中。Lambda函数中的Docker容器需要包含运行代码所需的库和依赖项。我们也可以使用Lambda层,但它受到最大250 MB的解压部署包大小配额和最多可以将五个层添加到Lambda函数的限制。
我们的解决方案是建立在SageMaker上的:我们扩展了预构建的SageMaker PyTorch Docker容器以运行我们的自定义PyTorch训练代码。接下来,我们使用SageMaker Python SDK将训练图像封装到SageMaker PyTorch估算器中,如下所示:
d2_estimator = Estimator(
image_uri=training_image_uri,
role=role,
sagemaker_session=sm_session,
instance_count=1,
instance_type=training_instance,
output_path=f"s3://{session_bucket}/{prefix_model}",
base_job_name=f"detectron2")
d2_estimator.fit({
"training": training_channel,
"validation": validation_channel,
},
wait=True)
最后,我们调用创建的PyTorch estimator上的fit()
函数来开始训练任务。当训练完成后,训练好的模型文件将被存储在Amazon S3的会话存储桶中,以供推理流程使用。
使用SageMaker和推理流程部署模型
我们还使用SageMaker来托管运行我们自定义的Detectron模型的推理端点。部署解决方案的完整基础设施是使用AWS CDK进行预配的。通过在PyTorch estimator上调用deploy
,我们可以通过SageMaker实时端点托管我们的自定义模型。这是我们第二次扩展预构建的SageMaker PyTorch容器,以包含PyTorch Detectron。我们使用以下方式运行推理脚本和托管我们训练好的PyTorch模型:
model = PyTorchModel(
name="d2-sku110k-model",
model_data=d2_estimator.model_data,
role=role,
sagemaker_session=sm_session,
entry_point="predict.py",
source_dir="src",
image_uri=serve_image_uri,
framework_version="1.6.0")
predictor = model.deploy(
initial_instance_count=1,
instance_type="ml.g4dn.xlarge",
endpoint_name="detectron-endpoint",
serializer=sagemaker.serializers.JSONSerializer(),
deserializer=sagemaker.deserializers.JSONDeserializer(),
wait=True)
请注意,我们在部署中使用了ml.g4dn.xlarge GPU,因为它是最小的可用GPU,并且对于这个演示来说已经足够。在我们的推理脚本中需要配置两个组件:模型加载和模型服务。model_fn()
函数被用于加载托管的Docker容器中的训练好的模型,该模型也可以在Amazon S3中找到,并返回一个可用于模型服务的模型对象,代码如下:
def model_fn(model_dir: str) -> DefaultPredictor:
for p_file in Path(model_dir).iterdir():
if p_file.suffix == ".pth":
path_model = p_file
cfg = get_cfg()
cfg.MODEL.WEIGHTS = str(path_model)
return DefaultPredictor(cfg)
predict_fn()
函数执行预测并返回结果。除了使用我们训练好的模型,我们还使用在COCO数据集上训练的Mask R-CNN模型的预训练版本来提取图像中的主要汽车。这是一个额外的后处理步骤,用于处理存在多辆汽车的图像。代码如下:
def predict_fn(input_img: np.ndarray, predictor: DefaultPredictor) -> Mapping:
pretrained_predictor = _get_pretraind_model()
car_mask = get_main_car_mask(pretrained_predictor, input_img)
outputs = predictor(input_img)
fmt_out = {
"image_height": input_object.shape[0],
"image_width": input_object.shape[1],
"pred_boxes": outputs["instances"].pred_boxes.tensor.tolist(),
"scores": outputs["instances"].scores.tolist(),
"pred_classes": outputs["instances"].pred_classes.tolist(),
"car_mask": car_mask.tolist()
}
return fmt_out
与Amazon Rekognition解决方案类似,我们从检测输出中过滤出预测为wheel
类别的边界框,并将其提供给后处理模块,以评估汽车相对于输出的位置。
最后,我们还改进了Detectron解决方案的后处理。它还使用不同汽车部件的分段来推断解决方案。例如,当检测到前保险杠但没有后保险杠时,我们假设我们有一辆汽车的前视图,并计算相应的角度。
将解决方案连接到Web应用程序
将模型端点连接到Amplify的步骤如下:
- 克隆应用程序存储库,该存储库是由AWS CDK堆栈创建的,名称为
car-angle-detection-website-repo
。确保在部署所使用的区域中查找它。 - 将每个部署的Lambda函数的API Gateway端点复制到前面存储库的
index.html
文件中(有占位符需要放置端点)。以下代码是.html文件中此部分的示例:
<td align="center" colspan="2">
<select id="endpoint">
<option value="https://ey82aaj8ch.execute-api.eu-central-1.amazonaws.com/prod/">
亚马逊 Rekognition</option>
<option value="https://nhq6q88xjg.execute-api.eu-central-1.amazonaws.com/prod/">
亚马逊 SageMaker Detectron</option>
</select>
<input class="btn" type="file" id="ImageBrowse" />
<input class="btn btn-primary" type="submit" value="上传">
</td>
- 保存HTML文件并将代码更改推送到远程主分支。
这将更新部署中的HTML文件。应用程序现在已经准备好使用了。
- 转到Amplify控制台,找到您创建的项目。
在部署完成后,应用程序URL将可见。
- 转到URL并享受用户界面。
结论
恭喜!我们已经部署了一个完整的无服务器架构,其中我们使用了亚马逊 Rekognition,但也提供了使用自定义模型的选项,可以在GitHub上找到此示例。如果您的团队中没有机器学习专家或足够的自定义数据来训练模型,您可以选择使用亚马逊 Rekognition。如果您希望更多地控制您的模型,希望进一步定制它,并且拥有足够的数据,您可以选择SageMaker解决方案。如果您有一支数据科学家团队,他们可能还想进一步增强模型并选择更自定义和灵活的选项。您可以使用这两个选项之一将Lambda函数和API Gateway放在您的Web应用程序后面。您还可以使用此方法处理不同的用例,您可能希望调整代码。
这种无服务器架构的优势在于构建块完全可互换。机会几乎是无限的。所以,今天就开始吧!
一如既往,AWS欢迎反馈。请提出任何意见或问题。