亚马逊AWS官方博客

在笔记本电脑上自定义并显示 AWS DeepLens 项目输出

AWS DeepLens 是一个带有摄像头的支持深度学习的开发人员工具包。它使您能够通过实操计算机视觉教程和预建模型来开发机器学习技能并进行扩展。预构建模型的示例包括:用于识别和检测房间里的不同对象 (如电视显示器、人和瓶子) 的对象检测以及用于识别不同类型的动作 (如刷牙、涂口红、打鼓、拉小提琴和打篮球) 的动作识别。

AWS DeepLens 可让您从设备的摄像头显示流以及在 IoT 控制台和本地设备上显示模型的输出。有关了解有关如何执行此操作的更多信息,您可以参阅文档。在本博客文章中,我们将讨论如何通过 HTML 页面上的 AWS DeepLens 自定义和显示项目输出。

我们将使用:

  • Amazon Cognito,旨在使 HTML 页面能够通过 IoT WebSockets 访问 AWS DeepLens MQTT 消息
  • AWS IoT,旨在处理数据订阅和发布
  • Amazon S3,旨在存储用于显示输出的 HTML 文件

您可以使用 AWS CLI 或 AWS 管理控制台来自定义 AWS DeepLens 项目输出。使用 CLI 和控制台的步骤如下所示。

先决条件

要执行以下步骤以自定义 AWS DeepLens 输出,您需要

  • 拥有一台 AWS DeepLens 设备
  • 注册该设备
  • 创建一个项目并将它部署到该设备

有关更多信息,您可以参阅文档。如果您没有 AWS DeepLens 设备,则可以注册以加入到我们的等待名单。

开始使用 AWS CLI 的步骤

要开始使用 AWS CLI,请执行以下步骤。

步骤 1:创建 Cognito 身份池

每当您注册 AWS DeepLens 设备时,该服务都会创建一个唯一的 MQTT 主题。本主题将在 AWS IoT 控制台上展示您的已部署模型的输出。例如,如果您已部署到 AWS DeepLens 的项目检测到您的周边环境中的对象,则可以使用 MQTT 主题向 IoT 控制台发送检测到的对象名称。在本博客文章中,我们希望能够在自定义 HTML 页面上显示 MQTT 消息。对此,我们将使用 Amazon Cognito。

利用 Amazon Cognito,您可以轻松地使用临时凭证以一种安全的方式访问 AWS 资源,从而不必将 AWS 凭证放在源代码或网页中。

为此,我们首先需要创建一个身份池。我们稍后会将此 IdentityPoolId 提供给 HTML 页面,使其能够使用临时凭证订阅 MQTT 主题。

在 AWS CLI 上,粘贴以下命令。在执行该步骤之前,请确保您是在所需的 AWS 区域中创建身份。

> aws cognito-identity create-identity-pool \ 
  --identity-pool-name DeepLens_Console  \
  --allow-unauthenticated-identities --region us-east-1

响应将采用以下格式:

{
    "IdentityPoolId": "us-east-1:XXXXXXX-1cd1-4c3a-9a39-dac267545277",
    "AllowUnauthenticatedIdentities": true,
    "IdentityPoolName": "DeepLensConsole"
}

记下 IdentityPoolId (以黄色突出显示)。您稍后会将它用作 HTML 页面的参数。

注意:此身份池将允许未经身份验证的用户获取一些访问您的 AWS 资源的权限 (我们将在后续步骤中定义)。这样做是为了简化与 HTML 页面的交互。如果您要增强该页面的安全性,则可以完全取消对未经身份验证的用户的支持,或者将页面访问限制为有限的功能。您还可以向该页面添加注册功能,以使用各种登录提供商对用户进行身份验证。

步骤 2:创建 IAM 角色以允许 AWS IoT MQTT 订阅

AWS DeepLens 设备使用 MQTT 主题和消息通过 IoT 订阅与云进行通信。这些渠道进行了优化以便在 IoT 环境中实现安全可靠的通信。要能够接收这些消息并在 HTML 页面上显示它们,我们需要定义以下 IAM 角色和权限。

首先,为 IAM 角色创建一个策略文档。为此,请将以下内容保存到名为 DeepLensConsoleUnauthName.json 的文件,该文件位于您运行 CLI 命令的同一目录下。请记住将 IdentityPoolId 替换为在上一步中检索到的内容。

在本步骤中,我们将为未经身份验证的用户访问 AWS 资源定义信任策略。现在,该角色没有权限,但我们允许 Amazon Cognito 代入它。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-1:XXXXX-1cd1-4c3a-9a39-dac267545277"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "unauthenticated"
        }
      }
    }
  ]
}

接下来,创建一个 IAM 角色,然后将您刚刚创建的策略附加到该角色。请注意,您需要使用在上一步中创建的同一路径和文件名。记住角色名称,因为您在后续步骤中需要它。

> aws iam create-role --role-name DeepLensConsoleUnauthName \  
  --assume-role-policy-document file://DeepLensConsoleUnauthName.json

