次の方法で共有


チュートリアル:Custom Vision Service を使用してエッジで画像の分類を実行する

適用対象:IoT Edge 1.5 のチェックマーク IoT Edge 1.5

重要

IoT Edge 1.5 LTS は、サポートされているリリースです。 IoT Edge 1.4 LTS は、2024 年 11 月 12 日をもってサポートが終了しています。 以前のリリースの場合は、「IoT Edge を更新する」を参照してください。

Azure IoT Edge を使用すると、クラウドからエッジにワークロードを移動することで、IoT ソリューションの効率が向上します。 この機能は、コンピューター ビジョン モデルのような、大量のデータを処理するサービスに適しています。 Azure AI Custom Vision を使用すると、カスタム画像分類器を構築して、コンテナーとしてデバイスにデプロイすることができます。 これら 2 つのサービスを組み合わせることで、ユーザーは最初にすべてのデータをオフサイトに転送することなく、画像またはビデオ ストリームから分析情報を見つけることができます。 Custom Vision には、分析情報を生成するためにトレーニング済みのモデルと画像を比較する分類子が用意されています。

たとえば、IoT Edge デバイス上の Custom Vision では、高速道路のトラフィックが通常よりも高いか低いか、駐車ガレージに連続して使用可能な駐車スポットがあるかが決まります。 これらの分析情報は、アクションを実行する別のサービスと共有できます。

このチュートリアルでは、以下の内容を学習します。

  • Custom Vision を使用して、画像分類器を構築する。
  • デバイス上の Custom Vision Web サーバーに対してクエリを実行する IoT Edge モジュールを開発します。
  • 画像分類子の結果を IoT Hub に送信します。

図 - チュートリアルのアーキテクチャ、分類器のステージングとデプロイ

Azure アカウントをお持ちでない場合は、開始する前に無料アカウントを作成してください。

前提条件

ヒント

このチュートリアルは、Raspberry Pi 3 での Custom Vision と Azure IoT Edge サンプル プロジェクトの簡易バージョンです。 クラウド VM 上で実行され、静的イメージを使用して画像分類子をトレーニングおよびテストします。これは、Custom Vision on IoT Edge を初めて使用するユーザーに役立ちます。 サンプル プロジェクトでは、物理ハードウェアを使用し、ライブ カメラ フィードを設定して画像分類器をトレーニングおよびテストします。これは、より詳細で実際のシナリオを調査するユーザーに役立ちます。

Custom Vision を使用して画像分類器を構築する

画像分類子を構築するには、Custom Vision プロジェクトを作成し、トレーニング画像を提供します。 このセクションで行う手順の詳細については、「Custom Vision で分類子を構築する方法」を参照してください。

イメージ分類子を構築してトレーニングした後、それを Docker コンテナーとしてエクスポートし、IoT Edge デバイスにデプロイします。

新しいプロジェクトを作成する

  1. Web ブラウザーで、Custom Vision の Web ページに移動します。

  2. [サインイン] を選択し、Azure リソースへのアクセスに使用するのと同じアカウントを使用してサインインします。

  3. [新しいプロジェクト] を選択します。

  4. 以下の値を設定して、プロジェクトを作成します。

    フィールド
    名前 EdgeTreeClassifier など、プロジェクトの名前を指定します。
    説明 オプションのプロジェクトの説明。
    リソース Custom Vision Service リソースを含む Azure リソース グループを 1 つ選択するか、まだ追加していない場合は新規作成します。
    プロジェクトの種類 分類
    分類の種類 [Multiclass (single tag per image)](マルチクラス (画像ごとに 1 つのタグ))
    ドメイン [General (compact)](汎用 (コンパクト))
    Export Capabilities (エクスポート機能) 基本プラットフォーム (TensorFlow、CoreML、ONNX、...)
  5. [プロジェクトの作成] を選択します。

画像をアップロードして分類器をトレーニングする

