教程:在边缘使用自定义视觉服务进行图像分类Tutorial: Perform image classification at the edge with Custom Vision Service

Azure IoT Edge 可以将工作负荷从云移到边缘,让 IoT 解决方案更高效。Azure IoT Edge can make your IoT solution more efficient by moving workloads out of the cloud and to the edge. 此功能非常适用于处理大量数据的服务,例如计算机视觉模型。This capability lends itself well to services that process a lot of data, like computer vision models. 将这两项服务一起使用可以对图像或视频流进行分析,不需先将所有数据从站点转移出来。Together, these two services enable you to find insights from images or video streams without having to transfer all of the data off site first. 自定义视觉提供一个可以将图像与训练的模型进行比较的分类器,以便生成见解。Custom Vision provides a classifier that compares an image against a trained model to generate insights.

例如,IoT Edge 设备上的自定义视觉可以确定某条高速公路的交通流量是高于还是低于正常,或者某个室内停车场是否有连续的停车位。For example, Custom Vision on an IoT Edge device could determine whether a highway is experiencing higher or lower traffic than normal, or whether a parking garage has available parking spots in a row. 这些见解可以与其他服务共享,方便采取行动。These insights can be shared with another service to take action.

在本教程中,你将了解如何执行以下操作:In this tutorial, you learn how to:

  • 使用自定义视觉生成图像分类器。Build an image classifier with Custom Vision.
  • 开发用于在设备上查询自定义视觉 Web 服务器的 IoT Edge 模块。Develop an IoT Edge module that queries the Custom Vision web server on your device.
  • 将图像分类器的结果发送到 IoT 中心。Send the results of the image classifier to IoT Hub.

示意图 - 架构、阶段和部署分类器教程

![Diagram - Tutorial architecture, stage and deploy classifier](./media/tutorial-deploy-custom-vision/custom-vision-architecture.png)

如果没有 Azure 试用版订阅,请在开始前创建一个试用版订阅If you don't have an Azure trail subscription, create a trial subscription before you begin.



本教程是 Raspberry Pi 3 上的自定义视觉和 Azure IoT Edge 示例项目的简化版本。This tutorial is a simplified version of the Custom Vision and Azure IoT Edge on a Raspberry Pi 3 sample project. 本教程旨在在云 VM 上运行,并使用静态图像训练和测试图像分类器,这对于刚开始评估 IoT Edge 上的自定义视觉的用户非常有用。This tutorial was designed to run on a cloud VM and uses static images to train and test the image classifier, which is useful for someone just starting to evaluate Custom Vision on IoT Edge. 该示例项目使用物理硬件并设置一个实时相机源,用于训练和测试图像分类器,这对于想要尝试更详细的真实应用场景的用户非常有用。The sample project uses physical hardware and sets up a live camera feed to train and test the image classifier, which is useful for someone who wants to try a more detailed, real-life scenario.

在开始学习本教程之前,应已完成上一篇教程,了解如何设置用于开发 Linux 容器的环境:开发适用于 Linux 设备的 IoT Edge 模块Before beginning this tutorial, you should have gone through the previous tutorial to set up your environment for Linux container development: Develop IoT Edge modules for Linux devices. 完成该教程后,应已准备好以下必备组件:By completing that tutorial, you should have the following prerequisites in place:

要使用自定义视觉设备开发 IoT Edge 模块,请在开发计算机上安装下述额外的必备组件:To develop an IoT Edge module with the Custom Vision service, install the following additional prerequisites on your development machine:

使用自定义视觉生成图像分类器Build an image classifier with Custom Vision

若要生成图像分类器,需创建自定义视觉项目并提供训练图像。To build an image classifier, you need to create a Custom Vision project and provide training images.

生成并训练图像分类器以后,即可将它作为 Docker 容器导出并部署到 IoT Edge 设备。Once your image classifier is built and trained, you can export it as a Docker container and deploy it to an IoT Edge device.

