Category: AWS DeepLens


在笔记本电脑上自定义并显示 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 自动驾驶汽车。

扩展 AWS DeepLens 以使用 AWS Lambda 发送 SMS 通知

AWS DeepLens 是一个带有摄像头的支持深度学习的开发人员工具包。它使您能够通过实操计算机视觉教程和预建模型来开发机器学习技能并进行扩展。

本博客文章将说明如何借助 AWS IoT 规则引擎和 Lambda 函数来利用云功能扩展 DeepLens 的本地功能。我们在这里介绍的简单功能是:在您通过 DeepLens 设备看到热狗后向您的电话号码发送 SMS 通知。我们期望有更多的高级用户扩展此功能以包含其他 AWS 云服务,例如 Amazon Elasticsearch Service (利用时间轴和帧为检测到的所有对象和面部构建控制面板和搜索界面)、Amazon Kinesis Analytics (构建有关在您的店面前走过的人数的异常检测模型)、Amazon Rekognition (使用名人识别和面部搜索 API 来识别您周围的 VIP) 和很多其服务。

这里有一张示意图展示了系统中数据的流动 – 从摄像头前部的物体一直到您口袋中的移动设备。

创建 Lambda 函数

首先,您将创建一个 AWS Lambda 函数,该函数将在云中运行并为具有足够高 (>0.5) 的概率获得热狗的人筛选来自您的 DeepLens 设备的消息。在此过程中,您还将在 AWS IoT 规则引擎中创建一条规则,用于从您使用 AWS Greengrass 部署到设备的 Lambda 函数获取消息。

  • AWS Lambda 控制台上,转到“Create Function”。
  • 筛选包含“iot-button-email”的蓝图并选择它作为您的蓝图模板。
  • 为您的 Lambda 函数指定一个名称。例如,Hotdog_Notifier”。
  • 在“Role”字段中保留“Create a new Role from template(s)”值。
  • 为新角色指定名称。例如,“Hotdog_Notifier_Role”。
  • 在“Policy Templates”中添加策略“SNS Publish policy”。
  • 在“aws-iot”部分中,切换为使用“Custom IoT Rule”。
    • 选择“Create a new rule”。
  • 为该规则指定名称 (例如,“search_hotdogs”) 和描述。
  • 在规则查询语句中放置以下 SELECT 查询:Select Hotdog from ‘/$aws/deeplens/KJHFD-DKJO87-LJLKD/inference’。此查询可捕获来自 DeepLens 设备的采用以下 JSON 格式的消息: { "Hotdog" : 0.5438 }
  • 在后面的复选框中启用“Trigger”。
  • 我们将在下一步中修改 Lambda 函数的代码。
  • 将环境参数从“email”更改为“phone_number”,并将您的电话号码作为“Value”放置。请注意,电话号码格式应包含国家/地区代码 (例如,美国号码 +15555555555)。您可以在 AWS SNS 常见问题中阅读有关针对 SMS 的国际支持的更多内容:https://aws.amazon.com/sns/faqs/#sms-related-questions
  • 选择“Create Function”按钮。
  • 切换为您刚刚创建的 Lambda 函数的“Configuration”。您可以查找左侧的配置选项卡 (“configuration”、“triggers”和“monitoring”)。
  • 在 Lambda 函数代码中,我们可以删除常规 SNS 订阅所需的所有帮助程序函数,例如 findExistingSubscription、createSubscription 和 createTopic。删除“use strict”之前的所有代码。我们还将修改代码以直接发送 SMS:
    'use strict';
    
    /**
     * This is a sample Lambda function that sends an SMS Notification When your
     * Deep Lens device detects a Hot Dog
     * 
     * Follow these steps to complete the configuration of your function:
     *
     * Update the phone number environment variable with your phone number.
     */
    
    const AWS = require('aws-sdk');
    
    const phone_number = process.env.phone_number;
    const SNS = new AWS.SNS({ apiVersion: '2010-03-31' });
    
    exports.handler = (event, context, callback) => {
        console.log('Received event:', event);
    
        // publish message
        const params = {
            Message: `Your DeepLens device just identified a Hot Dog. Congratulations!`,
            PhoneNumber: phone_number
        };
        if (event.Hotdog > 0.5)
            SNS.publish(params, callback);
    };
  • 选择“Save”。您也可以在此屏幕中测试 Lambda 函数,但我们现在将通过 IoT 规则引擎测试它,以模拟来自 DeepLens 设备的消息流。

测试配置

  • IoT 控制台中,选择“Test”选项。
  • 在以下消息上方选择“Publish to a Topic”和“Publish to the topic you defined in your Rule”: { "Hotdog": 0.68725 }
  • 您应该会收到 SMS 通知,其中包含消息“Your DeepLens device just…”,该消息是您在 Lambda 函数中定义的。
  • 现在是时候向您的 DeepLens 设备展示一些对象和一根热狗了。祝您好运!
  • 如果您在向设备展示一根热狗后没有收到信息,请回到顶部的图表,然后验证您是否按照颜色匹配了相关值以及是否提供了正确的电话号码和国家/地区代码。

结论

Amazon DeepLens 是一个开放式教育和创新平台,我们希望开发人员能提出很多不同的想法来使用它解决现实生活中的问题:从分析在商店周围走动的人员到为您的汽车自动打开车库门,或者在您的餐厅里的桌子很脏或客人请求服务时提醒您。这只是您可以使用 AWS DeepLens 构建 (借助与本博客文章中的简单扩展类似的扩展) 的系统的一个小型示例。


补充阅读

了解如何通过 HTML 页面上的 AWS DeepLens 自定义和显示项目输出


作者简介

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