画像分類器を作成するには、トレーニング画像のセットと、テスト画像が必要です。

  1. Cognitive-CustomVision-Windows リポジトリのサンプル画像を、ローカル開発マシンに複製またはダウンロードします。

    git clone https://github.com/Microsoft/Cognitive-CustomVision-Windows.git
    
  2. Custom Vision プロジェクトに戻り、 [Add images](画像の追加) を選択します。

  3. ローカルに複製した Git リポジトリを参照し、最初の画像フォルダー Cognitive-CustomVision-Windows/Samples/Images/Hemlock に移動します。 フォルダー内の 10 個の画像をすべて選択し、[ 開く] を選択します。

  4. この画像グループにタグ のヘムロック を追加し、 Enter キーを押してタグを適用します。

  5. [Upload 10 files](10 ファイルをアップロード) を選択します。

    Custom Vision にドクニンジンのタグが付けられたファイルをアップロードする

  6. 画像が正常にアップロードされたら、 [完了] を選択します。

  7. [Add images](画像の追加) をもう一度選択します。

  8. 2 つ目の画像フォルダー Cognitive-CustomVision-Windows/Samples/Images/Japanese Cherry を参照します。 フォルダー内の 10 個の画像をすべて選択し、 [開く] を選択します。

  9. この画像のグループにタグ japanese cherry を追加し、Enter キーを押してタグを適用します。

  10. [Upload 10 files](10 ファイルをアップロード) を選択します。 画像が正常にアップロードされたら、 [完了] を選択します。

  11. 両方の画像セットにタグを付けてアップロードした後、[ トレーニング ] を選択して分類子をトレーニングします。

分類器をエクスポートする

  1. 分類器をトレーニングした後、分類器の [パフォーマンス] ページで [エクスポート] を選択します。

    トレーニング済みの画像分類器をエクスポートする

  2. プラットフォームとして [DockerFile] を選択します。

  3. バージョンとして [Linux] を選択します。

  4. [エクスポート] を選択します。

  5. エクスポートが完了したら、[ ダウンロード ] を選択し、.zip パッケージをコンピューターにローカルに保存します。 パッケージのすべてのファイルを展開します。 これらのファイルを使用して、画像分類サーバーを含む IoT Edge モジュールを作成します。

ここまでで、Custom Vision プロジェクトの作成とトレーニングが完了しました。 次のセクションでは、エクスポートしたファイルを使用します。Custom Vision Web ページの使用は、これで終了です。

IoT Edge ソリューションを作成する

これで、開発用コンピューター上のイメージ分類子のコンテナー バージョンのファイルが作成されました。 このセクションでは、IoT Edge モジュールとして実行する画像分類子コンテナーを設定します。 また、分類子に要求を投稿し、結果をメッセージとして IoT Hub に送信する 2 つ目のモジュールも作成します。

新しいソリューションの作成

ソリューションとは、単一の IoT Edge デプロイ用に複数のモジュールを開発、整理するための論理的な方法のことです。 ソリューションには、1 つ以上のモジュールのコードと、それらを IoT Edge デバイス上でどのように構成するかを宣言する配置マニフェストが含まれています。 Azure IoT Edge Dev Tool コマンド ライン (CLI) 開発ツールを使用してソリューションを作成します。 このツールを使用する最も簡単な方法は、 Docker で IoT Edge 開発コンテナーを実行することです

  1. 分類子という名前のディレクトリを作成し、ディレクトリに変更します。

    mkdir CustomVisionSolution
    cd CustomVisionSolution
    
  2. iotedgedev ツールの init コマンドを実行して、新しい IoT Edge ソリューションを作成します。 IoT Edge Dev Docker コンテナーで、次のコマンドを入力します。

    iotedgedev solution init --template python --module classifier
    

    iotedgedev ソリューション init スクリプトでは、次のようないくつかの手順を完了するように求められます。

    • Azure に対して認証します
    • Azure サブスクリプションを選択する
    • リソース グループを選択または作成する
    • Azure IoT Hub を選択または作成する
    • Azure IoT Edge デバイスを選択または作成する

    このコマンドは、現在の作業ディレクトリに 分類子 という名前のモジュールを含む新しい IoT Edge ソリューションを作成します。

  3. Visual Studio Code でソリューションを開きます。