创建新项目Create a new project

  1. 在 Web 浏览器中,导航到自定义影像服务网页In your web browser, navigate to the Custom Vision web page.

  2. 选择“登录”,使用访问 Azure 资源时所用的帐户进行登录。 Select Sign in and sign in with the same account that you use to access Azure resources.

  3. 选择“新建项目”。 Select New project.

  4. 使用以下值来创建项目:Create your project with the following values:

    字段Field Value
    名称Name 为项目提供一个名称,例如 EdgeTreeClassifierProvide a name for your project, like EdgeTreeClassifier.
    说明Description 可选项目说明。Optional project description.
    资源Resource 选择一个包含自定义视觉服务资源的 Azure 资源组,或者如果尚未添加 Azure 资源组,则选择“新建” 。Select one of your Azure resource groups that includes a Custom Vision Service resource or create new if you haven't yet added one.
    项目类型Project Types 分类Classification
    分类类型Classification Types 多类(一个图像一个标记)Multiclass (single tag per image)
    Domains 常规(精简)General (compact)
    导出功能Export Capabilities 基本平台(Tensorflow、CoreML、ONNX 等)Basic platforms (Tensorflow, CoreML, ONNX, ...)
  5. 选择“创建项目”。 Select Create project.

上传图像并训练分类器Upload images and train your classifier

创建图像分类器需要一组训练图像和测试图像。Creating an image classifier requires a set of training images, as well as test images.

  1. 将示例图像从 Cognitive-CustomVision-Windows 存储库克隆或下载到本地开发计算机。Clone or download sample images from the Cognitive-CustomVision-Windows repo onto your local development machine.

    git clone https://github.com/Microsoft/Cognitive-CustomVision-Windows.git
  2. 返回到自定义视觉项目,选择“添加图像”。 Return to your Custom Vision project and select Add images.

  3. 浏览到已克隆到本地的 git 存储库,导航到第一个图像文件夹 Cognitive-CustomVision-Windows / Samples / Images / HemlockBrowse to the git repo that you cloned locally, and navigate to the first image folder, Cognitive-CustomVision-Windows / Samples / Images / Hemlock. 选择文件夹中的所有 10 个图像,然后单击“打开”。 Select all 10 images in the folder and then Open.

  4. 将标记“铁杉” 添加到此组图像,然后按 Enter 应用该标记。Add the tag hemlock to this group of images and press enter to apply the tag.

  5. 选择“上传 10 个文件”。 Select Upload 10 files.

    将 hemlock 标记的文件上传到自定义视觉

  6. 成功上传图像以后,选择“完成”。 When the images are uploaded successfully, select Done.

  7. 再次选择“添加图像”。 Select Add images again.

  8. 浏览到第二个图像文件夹 Cognitive-CustomVision-Windows / Samples / Images / Japanese CherryBrowse to the second image folder, Cognitive-CustomVision-Windows / Samples / Images / Japanese Cherry. 选择文件夹中的所有 10 个图像,然后单击“打开”。 Select all 10 images in the folder and then Open.

  9. 将标记“日本樱花” 添加到此组图像,然后按 Enter 应用该标记。Add the tag japanese cherry to this group of images and press enter to apply the tag.

  10. 选择“上传 10 个文件”。 Select Upload 10 files. 成功上传图像以后,选择“完成”。 When the images are uploaded successfully, select Done.

  11. 将两组图像标记并上传后,请选择“训练”,对分类器进行训练。 When both sets of images are tagged and uploaded, select Train to train the classifier.

导出分类器Export your classifier

  1. 训练分类器以后,请在分类器的“性能”页上选择“导出”。 After training your classifier, select Export on the Performance page of the classifier.


  2. 选择“DockerFile” 作为平台。Select DockerFile for the platform.

  3. 选择“Linux” 作为版本。Select Linux for the version.

  4. 选择“导出”。 Select Export.

    导出为带 Linux 容器的 DockerFile

  5. 导出完成后,选择“下载”,将 .zip 包保存到本地计算机。When the export is complete, select Download and save the .zip package locally on your computer. 从包中提取所有文件。Extract all files from the package. 将使用这些文件创建一个包含图像分类服务器的 IoT Edge 模块。You'll use these files to create an IoT Edge module that contains the image classification server.

此时,你已完成自定义视觉项目的创建和训练。When you reach this point, you've finished creating and training your Custom Vision project. 将在下一部分使用导出的文件,但现在已完成自定义视觉网页的操作。You'll use the exported files in the next section, but you're done with the Custom Vision web page.

创建 IoT Edge 解决方案Create an IoT Edge solution