接下来,将 AWSIoTDataAccess 策略附加您刚刚创建的角色。这会将一个允许此角色读取和写入消息的托管策略附加到您的 IoT 终端节点的所有主题。您可以创建一个更严格的策略来限制允许的主题和命令,或者也可以向该角色添加更多权限。例如,您可以使用以下策略 ARN 允许 Amazon Polly 读出标签:arn:aws:iam::aws:policy/AmazonPollyReadOnlyAccess

> attach-role-policy \
  --role-name DeepLensConsoleUnauthName \
  --policy-arn arn:aws:iam::aws:policy/AWSIoTDataAccess

步骤 3:连接身份池和 IAM 角色

现在,您需要将 Cognito 身份池连接到 IAM 角色。请使用以下命令实现此关联。

> aws cognito-identity set-identity-pool-roles \ 
--identity-pool-id "us-east-1:XXXXX-1cd1-4c3a-9a39-dac267545277" \ 
--roles unauthenticated=DeepLensConsoleUnauthName

步骤 4:查找您的账户的 IoT 终端节点

使用 AWS CLI 执行以下步骤:

键入命令。

aws iot describe-endpoint

它将返回您的 IoT 终端节点

{
       "endpointAddress": "XXXXXXXXXXXXX.iot.us-east-1.amazonaws.com"
}

步骤 5:打开 HTML 页面以查看您的项目输出

您现在可以通过传递之前定义的参数在 Amazon S3 中打开静态 HTML 页面:

https://s3-us-west-2.amazonaws.com/im-examples/console/index.html?region=us-east-1&host=IoTEndpoint&id-pool=IdentityPoolId

例如,以下是包含本指南中使用的值的链接:

https://s3-us-west-2.amazonaws.com/im-examples/console/index.html?region=us-east-1&host=XXXXXXXXX.iot.us-east-1.amazonaws.com&id-pool=us-east-1:XXXXXXXX-XXXX-4a79-8dd4-568590df9298

根据您的项目所显示的结果,您可以在此 HTML 页面上查看 MQTT 消息、图像和带有边界框的视频流。

开始使用 AWS 管理控制台的步骤

要开始使用 AWS 管理控制台,请执行以下步骤。

步骤 1:创建 Cognito 身份池

每当您注册 AWS DeepLens 设备时,该服务都会创建一个唯一的 MQTT 主题。本主题将在 AWS IoT 控制台上展示您的已部署模型的输出。例如,如果您已部署到 AWS DeepLens 的项目检测到您的周边环境中的对象,则可以使用 MQTT 主题向 IoT 控制台发送检测到的对象名称。在本博客文章中,我们希望能够在自定义 HTML 页面上显示 MQTT 消息。对此,我们将使用 Amazon Cognito。

利用 Amazon Cognito,您可以轻松地使用临时凭证以一种安全的方式访问 AWS 资源,从而不必将 AWS 凭证放在源代码或网页中。

为此,我们首先需要创建一个身份池。我们稍后会将此 IdentityPoolId 提供给 HTML 页面,使其能够使用临时凭证订阅 MQTT 主题。

Amazon Cognito 控制台中,选择“Manage Federated Identities”和“Create new identity pool”。为其指定名称 (例如,“DeepLens_Console”) 并选中选项“Enable access to unauthenticated identities”。

注意:此身份池将允许未经身份验证的用户获取一些访问您的 AWS 资源的权限 (我们将在后续步骤中定义)。这样做是为了简化与 HTML 页面的交互。如果您要增强该页面的安全性,则可以完全取消对未经身份验证的用户的支持,或者将页面访问限制为有限的功能。您还可以向该页面添加注册功能,以使用各种登录提供商对用户进行身份验证。

允许 Amazon Cognito 代表您代入角色。

在下一个屏幕上,您将看到有关如何在移动和 Web 界面中使用 IdentityPoolId 的说明和代码示例。现在,请选择“Edit identity pool”按钮,并记下未经身份验证的身份的 IdentityPoolId 和 role name

步骤 2:编辑 IAM 角色以允许 AWS IoT MQTT 订阅

AWS DeepLens 设备使用 MQTT 主题和消息通过 IoT 订阅与云进行通信。这些渠道进行了优化以便在 IoT 环境中实现安全可靠的通信。要能够接收这些消息并在本地 HTMP 页面上显示它们,我们需要定义具有访问 IoT 资源的适当权限的特定 IAM 角色。

转到 IAM 控制台并搜索未经身份验证的角色的名称。选择带有 Unauth_Role 后缀的角色 (列表上的第二个)。

现在,为角色单击“Attach policy”,搜索 IoT 托管策略,然后选择“AWSIoTDataAccess”。

选择“Attach policy”。

这会将一个允许此角色读取和写入消息的托管策略附加到您的 IoT 终端节点的所有主题。您可以创建一个更严格的策略来限制允许的主题和命令,或者向该角色添加更多权限 (例如,您可以使用以下策略 ARN 允许 Amazon Polly 读出标签):arn:aws:iam::aws:policy/AmazonPollyReadOnlyAccess )。