画像分類器を追加する

Visual Studio Code の Python モジュール テンプレートには、IoT Edge をテストするために実行できるいくつかのサンプル コードが含まれています。 このシナリオでは、そのコードを使用しません。 代わりに、このセクションの手順を使用して、前にエクスポートした画像分類器コンテナーでサンプル コードを置き換えます。

  1. エクスプローラーで、ダウンロードして展開した Custom Vision パッケージを参照します。 展開したパッケージ内のすべての内容をコピーします。 2 つのフォルダー (appazureml) および 2 つのファイル (DockerfileREADME) であるはずです。

  2. エクスプローラーで、Visual Studio Code に IoT Edge ソリューションを作成する場所として指定したディレクトリを参照します。

  3. 分類器モジュール フォルダーを開きます。 前のセクションで提案された名前を使用した場合、フォルダー構造は CustomVisionSolution/modules/classifier のようになります。

  4. classifier フォルダーにファイルを貼り付けます。

  5. Visual Studio Code ウィンドウに戻ります。 今度は、ソリューション ワークスペースで、モジュール フォルダーに画像分類器ファイルが表示されます。

  6. 元の Dockerfile.amd64 ファイルをカスタム ビジョン パッケージから Dockerfile に置き換えます。元の Dockerfile.amd64 を削除し、Dockerfile の名前を Dockerfile.amd64 に変更します。

  7. 変更を保存します。

シミュレートされたカメラ モジュールを作成する

実際のカスタム ビジョンの展開では、カメラはライブ画像またはビデオ ストリームを提供します。 このシナリオでは、画像分類器にテスト画像を送信するモジュールを構築することにより、カメラをシミュレートします。

このセクションでは、同じ CustomVisionSolution に新しいモジュールを追加し、シミュレートされたカメラを作成するコードを設定します。

  1. iotedgedev ツールを使用して、ソリューションに新しいモジュールを追加します。 このコマンドにより、ソリューションの modules フォルダーに cameracapture という名前の新しいフォルダーが作成されます。

    iotedgedev solution add --template python cameracapture
    
  2. modules / フォルダー内の main.py ファイルを開きます。

  3. ファイル全体を次のコードに置き換えます。 このサンプル コードにより、分類器モジュールで実行されている画像処理サービスに POST 要求が送信されます。 このモジュール コンテナーに、要求で使用するサンプル画像を提供します。 その後、応答が IoT Hub メッセージとしてパッケージ化され、出力キューに送信されます。

    # 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
    SENT_IMAGES = 0
    
    # 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:
            try:
                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(e)
                print("No response from classification service")
                return None
    
        return json.dumps(response.json())
    
    def main(imagePath, imageProcessingEndpoint):
        try:
            print ( "Simulated camera module for Azure IoT Edge. Press Ctrl-C to exit." )
    
            try:
                global CLIENT
                CLIENT = IoTHubModuleClient.create_from_edge_environment()
            except Exception as iothub_error:
                print ( "Unexpected error {} from IoTHub".format(iothub_error) )
                return
    
            print ( "The sample is now sending images for processing and will indefinitely.")
    
            while True:
                classification = sendFrameForProcessing(imagePath, imageProcessingEndpoint)
                if classification:
                    send_to_hub(classification)
                time.sleep(10)
    
        except KeyboardInterrupt:
            print ( "IoT Edge module sample stopped" )
    
    if __name__ == '__main__':
        try:
            # Retrieve the image location and image classifying server endpoint from container environment
            IMAGE_PATH = os.getenv('IMAGE_PATH', "")
            IMAGE_PROCESSING_ENDPOINT = os.getenv('IMAGE_PROCESSING_ENDPOINT', "")
        except ValueError as error:
            print ( error )
            sys.exit(1)
    
        if ((IMAGE_PATH and IMAGE_PROCESSING_ENDPOINT) != ""):
            main(IMAGE_PATH, IMAGE_PROCESSING_ENDPOINT)
        else: 
            print ( "Error: Image path or image-processing endpoint missing" )
    
  4. main.py ファイルを保存します。

  5. requirements.txt ファイルを開きます。

  6. コンテナーに含めるライブラリのための新しい行を追加します。

    requests
    
  7. requirements.txt ファイルを保存します。