现在,开发计算机上有了适用于容器版图像分类器的文件。Now you have the files for a container version of your image classifier on your development machine. 在此部分,请将图像分类器容器配置为以 IoT Edge 模块方式运行。In this section, you configure the image classifier container to run as an IoT Edge module. 此外还创建另一个将与图像分类器一起部署的模块。You also create a second module that will be deployed alongside the image classifier. 第二个模块将请求发布到分类器,并将结果以消息形式发送到 IoT 中心。The second module posts requests to the classifier and sends the results as messages to IoT Hub.

创建新的解决方案Create a new solution

可以通过解决方案以逻辑方式为单个 IoT Edge 部署开发和组织多个模块。A solution is a logical way of developing and organizing multiple modules for a single IoT Edge deployment. 解决方案包含适用于一个或多个模块的代码,另外还包含部署清单,用于声明如何在 IoT Edge 设备上配置模块。A solution contains code for one or more modules as well as the deployment manifest that declares how to configure them on an IoT Edge device.

  1. 在 Visual Studio Code 中,选择“查看” > “命令面板”,以打开 VS Code 命令面板。In Visual Studio Code, select View > Command Palette to open the VS Code command palette.

  2. 在“命令面板”中,输入并运行 Azure IoT Edge:New IoT Edge solution 命令。In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. 在命令面板中提供以下信息,以便创建解决方案:In the command palette, provide the following information to create your solution:

    字段Field Value
    选择文件夹Select folder 在适用于 VS Code 的开发计算机上选择用于创建解决方案文件的位置。Choose the location on your development machine for VS Code to create the solution files.
    提供解决方案名称Provide a solution name 输入解决方案的描述性名称(例如 CustomVisionSolution),或者接受默认名称。Enter a descriptive name for your solution, like CustomVisionSolution, or accept the default.
    选择模块模板Select module template 选择“Python 模块”。 Choose Python Module.
    提供模块名称Provide a module name 将模块命名为 classifierName your module classifier.

    必须确保此模块名称为小写。It's important that this module name be lowercase. IoT Edge 在引用模块时区分大小写,而此解决方案使用的库会将所有请求格式化为小写。IoT Edge is case-sensitive when referring to modules, and this solution uses a library that formats all requests in lowercase.
    为模块提供 Docker 映像存储库Provide Docker image repository for the module 映像存储库包含容器注册表的名称和容器映像的名称。An image repository includes the name of your container registry and the name of your container image. 容器映像是在上一步预先填充的。Your container image is prepopulated from the last step. 将 localhost:5000 替换为 Azure 容器注册表中的“登录服务器”值 。Replace localhost:5000 with the Login server value from your Azure container registry. 可以在 Azure 门户的容器注册表的“概述”页中检索登录服务器。You can retrieve the Login server from the Overview page of your container registry in the Azure portal.

    最终的字符串看起来类似于 <registry name>.azurecr.cn/classifierThe final string looks like <registry name>.azurecr.cn/classifier.

    提供 Docker 映像存储库

Visual Studio Code 窗口会加载 IoT Edge 解决方案工作区。The Visual Studio Code window loads your IoT Edge solution workspace.

添加注册表凭据Add your registry credentials

环境文件存储容器注册表的凭据,并将其与 IoT Edge 运行时共享。The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime. 此运行时需要这些凭据才能将专用映像拉取到 IoT Edge 设备中。The runtime needs these credentials to pull your private images onto the IoT Edge device.

IoT Edge 扩展尝试从 Azure 中拉取容器注册表凭据并将其填充到环境文件中。The IoT Edge extension tries to pull your container registry credentials from Azure and populate them in the environment file. 检查凭据是否已包含在内。Check to see if your credentials are already included. 如果没有,请立即添加:If not, add them now:

  1. 在 VS Code 资源管理器中,打开 .env 文件。In the VS Code explorer, open the .env file.
  2. 使用从 Azure 容器注册表复制的 usernamepassword 值更新相关字段。Update the fields with the username and password values that you copied from your Azure container registry.
  3. 保存此文件。Save this file.

选择目标体系结构Select your target architecture

目前,Visual Studio Code 可以为 Linux AMD64 和 Linux ARM32v7 设备开发模块。Currently, Visual Studio Code can develop modules for Linux AMD64 and Linux ARM32v7 devices. 需要选择面向每个解决方案的体系结构,因为每种体系结构类型的容器的生成和运行方式均不相同。You need to select which architecture you're targeting with each solution, because the container is built and run differently for each architecture type. 默认值为 Linux AMD64,我们将在本教程中使用此功能。The default is Linux AMD64, which is what we'll use for this tutorial.

  1. 打开命令面板并搜索 Azure IoT Edge:Set Default Target Platform for Edge Solution,或选择窗口底部侧栏中的快捷方式图标。Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge Solution, or select the shortcut icon in the side bar at the bottom of the window.

  2. 在命令面板中,从选项列表中选择目标体系结构。In the command palette, select the target architecture from the list of options. 在本教程中,我们使用 Ubuntu 虚拟机作为 IoT Edge 设备,因此将保留默认的“amd64” 。For this tutorial, we're using an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.