步骤 3:查找您的账户的 IoT 终端节点

使用 AWS IoT 控制台选择 Settings 选项:

步骤 4:打开 HTML 页面以查看您的项目输出

您现在可以通过传递之前定义的参数在 Amazon S3 中打开静态 HTML 页面。

https://s3-us-west-2.amazonaws.com/im-examples/console/index.html?region=us-east-1&host=IoTEndpoint&id-pool=IdentityPoolId

例如,以下是包含本博客文章中使用的值的链接:

https://s3-us-west-2.amazonaws.com/im-examples/console/index.html?region=us-east-1&host=XXXXXXXXX.iot.us-east-1.amazonaws.com&id-pool=us-east-1:XXXXXXXX-XXXX-4a79-8dd4-568590df9298

根据您的项目所显示的结果,您可以在此 HTML 页面上查看 MQTT 消息、图像和带有边界框的视频流。

从设备发送要在项目输出页面上显示的图像

边缘 AWS Lambda 函数的简单功能是将文本消息发布到 IoT 主题。您将能够在项目输出页面上 (或在 AWS IoT 控制台中的“test”选项卡上) 看到这些消息。

第一个扩展用于在模型推理之前或之后显示图像 (带边界框)。在本示例中,您将图像上传到 Amazon S3 并将图像 URL 发送到 IoT 主题。

将图像上传到 S3

首先,将 Python 函数添加到边缘 Lambda 函数以将图像上传到 Amazon S3:

# Function to write to S3
# The function is creating an S3 client every time to use temporary credentials
# from the GG session over TES 
def write_image_to_s3(img):
    session = Session()
    s3 = session.create_client('s3')
    file_name = 'DeepLens/image-'+time.strftime("%Y%m%d-%H%M%S")+'.jpg'
    # You can contorl the size and quality of the image
    encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90]
    _, jpg_data = cv2.imencode('.jpg', img, encode_param)
    response = s3.put_object(ACL='public-read', Body=jpg_data.tostring(),Bucket='<BUCKET_NAME>',Key=file_name)

    image_url = 'https://s3.amazonaws.com/<BUCKET_NAME>/'+file_name
    return image_url

接下来,您将从推理 Python 函数调用该函数:

    ...
    # Upload to S3 to allow viewing the image in the browser
    image_url = write_image_to_s3(frame_with_bb)

并将它添加到输出消息:

    client.publish(topic=iotTopic, payload='{{"img":"{}"}}'.format(image_url))

添加到图像的另一个命令是在模型输出图像 (“ssd”类型) 时显示边界框:

# Adding top n bounding boxes results
def apply_bounding_box(img, topn_results):
        '''
        cv2.rectangle(img, (x1, y1), (x2, y2), RGB(255,0,0), 2)
        x1,y1 ------
        |          |
        --------x2,y2
        '''
        for obj in topn_results:
            class_id = obj['label']
            class_prob = obj['prob']
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            cv2.rectangle(img, (int(obj['xmin']), int(obj['ymin'])), (int(obj['xmax']), int(obj['ymax'])), (255,0,0), 2)
        return img

然后,使用以下代码获取前 n (例如 5) 个结果并将其应用于图像:

     ...
     results = model.parseResult('ssd',results)
     tops = results['ssd'][0:5]
     frame_with_bb = apply_bounding_box(frame_resize,tops)

结论

对此类输出页面还可以添加很多其他命令,将来的博客文章中将介绍其中一些。一部分示例是通过 MQTT 消息流式传输视频并在输出页面上重新生成流,或者嵌入 Amazon CloudWatch 图形或控制面板,等等。

AWS DeepLens 是一个开放式平台,用于生成教育和生产项目等内容。我们期望您构建新的深度学习模型、新的 Lambda 边缘函数、带有云逻辑的新功能以及用于控制和查看项目输出的新的人机接口,由此来扩展内置项目。
在本博客文章中,您看到了一个简单的基于 HTML 的页面,该页面能够安全地连接到您的设备以及在设备中运行的项目,并能够显示项目推理的输出。我希望它能为您提供一个良好的框架和基础,让您针对更高级的使用案例构建更先进的接口。我很想倾听您的想法,并希望与围绕 AWS DeepLens 的社区分享这些想法。


补充阅读

了解如何扩展 AWS DeepLens 以利用 AWS Lambda 发送 SMS 通知


作者简介

Guy Ernest 是 Amazon AI 的首席解决方案架构师。 他有一个令人非常兴奋的机会来帮助塑造和践行策略,以构建思想共享并广泛使用适用于 AI、机器学习和深度学习使用案例的 Amazon 云计算平台。在空闲时间,他喜欢与妻子和家人呆在一起,收集一些令人尴尬的故事,然后在谈论 Amazon 和 AI 的未来时进行分享。

Sunil Mallya 是 AWS Deep Learning 团队的高级解决方案架构师。 他致力于帮助我们的客户构建机器学习和深度学习解决方案以推进其业务。在业余时间,他喜欢烹饪、航海和打造 RC 自动驾驶汽车。