テスト画像をコンテナーに追加する

このシナリオで画像フィードを提供するために、実際のカメラを使用する代わりに、単一のテスト画像を使用します。 テスト画像は、GitHub リポジトリに含まれています。これは、このチュートリアルの前の方で画像をトレーニングするためにダウンロードしたものです。

  1. Cognitive-CustomVision-Windows / Samples / Images / Test にあるテスト画像に移動します。

  2. test_image.jpg をコピーします。

  3. IoT Edge ソリューション ディレクトリを参照し、 モジュール / cameracapture フォルダーにテスト イメージを貼り付けます。 この画像は、前のセクションで編集した main.py ファイルと同じフォルダー内にある必要があります。

  4. Visual Studio Code で、cameracapture モジュールの Dockerfile.amd64 ファイルを開きます。

  5. 作業ディレクトリ WORKDIR /app を確立する行の後に、次のコード行を追加します。

    ADD ./test_image.jpg .
    
  6. Dockerfile を保存します。

配置マニフェストを準備する

ここまで、このチュートリアルでは、ツリーの画像を分類し、そのモデルを IoT Edge モジュールとしてパッケージ化するためのカスタム ビジョン モデルをトレーニングしました。 次に、画像分類サーバーに対してクエリを実行し、その結果を IoT Hub に報告する 2 つ目のモジュールを作成しました。 これで、これら 2 つのモジュールを一緒に起動して実行する方法を IoT Edge デバイスに指示する配置マニフェストを作成する準備ができました。

Visual Studio Code 用の IoT Edge 拡張機能では、各 IoT Edge ソリューションに、配置マニフェストの作成を支援するためのテンプレートが用意されています。

  1. ソリューション フォルダー内の deployment.template.json ファイルを開きます。

  2. 配置マニフェストでモジュールのレジストリ資格情報を設定します。

    "registryCredentials": {
        "<registryName>": {
            "username": "<AcrUsername>",
            "password": "<AcrPassword>",
            "address": "<registryName>.azurecr.io"
        }
    }
    

    <registryName>を Azure コンテナー レジストリの名前に置き換え、<AcrUsername><AcrPassword> をレジストリのユーザー名とパスワードに置き換えます。 これらの値は、Azure portal の Azure コンテナー レジストリの [アクセス キー ] セクションで確認できます。

  3. modules セクションを見つけます。これには、作成した 2 つのモジュール、分類子カメラキャプチャ、および既定で含まれる 3 つ目の tempSensor という 3 つのモジュールが含まれています。

  4. すべてのパラメーターを含 む tempSensor モジュールを削除します。 このモジュールでは、テスト シナリオのサンプル データを提供しますが、このデプロイでは必要ありません。

  5. 画像分類モジュールに classifier 以外の名前を付けた場合は、ここで名前の文字がすべて小文字であることを確認してください。 cameracapture モジュールは、すべての要求を小文字で書式設定する要求ライブラリを使用して分類子モジュールを呼び出し、IoT Edge では大文字と小文字が区別されます。

  6. システム モジュール edgeAgentedgeHub ごとに、 createOptions 値を文字列化されたバージョンに変更します。 例えば次が挙げられます。

    "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
    
  7. 各システム モジュール の edgeAgentedgeHub について、イメージのバージョンを最新バージョン 1.5 に変更します。 例えば次が挙げられます。

    "image": "mcr.microsoft.com/azureiotedge-agent:1.5",
    "image": "mcr.microsoft.com/azureiotedge-hub:1.5",
    
  8. 分類子モジュールの createOptions パラメーターを文字列化されたバージョンに更新します。 例えば次が挙げられます。

    "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
    
  9. cameracapture モジュールの createOptions パラメーターを次の JSON で更新します。 この情報によって、モジュール コンテナーに環境変数が作成されます。これらの変数は、main.py プロセスで取得されます。 この情報を配置マニフェストに含めると、モジュール イメージを再構築せずにイメージまたはエンドポイントを変更できます。

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

    Custom Vision モジュールに classifier 以外の名前を付けた場合は、それに一致するように画像処理エンドポイントの値を更新します。

    たとえば、 分類子カメラキャプチャ の構成は次のようになります。

    "modules": {
        "classifier": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
                "image": "${MODULES.classifier}",
                "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
            }
        },
        "cameracapture": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
                "image": "${MODULES.cameracapture}",
                "createOptions": "{\"Env\":[\"IMAGE_PATH=test_image.jpg\",\"IMAGE_PROCESSING_ENDPOINT=http://classifier/image\"]}"
            }
        }
    }
    
  10. deployment.template.json ファイルを保存します。