添加图像分类器Add your image classifier

Visual Studio Code 中的 Python 模块模板包含一些可以在运行后对 IoT Edge 进行测试的示例代码。The Python module template in Visual Studio code contains some sample code that you can run to test IoT Edge. 在本方案中不需使用该代码。You won't use that code in this scenario. 请按照此部分的步骤将示例代码替换为以前导出的图像分类器容器。Instead, use the steps in this section to replace the sample code with the image classifier container that you exported previously.

  1. 在文件资源管理器中,浏览到已下载并提取的自定义视觉包。In your file explorer, browse to the Custom Vision package that you downloaded and extracted. 复制已提取包中的所有内容。Copy all the contents from the extracted package. 其中应该有两个文件夹(appazureml)和两个文件(DockerfileREADME)。It should be two folders, app and azureml, and two files, Dockerfile and README.

  2. 在文件资源管理器中,浏览到曾经要求 Visual Studio Code 在其中创建 IoT Edge 解决方案的目录。In your file explorer, browse to the directory where you told Visual Studio Code to create your IoT Edge solution.

  3. 打开 classifier 模块文件夹。Open the classifier module folder. 如果在上一部分使用了建议的名称,则文件夹结构将类似于 CustomVisionSolution / modules / classifierIf you used the suggested names in the previous section, the folder structure looks like CustomVisionSolution / modules / classifier.

  4. 将文件粘贴到 classifier 文件夹中。Paste the files into the classifier folder.

  5. 返回到 Visual Studio Code 窗口。Return to the Visual Studio Code window. 解决方案工作区现在会显示模块文件夹中的图像分类器文件。Your solution workspace should now show the image classifier files in the module folder.


  6. 打开 classifier 文件夹中的 module.json 文件。Open the module.json file in the classifier folder.

  7. 更新 platforms 参数,使其指向你添加的新 Dockerfile,并删除 AMD64 之外的所有选项,这是我们在本教程中唯一使用的体系结构。Update the platforms parameter to point to the new Dockerfile that you added, and remove all the options besides AMD64, which is the only architecture we're using for this tutorial.

    "platforms": {
        "amd64": "./Dockerfile"
  8. 保存所做更改。Save your changes.

创建模拟摄像头模块Create a simulated camera module

在实际的自定义视觉部署中,会有一个提供实时图像或视频流的摄像头。In a real Custom Vision deployment, you would have a camera providing live images or video streams. 在本方案中,请生成一个可以向图像分类器发送测试图像的模块来模拟摄像头。For this scenario, you simulate the camera by building a module that sends a test image to the image classifier.

添加并配置新模块Add and configure a new module

在此部分,请将新模块添加到同一 CustomVisionSolution 并提供创建模拟摄像头所需的代码。In this section, you add a new module to the same CustomVisionSolution and provide code to create the simulated camera.

  1. 在同一 Visual Studio Code 窗口中,使用命令面板运行 Azure IoT Edge: Add IoT Edge Module”。In the same Visual Studio Code window, use the command palette to run Azure IoT Edge: Add IoT Edge Module. 在命令面板中提供新模块所需的以下信息:In the command palette, provide the following information for your new module:

    PromptPrompt Value
    选择部署模板文件Select deployment template file 选择 CustomVisionSolution 文件夹中的 deployment.template.json 文件。Select the deployment.template.json file in the CustomVisionSolution folder.
    选择模块模板Select module template 选择“Python 模块”Select Python Module
    提供模块名称Provide a module name 将模块命名为 cameraCaptureName your module cameraCapture
    为模块提供 Docker 映像存储库Provide Docker image repository for the module 将 localhost:5000 替换为 Azure 容器注册表的登录服务器值。Replace localhost:5000 with the Login server value for your Azure container registry.

    最终的字符串看起来类似于 <registryname>.azurecr.cn/cameracaptureThe final string looks like <registryname>.azurecr.cn/cameracapture.

    VS Code 窗口会加载解决方案工作区中的新模块,并会更新 deployment.template.json 文件。The VS Code window loads your new module in the solution workspace, and updates the deployment.template.json file. 现在会看到两个模块文件夹:classifier 和 cameraCapture。Now you should see two module folders: classifier and cameraCapture.

  2. 打开 modules / cameraCapture 文件夹中的 main.py 文件。Open the main.py file in the modules / cameraCapture folder.

  3. 将整个文件替换为以下代码。Replace the entire file with the following code. 此示例代码将 POST 请求发送到在 classifier 模块中运行的图像处理服务。This sample code sends POST requests to the image-processing service running in the classifier module. 我们提供的此模块容器包含可在请求中使用的示例图像。We provide this module container with a sample image to use in the requests. 此示例代码随后将响应打包为 IoT 中心消息并发送到输出队列。It then packages the response as an IoT Hub message and sends it to an output queue.

    # Copyright (c) Microsoft. All rights reserved.
    # Licensed under the MIT license. See LICENSE file in the project root for
    # full license information.
    import time
    import sys
    import os
    import requests
    import json
    from azure.iot.device import IoTHubModuleClient, Message
    # global counters
    # global client
    CLIENT = None
    # Send a message to IoT Hub
    # Route output1 to $upstream in deployment.template.json
    def send_to_hub(strMessage):
        message = Message(bytearray(strMessage, 'utf8'))
        CLIENT.send_message_to_output(message, "output1")
        global SENT_IMAGES
        SENT_IMAGES += 1
        print( "Total images sent: {}".format(SENT_IMAGES) )
    # Send an image to the image classifying server
    # Return the JSON response from the server with the prediction result
    def sendFrameForProcessing(imagePath, imageProcessingEndpoint):
        headers = {'Content-Type': 'application/octet-stream'}
        with open(imagePath, mode="rb") as test_image:
                response = requests.post(imageProcessingEndpoint, headers = headers, data = test_image)
                print("Response from classification service: (" + str(response.status_code) + ") " + json.dumps(response.json()) + "\n")
            except Exception as e:
                print("No response from classification service")
                return None
        return json.dumps(response.json())
    def main(imagePath, imageProcessingEndpoint):
            print ( "Simulated camera module for Azure IoT Edge. Press Ctrl-C to exit." )
                global CLIENT
                CLIENT = IoTHubModuleClient.create_from_edge_environment()
            except Exception as iothub_error:
                print ( "Unexpected error {} from IoTHub".format(iothub_error) )
            print ( "The sample is now sending images for processing and will indefinitely.")
            while True:
                classification = sendFrameForProcessing(imagePath, imageProcessingEndpoint)
                if classification:
        except KeyboardInterrupt:
            print ( "IoT Edge module sample stopped" )
    if __name__ == '__main__':
            # Retrieve the image location and image classifying server endpoint from container environment
            IMAGE_PATH = os.getenv('IMAGE_PATH', "")
        except ValueError as error:
            print ( error )
            print ( "Error: Image path or image-processing endpoint missing" )
  4. 保存 main.py 文件。Save the main.py file.

  5. 打开 requrements.txt 文件。Open the requrements.txt file.

  6. 为将要包括在容器中的库添加新的一行。Add a new line for a library to include in the container.

  7. 保存 requirements.txt 文件。Save the requirements.txt file.

向容器添加测试图像Add a test image to the container

我们将使用单个测试图像,而不会通过实际摄像头来提供此方案的图像源。Instead of using a real camera to provide an image feed for this scenario, we're going to use a single test image. 测试图像包含在 GitHub 存储库中,你在本教程前面已下载适用于训练图像的该库。A test image is included in the GitHub repo that you downloaded for the training images earlier in this tutorial.

  1. 导航到 Cognitive-CustomVision-Windows / Samples / Images / Test 中的测试图像。Navigate to the test image, located at Cognitive-CustomVision-Windows / Samples / Images / Test.

  2. 复制 test_image.jpgCopy test_image.jpg

  3. 浏览到 IoT Edge 解决方案目录,将测试图像粘贴到 modules / cameraCapture 文件夹中。Browse to your IoT Edge solution directory and paste the test image in the modules / cameraCapture folder. 该图像应该置于你在上一部分编辑的 main.py 文件所在的文件夹中。The image should be in the same folder as the main.py file that you edited in the previous section.

  4. 在 Visual Studio Code 中打开适用于 cameraCapture 模块的 Dockerfile.amd64 文件。In Visual Studio Code, open the Dockerfile.amd64 file for the cameraCapture module.

  5. 在建立工作目录 WORKDIR /app 的行后面,添加以下代码行:After the line that establishes the working directory, WORKDIR /app, add the following line of code:

    ADD ./test_image.jpg .
  6. 保存 Dockerfile。Save the Dockerfile.

准备部署清单Prepare a deployment manifest

到目前为止,你已在本教程中训练了一个用于对树的图像分类的自定义视觉模型,并且已将该模型打包成一个 IoT Edge 模块。So far in this tutorial you've trained a Custom Vision model to classify images of trees, and packaged that model up as an IoT Edge module. 然后,你创建了另一个模块,该模块可以查询图像分类服务器并将其结果报告回 IoT 中心。Then, you created a second module that can query the image classification server and report its results back to IoT Hub. 现在可以创建部署清单了。该清单会告知 IoT Edge 设备如何同时启动并运行这两个模块。Now, you're ready to create the deployment manifest that will tell an IoT Edge device how to start and run these two modules together.

适用于 Visual Studio Code 的 IoT Edge 扩展在每个 IoT Edge 解决方案中提供了一个模板,用于创建部署清单。The IoT Edge extension for Visual Studio Code provides a template in each IoT Edge solution to help you create a deployment manifest.

  1. 在解决方案文件夹中打开 deployment.template.json 文件。Open the deployment.template.json file in the solution folder.

  2. 找到 modules 节,其中应包含三个模块:两个你创建的,即 classifier 和 cameraCapture,第三个是默认包含的,即 SimulatedTemperatureSensor。Find the modules section, which should contain three modules: the two that you created, classifier and cameraCapture, and a third that's included by default, SimulatedTemperatureSensor.

  3. 删除 SimulatedTemperatureSensor 模块及其所有参数。Delete the SimulatedTemperatureSensor module with all of its parameters. 包括此模块是为了提供测试方案的示例数据,但我们在此部署中不需要它。This module is included to provide sample data for test scenarios, but we don't need it in this deployment.

  4. 如果为图像分类模块提供了 classifier 之外的名称,现在请检查该名称,确保其采用全小写形式。If you named the image classification module something other than classifier, check the name now and ensure that it's all lowercase. cameraCapture 模块调用 classifier 模块时使用的请求库可以将所有请求格式化为小写,而 IoT Edge 区分大小写。The cameraCapture module calls the classifier module using a requests library that formats all requests in lowercase, and IoT Edge is case-sensitive.

  5. 使用以下 JSON 更新 cameraCapture 模块的 createOptions 参数。Update the createOptions parameter for the cameraCapture module with the following JSON. 此信息在模块容器中创建环境变量,该容器是在 main.py 进程中检索的。This information creates environment variables in the module container that are retrieved in the main.py process. 将此信息包含在部署清单中即可更改图像或终结点,不需重新生成模块图像。By including this information in the deployment manifest, you can change the image or endpoint without having to rebuild the module image.

    "createOptions": "{\"Env\":[\"IMAGE_PATH=test_image.jpg\",\"IMAGE_PROCESSING_ENDPOINT=http://classifier/image\"]}"

    如果为自定义视觉模块提供了 classifier 之外的名称,请更新图像处理终结点值,使之匹配。If you named your Custom Vision module something other than classifier, update the image-processing endpoint value to match.

  6. 在文件底部,更新 $edgeHub 模块的 routes 参数。At the bottom of the file, update the routes parameter for the $edgeHub module. 你希望将预测结果从 cameraCapture 路由到 IoT 中心。You want to route the prediction results from cameraCapture to IoT Hub.

        "routes": {
          "cameraCaptureToIoTHub": "FROM /messages/modules/cameraCapture/outputs/* INTO $upstream"

    如果为第二个模块提供了 cameraCapture 之外的名称,请更新路由值,使之匹配。If you named your second module something other than cameraCapture, update the route value to match.

  7. 保存 deployment.template.json 文件。Save the deployment.template.json file.

生成并推送 IoT Edge 解决方案Build and push your IoT Edge solution

创建两个模块并配置部署清单模板以后,即可生成容器映像并将其推送到容器注册表。With both modules created and the deployment manifest template configured, you're ready to build the container images and push them to your container registry.

映像位于注册表中以后,即可将解决方案部署到 IoT Edge 设备。Once the images are in your registry, you can deploy the solution to an IoT Edge device. 可以通过 IoT 中心设置设备上的模块,但是也可以通过 Visual Studio Code 访问 IoT 中心和设备。You can set modules on a device through the IoT Hub, but you can also access your IoT Hub and devices through Visual Studio Code. 在此部分,请先设置对 IoT 中心的访问权限,然后使用 VS Code 将解决方案部署到 IoT Edge 设备。In this section, you set up access to your IoT Hub then use VS Code to deploy your solution to your IoT Edge device.

首先,生成解决方案并将其推送到容器注册表。First, build and push your solution to your container registry.

  1. 打开 VS Code 集成终端,方法是选择“视图” > “终端” 。Open the VS Code integrated terminal by selecting View > Terminal.

  2. 在终端中输入以下命令,以登录到 Docker。Sign in to Docker by entering the following command in the terminal. 使用 Azure 容器注册表中的用户名、密码和登录服务器登录。Sign in with the username, password, and login server from your Azure container registry. 可以在 Azure 门户中从注册表的“访问密钥”部分检索这些值。You can retrieve these values from the Access keys section of your registry in the Azure portal.

    docker login -u <ACR username> -p <ACR password> <ACR login server>

    可能会收到一条安全警告,推荐使用 --password-stdinYou may receive a security warning recommending the use of --password-stdin. 这条最佳做法是针对生产方案建议的,这超出了本教程的范畴。While that best practice is recommended for production scenarios, it's outside the scope of this tutorial. 有关详细信息,请参阅 docker login 参考。For more information, see the docker login reference.

  3. 在 VS Code 资源管理器中右键单击“deployment.template.json”文件,然后选择“生成并推送 IoT Edge 解决方案”。In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT Edge solution.

    “生成并推送”命令会启动三项操作。The build and push command starts three operations. 首先,它在解决方案中创建名为 config 的新文件夹,用于保存基于部署模板和其他解决方案文件中的信息生成的完整部署清单。First, it creates a new folder in the solution called config that holds the full deployment manifest, which is built out of information in the deployment template and other solution files. 其次,它会运行 docker build,以基于目标体系结构的相应 dockerfile 生成容器映像。Second, it runs docker build to build the container image based on the appropriate dockerfile for your target architecture. 然后,它会运行 docker push,以将映像存储库推送到容器注册表。Then, it runs docker push to push the image repository to your container registry.

    首次执行此过程可能需要几分钟时间,但下次运行命令时速度会变快。This process may take several minutes the first time, but is faster the next time that you run the commands.

将模块部署到设备Deploy modules to device

使用 Visual Studio Code 资源管理器和 Azure IoT Tools 扩展将模块项目部署到 IoT Edge 设备。Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT Edge device. 你已经为方案准备了部署清单,即 config 文件夹中的 deployment.amd64.json 文件。You already have a deployment manifest prepared for your scenario, the deployment.amd64.json file in the config folder. 现在需要做的就是选择一个设备来接收部署。All you need to do now is select a device to receive the deployment.

确保 IoT Edge 设备已启动并运行。Make sure that your IoT Edge device is up and running.

  1. 在 Visual Studio Code 资源管理器中的“Azure IoT 中心”部分下,展开“设备”可查看 IoT 设备的列表。 In the Visual Studio Code explorer, under the Azure IoT Hub section, expand Devices to see your list of IoT devices.

  2. 右键单击 IoT Edge 设备的名称,然后选择“为单个设备创建部署”。Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.

  3. 选择 config 文件夹中的 deployment.amd64.json 文件,然后单击“选择 Edge 部署清单”。 Select the deployment.amd64.json file in the config folder and then click Select Edge Deployment Manifest. 不要使用 deployment.template.json 文件。Do not use the deployment.template.json file.

  4. 在设备下,展开“模块”可查看已部署的正在运行的模块的列表。Under your device, expand Modules to see a list of deployed and running modules. 单击“刷新”按钮。Click the refresh button. 此时应看到新的 classifier 和 cameraCapture 模块与 $edgeAgent 和 $edgeHub 一起运行 。You should see the new classifier and cameraCapture modules running along with the $edgeAgent and $edgeHub.

也可查看设备本身上的所有模块是否都已启动并运行。You can also check to see that all the modules are up and running on your device itself. 在 IoT Edge 设备上运行以下命令,以便查看模块的状态。On your IoT Edge device, run the following command to see the status of the modules.

iotedge list

启动模块可能需要数分钟时间。It may take a few minutes for the modules to start. IoT Edge 运行时需要接收其新的部署清单,从容器运行时下拉模块映像,然后启动每个新模块。The IoT Edge runtime needs to receive its new deployment manifest, pull down the module images from the container runtime, then start each new module.

查看分类结果View classification results

可以通过两种方式来查看模块的结果,一种是生成和发送消息时在设备本身上查看,另一种是在消息到达 IoT 中心时通过 Visual Studio Code 查看。There are two ways to view the results of your modules, either on the device itself as the messages are generated and sent, or from Visual Studio Code as the messages arrive at IoT Hub.

通过设备查看 cameraCapture 模块的日志,了解发送消息以后系统确认 IoT 中心接收到消息这一过程。From your device, view the logs of the cameraCapture module to see the messages being sent and the confirmation that they were received by IoT Hub.

iotedge logs cameraCapture

在 Visual Studio Code 中右键单击 IoT Edge 设备的名称,选择“开始监视内置事件终结点”。From Visual Studio Code, right-click on the name of your IoT Edge device and select Start Monitoring Built-in Event Endpoint.


最初可能会在 cameraCapture 模块的输出中看到连接错误。Initially, you may see connection errors in the output from the cameraCapture module. 这是由于所部署的模块与启动的模块之间的延迟导致的。This is due to the delay between modules being deployed and starting.

cameraCapture 模块会自动重新尝试连接,直至成功。The cameraCapture module automatically reattempts connection until successful. 成功连接后,你将看到如下所述的预期图像分类消息。After successful connection, you will see the expected image classification messages described below.

自定义视觉模块中的结果是从 cameraCapture 模块作为消息发送的,其中包括图像为铁杉树或樱花树的概率。The results from the Custom Vision module, which are sent as messages from the cameraCapture module, include the probability that the image is of either a hemlock or cherry tree. 由于图像为铁杉,因此会看到概率为 1.0。Since the image is hemlock, you should see the probability as 1.0.

清理资源Clean up resources

如果打算继续学习下一篇建议的文章,可以保留已创建的资源和配置,以便重复使用。If you plan to continue to the next recommended article, you can keep the resources and configurations that you created and reuse them. 还可以继续使用相同的 IoT Edge 设备作为测试设备。You can also keep using the same IoT Edge device as a test device.

否则,可以删除本文中使用的本地配置和 Azure 资源,以免产生费用。Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid charges.

删除 Azure 资源Delete Azure resources

删除 Azure 资源和资源组的操作不可逆。Deleting Azure resources and resource groups is irreversible. 请确保不要意外删除错误的资源组或资源。Make sure that you don't accidentally delete the wrong resource group or resources. 如果在现有的包含要保留资源的资源组中创建了 IoT 中心,请只删除 IoT 中心资源本身,而不要删除资源组。If you created the IoT hub inside an existing resource group that has resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.

若要删除资源,请执行以下操作:To delete the resources:

  1. 登录到 Azure 门户,然后选择“资源组”。 Sign in to the Azure portal and select Resource groups.

  2. 选择包含 IoT Edge 测试资源的资源组的名称。Select the name of the resource group that contains your IoT Edge test resources.

  3. 查看包含在资源组中的资源的列表。Review the list of resources contained in your resource group. 若要删除这一切,可以选择“删除资源组”。 If you want to delete all of them, you can select Delete resource group. 如果只需删除部分内容,可以单击要单独删除的每个资源。If you want to delete only some of them, you can click into each resource to delete them individually.

后续步骤Next steps

在本教程中,你训练了一个自定义视觉模型并将其作为模块部署到了 IoT Edge 设备中。In this tutorial, you trained a Custom Vision model and deployed it as a module onto an IoT Edge device. 然后,你生成了一个模块,该模块可以查询图像分类服务并将其结果报告回 IoT 中心。Then you built a module that can query the image classification service and report its results back to IoT Hub.

继续阅读后续教程,了解如何使用 Azure IoT Edge 通过其他方式将数据转化为边缘业务见解。Continue on to the next tutorials to learn about other ways that Azure IoT Edge can help you turn data into business insights at the edge.