IoT Edge ソリューションをビルドしてプッシュする

両方のモジュールを作成し、配置マニフェスト テンプレートを構成した後、コンテナー イメージをビルドし、コンテナー レジストリにプッシュします。

レジストリにイメージを配置したら、ソリューションを IoT Edge デバイスにデプロイできます。 IoT Hub を使用してデバイスにモジュールを設定できます。 このセクションでは、IoT Hub へのアクセスを設定し、Azure CLI を使用して IoT Edge デバイスにソリューションをデプロイします。

まず、ソリューションをビルドしてコンテナー レジストリにプッシュします。

  1. [表示]>[ターミナル] の順に選択して、Visual Studio Code 統合ターミナルを開きます。

  2. Azure コンテナー レジストリのユーザー名、パスワード、ログイン サーバーを使用して、ターミナルで次のコマンドを入力して Docker にサインインします。 これらの値は、Azure portal でご自身のレジストリの [アクセス キー] セクションから取得できます。

    docker login -u <AcrUsername> -p <AcrPassword> <AcrLoginServer>
    

    --password-stdin の使用を推奨するセキュリティ警告が表示される場合があります。 このベスト プラクティスは、運用環境のシナリオを対象に推奨されていますが、それはこのチュートリアルの範囲外になります。 詳細については、docker login のリファレンスをご覧ください。

  3. モジュールの Dockerfile を使用して、モジュールの Docker イメージを ビルド してタグ付けします。

    docker build --rm -f "<DockerFilePath>" -t <ImageNameAndTag> "<ContextPath>" 
    

    たとえば、ローカル レジストリまたは Azure コンテナー レジストリのイメージをビルドするには、次のコマンドを使用します。

    
    # Build and tag the image for an Azure Container Registry. Replace <AcrRegistryName> with your own registry name.
    
    docker build --rm -f "./modules/classifier/Dockerfile.amd64" -t <AcrRegistryName>.azurecr.io/classifier:0.0.1-amd64 "./modules/classifier"
    docker build --rm -f "./modules/cameracapture/Dockerfile.amd64" -t <AcrRegistryName>.azurecr.io/cameracapture:0.0.1-amd64 "./modules/cameracapture"
    

モジュールの Docker イメージをプッシュする

コンテナー イメージをレジストリ内のストレージにプッシュできるように、Docker にコンテナー レジステリの資格情報を提供します。

  1. Azure Container Registry (ACR) 資格情報を使って Docker にサインインします。

    docker login -u <AcrUsername> -p <AcrPassword> <AcrLoginServer>
    

    --password-stdin の使用を推奨するセキュリティ警告が表示される場合があります。 これは運用環境のシナリオでの推奨されているベスト プラクティスですが、このチュートリアルの範囲外になります。 詳細については、docker login のリファレンスをご覧ください。

  2. Azure Container Registry にサインインします。 コマンドを使用するには、azする必要があります。 このコマンドは 、設定>Access キーのコンテナー レジストリで見つかったユーザー名とパスワードを要求します。

    az acr login -n <AcrRegistryName>
    

    ヒント

    このチュートリアルの任意の時点でログアウトした場合、Docker および Azure Container Registry のサインイン ステップを繰り返して続行します。

  3. モジュール イメージをローカル レジストリまたはコンテナー レジストリにプッシュします。

    docker push <ImageName>
    

    例えば次が挙げられます。

    # Push the Docker image to an Azure Container Registry. Replace <AcrRegistryName> with your Azure Container Registry name.
    
    az acr login --name <AcrRegistryName>
    docker push <AcrRegistryName>.azurecr.io/classifier:0.0.1-amd64
    docker push <AcrRegistryName>.azurecr.io/cameracapture:0.0.1-amd64
    

デプロイ テンプレートを更新する

コンテナー レジストリ イメージの場所で deployment.template.json ファイルを更新します。 イメージの値を、レジストリにプッシュしたイメージに変更します。 たとえば、 <AcrRegistryName> を分類子モジュールと cameracapture モジュールの イメージ 値のレジストリ名に置き換えます。

"classifier": {
    "version": "1.0",
    "type": "docker",
    "status": "running",
    "restartPolicy": "always",
    "settings": {
        "image": "<AcrRegistryName>.azurecr.io/classifier:0.0.1-amd64",
        "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
    },
    "cameracapture": {
        "version": "1.0",
        "type": "docker",
        "status": "running",
        "restartPolicy": "always",
        "settings": {
            "image": "<AcrRegistryName>.azurecr.io/cameracapture:0.0.1-amd64",
            "createOptions": "{\"Env\":[\"IMAGE_PATH=test_image.jpg\",\"IMAGE_PROCESSING_ENDPOINT=http://classifier/image\"]}"
        }
    }
}

最終的な配置マニフェストは次のようになります。

{
  "$schema-template": "4.0.0",
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": {
          "type": "docker",
          "settings": {
            "minDockerVersion": "v1.25",
            "loggingOptions": "",
            "registryCredentials": {
              "<AcrRegistryName>": {
                "username": "<AcrUserName>",
                "password": "<AcrPassword>",
                "address": "<AcrRegistryName>.azurecr.io"
              }
            }
          }
        },
        "systemModules": {
          "edgeAgent": {
            "type": "docker",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-agent:1.5",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
            }
          },
          "edgeHub": {
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-hub:1.5",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
            }
          }
        },
        "modules": {
          "classifier": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
              "image": "<AcrRegistryName>.azurecr.io/classifier:0.0.1-amd64",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
            }
          },
          "cameracapture": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
              "image": "<AcrRegistryName>.azurecr.io/cameracapture:0.0.1-amd64",
              "createOptions": "{\"Env\":[\"IMAGE_PATH=test_image.jpg\",\"IMAGE_PROCESSING_ENDPOINT=http://classifier/image\"]}"
            }
          }
        }
      }
    },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.2",
        "routes": {
          "sensorToclassifier": "FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/classifier/inputs/input1\")",
          "classifierToIoTHub": "FROM /messages/modules/classifier/outputs/* INTO $upstream",
          "cameracaptureToIoTHub": "FROM /messages/modules/cameracapture/outputs/* INTO $upstream"
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 7200
        }
      }
    }
  }
}

モジュールをデバイスにデプロイする

ビルドされたコンテナー イメージがコンテナー レジストリに格納されていることを確認します。 次に、あなたのシナリオに合わせて準備された配置マニフェスト deployment.template.json を使用して、デバイスに展開します。

IoT Edge Azure CLI set-modules コマンドを使用して、モジュールを Azure IoT Hub にデプロイします。 たとえば、 deployment.template.json ファイルで定義されているモジュールを IoT Edge デバイスの IoT Hub <IotHubName><DeviceName> にデプロイするには、次のコマンドを使用します。 ハブ名デバイス IDログイン IoT Hub 接続文字列の値を独自の値に置き換えます。

az iot edge set-modules --hub-name <IotHubName> --device-id <DeviceName> --content ./deployment.template.json --login "HostName=my-iot-hub.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<SharedAccessKey>"

ヒント

IoT Hub 接続文字列は共有アクセス キーを含め、Azure portal にあります。 IoT Hub >セキュリティ設定>共有アクセス ポリシー>iothubowner に移動します。

IoT Edge デバイスが動作していることを確認します。

お使いのデバイスの [モジュール] を展開し、デプロイされて実行中のモジュールの一覧を表示します。 [更新] ボタンを選択します。 新しい分類子カメラキャプチャモジュールが、$edgeAgent$edgeHubと一緒に実行されているのが表示されます。

また、すべてのモジュールが動作していることをデバイス自体で確認することもできます。 IoT Edge デバイスで、次のコマンドを実行してモジュールの状態を表示します。

iotedge list

モジュールが開始されるまでに数分かかる場合があります。 IoT Edge ランタイムは、新しい配置マニフェストを受け取り、コンテナー ランタイムからモジュール イメージを取得して、それぞれの新しいモジュールを開始する必要があります。

分類の結果を表示する

デバイスで、cameracapture モジュールのログを表示して送信されたメッセージを確認し、IoT Hub によって受信されたことを確認します。

iotedge logs cameracapture

たとえば、次のような出力が表示されます。

admin@vm:~$ iotedge logs cameracapture
Simulated camera module for Azure IoT Edge. Press Ctrl-C to exit.
The sample is now sending images for processing and will indefinitely.
Response from classification service: (200) {"created": "2023-07-13T17:38:42.940878", "id": "", "iteration": "", "predictions": [{"boundingBox": null, "probability": 1.0, "tagId": "", "tagName": "hemlock"}], "project": ""}

Total images sent: 1
Response from classification service: (200) {"created": "2023-07-13T17:38:53.444884", "id": "", "iteration": "", "predictions": [{"boundingBox": null, "probability": 1.0, "tagId": "", "tagName": "hemlock"}], "project": ""}

注意

最初に、モジュールのデプロイと開始の間の遅延が原因で、cameracapture モジュールからの出力に接続エラーが表示されることがあります。

cameracapture モジュールは、成功するまで自動的に接続を再試行します。 正常に接続されると、予想される画像分類メッセージが表示されます。

カメラキャプチャ モジュールからメッセージとして送信される Custom Vision モジュールの結果には、画像がヘムロックまたは桜の木である確率が含まれます。 画像はヘムロックであるため、確率は 1.0 と表示されます。

リソースをクリーンアップする

次の推奨記事に進む場合は、作成したリソースと構成を保持し、再利用します。 また、同じ IoT Edge デバイスをテスト デバイスとして使用し続けることもできます。

それ以外の場合は、課金されないように、この記事で使用したローカル構成と Azure リソースを削除します。

Azure リソースを削除する

Azure のリソースとリソース グループは、削除すると元に戻すことができません。 間違ったリソース グループやリソースをうっかり削除しないようにしてください。 保持するリソースを含む既存のリソース グループ内に IoT Hub を作成した場合は、リソース グループではなく、IoT Hub リソース自体のみを削除します。

リソースを削除するには、次の手順に従います。

  1. Azure portal にサインインし、 [リソース グループ] を選択します。

  2. IoT Edge のテスト リソースを含んだリソース グループの名前を選択します。

  3. リソース グループに含まれているリソースの一覧を確認します。 それらすべてを削除する場合は、[リソース グループの削除] を選択します。 一部だけを削除する場合は、削除する各リソースを選択して個別に削除してください。

次のステップ

このチュートリアルでは、Custom Vision モデルをトレーニングし、モジュールとして IoT Edge デバイスにデプロイしました。 次に、画像分類サービスに対してクエリを実行し、その結果を IoT Hub にレポートできるモジュールを構築しました。

次のチュートリアルに進むと、Azure IoT Edge を利用してエッジでデータをビジネス上の分析情報に変える他の方法について学習できます。