

サポート終了通知: 2026 年 5 月 31 日、 AWS は のサポートを終了します AWS Panorama。2026 年 5 月 31 日以降、 AWS Panorama コンソールまたは AWS Panorama リソースにアクセスできなくなります。詳細については、[AWS Panorama 「サポート終了](https://docs.aws.amazon.com/panorama/latest/dev/panorama-end-of-support.html)」を参照してください。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# AWS Panorama アプリケーションの開発
<a name="gettingstarted-sample"></a>

サンプルアプリケーションを使用して、AWS Panorama アプリケーションの構造について学んだり、独自のアプリケーションの開始点にしたりできます。

次の図表に、AWS Panorama アプライアンスで実行されるアプリケーションの主要なコンポーネントを示します。アプリケーションコードは AWS Panorama アプリケーションSDK を使用して画像を取得し、直接アクセスできないモデルとやり取りします。アプリケーションは接続されたディスプレイに動画を出力しますが、ローカルネットワークの外部には画像データを送信しません。

![\[\]](http://docs.aws.amazon.com/ja_jp/panorama/latest/dev/images/sample-app.png)


この例では、アプリケーションは AWS Panorama アプリケーション SDK を使用してカメラからビデオフレームを取得し、ビデオデータを前処理して、オブジェクトを検出するコンピュータビジョンモデルにデータを送信します。アプリケーションは、アプライアンスに接続された HDMI ディスプレイに結果を表示します。

**Topics**
+ [アプリケーションマニフェスト。](#gettingstarted-sample-manifest)
+ [サンプルアプリケーションでのビルド](#gettingstarted-sample-adapting)
+ [コンピュータービジョンモデルの変更](#gettingstarted-sample-model)
+ [画像の前処理](#gettingstarted-sample-preprocessing)
+ [Python 用 SDK によるメトリクスのアップロード](#gettingstarted-sample-metrics)
+ [次の手順](#gettingstarted-sample-nextsteps)

## アプリケーションマニフェスト。
<a name="gettingstarted-sample-manifest"></a>

アプリケーションマニフェストは、`graphs` フォルダー内の `graph.json` という名前のファイルです。マニフェストは、パッケージ、ノード、エッジなどのアプリケーションのコンポーネントを定義します。

パッケージは、アプリケーションコード、モデル、カメラ、ディスプレイのコード、構成、バイナリファイルです。サンプルアプリケーションは 4 つのパッケージを使用します。

**Example `graphs/aws-panorama-sample/graph.json` - パッケージ**  

```
        "packages": [
            {
                "name": "123456789012::SAMPLE_CODE",
                "version": "1.0"
            },
            {
                "name": "123456789012::SQUEEZENET_PYTORCH_V1",
                "version": "1.0"
            },
            {
                "name": "panorama::abstract_rtsp_media_source",
                "version": "1.0"
            },
            {
                "name": "panorama::hdmi_data_sink",
                "version": "1.0"
            }
        ],
```

最初の 2 つのパッケージは、アプリケーション内の `packages` ディレクトリで定義されています。これらには、このアプリケーション固有のコードとモデルが含まれています。次の 2 つのパッケージは、AWS Panorama サービスが提供する汎用のカメラおよびディスプレイパッケージです。`abstract_rtsp_media_source` パッケージは、デプロイ時にオーバーライドするカメラのプレースホルダーです。`hdmi_data_sink` パッケージはデバイスの HDMI 出力コネクタを表します。

ノードはパッケージへのインターフェースであると同時に、デプロイ時にオーバーライドできるデフォルト値を持つ非パッケージパラメーターのインターフェースでもあります。コードパッケージとモデルパッケージは、ビデオストリームでも、フロート、ブーリアン、文字列などの基本データ型でも、入力と出力を指定する `package.json` ファイル内のインターフェイスを定義します。

たとえば、`code_node` ノードは `SAMPLE_CODE` パッケージのインターフェースを参照します。

```
        "nodes": [
            {
                "name": "code_node",
                "interface": "123456789012::SAMPLE_CODE.interface",
                "overridable": false,
                "launch": "onAppStart"
            },
```

このインターフェースはパッケージ構成ファイル、`package.json` 内で定義されています。このインターフェースは、パッケージがビジネスロジックであり、`video_in` という名前のビデオストリームと `threshold`という名前の浮動小数点数を入力として受け取ることを指定しています。また、このインターフェースでは、ビデオをディスプレイに出力するための `video_out` という名前のビデオストリームバッファがコードに必要であることも指定されています。

**Example `packages/123456789012-SAMPLE_CODE-1.0/package.json`**  

```
{
    "nodePackage": {
        "envelopeVersion": "2021-01-01",
        "name": "SAMPLE_CODE",
        "version": "1.0",
        "description": "Computer vision application code.",
        "assets": [],
        "interfaces": [
            {
                "name": "interface",
                "category": "business_logic",
                "asset": "code_asset",
                "inputs": [
                    {
                        "name": "video_in",
                        "type": "media"
                    },
                    {
                        "name": "threshold",
                        "type": "float32"
                    }
                ],
                "outputs": [
                    {
                        "description": "Video stream output",
                        "name": "video_out",
                        "type": "media"
                    }
                ]
            }
        ]
    }
}
```

アプリケーションマニフェストに戻ると、`camera_node` ノードはカメラからのビデオストリームを表しています。これには、アプリケーションをデプロイするとコンソールに表示され、カメラストリームの選択を促すデコレータが含まれています。

**Example `graphs/aws-panorama-sample/graph.json` – Camera ノード**  

```
            {
                "name": "camera_node",
                "interface": "panorama::abstract_rtsp_media_source.rtsp_v1_interface",
                "overridable": true,
                "launch": "onAppStart",
                "decorator": {
                    "title": "Camera",
                    "description": "Choose a camera stream."
                }
            },
```

パラメータノード `threshold_param` は、アプリケーションコードで使用される信頼度しきい値パラメータを定義します。デフォルト値は 60 で、デプロイ時に上書きできます。

**Example `graphs/aws-panorama-sample/graph.json` — パラメータノード**  

```
            {
                "name": "threshold_param",
                "interface": "float32",
                "value": 60.0,
                "overridable": true,
                "decorator": {
                    "title": "Confidence threshold",
                    "description": "The minimum confidence for a classification to be recorded."
                }
            }
```

アプリケーションマニフェストの最後のセクション `edges` では、ノード間の接続を行います。カメラのビデオストリームとしきい値パラメータはコードノードの入力に接続し、コードノードからのビデオ出力はディスプレイに接続します。

**Example `graphs/aws-panorama-sample/graph.json` - エッジ**  

```
        "edges": [
            {
                "producer": "camera_node.video_out",
                "consumer": "code_node.video_in"
            },
            {
                "producer": "code_node.video_out",
                "consumer": "output_node.video_in"
            },
            {
                "producer": "threshold_param",
                "consumer": "code_node.threshold"
            }
        ]
```

## サンプルアプリケーションでのビルド
<a name="gettingstarted-sample-adapting"></a>

サンプルコードを開始点として使用して、独自のアプリケーションを作成することができます。

各パッケージ名は一意にする必要があります。自分とアカウント内の別のユーザーの両方が `code` や`model` などの汎用パッケージ名を使用している場合、デプロイ時に間違ったバージョンのパッケージが表示される可能性があります。コードパッケージの名前を、自分のアプリケーションを表す名前に変更してください。

**コードパッケージの名前を変更するには**

1. パッケージフォルダーの名前を変更します:`packages/123456789012-SAMPLE_CODE-1.0/`。

1. 次の場所でパッケージ名を更新します。

****
   + **アプリケーションマニフェスト** — `graphs/aws-panorama-sample/graph.json`
   + **パッケージ構成** – `packages/123456789012-SAMPLE_CODE-1.0/package.json`
   + **ビルドスクリプト** — `3-build-container.sh`

**アプリケーションコードを更新するには**

1. `packages/123456789012-SAMPLE_CODE-1.0/src/application.py` でアプリケーションコードを変更します。

1. コンテナを構築するには、`3-build-container.sh` を実行します。

   ```
   aws-panorama-sample$ ./3-build-container.sh
   TMPDIR=$(pwd) docker build -t code_asset packages/123456789012-SAMPLE_CODE-1.0
   Sending build context to Docker daemon  61.44kB
   Step 1/2 : FROM public.ecr.aws/panorama/panorama-application
    ---> 9b197f256b48
   Step 2/2 : COPY src /panorama
    ---> 55c35755e9d2
   Successfully built 55c35755e9d2
   Successfully tagged code_asset:latest
   docker export --output=code_asset.tar $(docker create code_asset:latest)
   gzip -9 code_asset.tar
   Updating an existing asset with the same name
   {
       "name": "code_asset",
       "implementations": [
           {
               "type": "container",
               "assetUri": "98aaxmpl1c1ef64cde5ac13bd3be5394e5d17064beccee963b4095d83083c343.tar.gz",
               "descriptorUri": "1872xmpl129481ed053c52e66d6af8b030f9eb69b1168a29012f01c7034d7a8f.json"
           }
       ]
   }
   Container asset for the package has been succesfully built at  ~/aws-panorama-sample-dev/assets/98aaxmpl1c1ef64cde5ac13bd3be5394e5d17064beccee963b4095d83083c343.tar.gz
   ```

   CLI は古いコンテナアセットを `assets` フォルダから自動的に削除し、パッケージ構成を更新します。

1. パッケージをアップロードするには、`4-package-application.py` を実行します。

1. AWS Panorama コンソールの [[デプロイされたアプリケーション] ページ](https://console.aws.amazon.com/panorama/home#deployed-applications)を開きます。

1. アプリケーションを選択します。

1. ［**置換**］を選択します。

1. アプリケーションを実行するには、手順に従います。必要に応じて、アプリケーションマニフェスト、カメラストリーム、またはパラメータを変更できます。

## コンピュータービジョンモデルの変更
<a name="gettingstarted-sample-model"></a>

サンプルアプリケーションにはコンピュータビジョンモデルが含まれています。独自のモデルを使用するには、モデルノードの構成を変更し、AWS Panorama アプリケーション CLI を使用してアセットとしてインポートします。

次の例では MXNet SSD ResNet50 モデルを使用しています。このモデルは、このガイドの GitHub リポジトリからダウンロードできます。[ssd\$1512\$1resnet50\$1v1\$1voc.tar.gz](https://github.com/awsdocs/aws-panorama-developer-guide/releases/download/v0.1-preview/ssd_512_resnet50_v1_voc.tar.gz)

**サンプルアプリケーションのモデルを変更するには**

1. モデルに合うようにパッケージフォルダーの名前を変更します。たとえば、`packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/` などにします。

1. 次の場所でパッケージ名を更新します。

****
   + **アプリケーションマニフェスト** — `graphs/aws-panorama-sample/graph.json`
   + **パッケージ構成** – `packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/package.json`

1. パッケージ構成ファイル (`package.json`) 内。`assets` 値を空白の配列に変更します。

   ```
   {
       "nodePackage": {
           "envelopeVersion": "2021-01-01",
           "name": "SSD_512_RESNET50_V1_VOC",
           "version": "1.0",
           "description": "Compact classification model",
           "assets": [],
   ```

1. パッケージ記述ファイル (`descriptor.json`) を開きます。モデルと一致するように`framework` および`shape` の値を更新します。

   ```
   {
       "mlModelDescriptor": {
           "envelopeVersion": "2021-01-01",
           "framework": "MXNET",
           "inputs": [
               {
                   "name": "data",
                   "shape": [ 1, 3, 512, 512 ]
               }
           ]
       }
   }
   ```

   **シェイプ** の値は `1,3,512,512`、モデルが入力として受け取る画像の数 (1)、各画像のチャネル数 (3–- 赤、緑、青 )、および画像のサイズ (512 x 512) を示します。配列の値と順序はモデルによって異なります。

1. AWS Panorama アプリケーション CLI を使用してモデルをインポートします。AWS Panorama アプリケーション CLI は、モデルファイルと記述子ファイルを一意の名前で `assets` フォルダにコピーし、パッケージ構成を更新します。

   ```
   aws-panorama-sample$ panorama-cli add-raw-model --model-asset-name model-asset \
   --model-local-path ssd_512_resnet50_v1_voc.tar.gz \
   --descriptor-path packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/descriptor.json \
   --packages-path packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0
   {
       "name": "model-asset",
       "implementations": [
           {
               "type": "model",
               "assetUri": "b1a1589afe449b346ff47375c284a1998c3e1522b418a7be8910414911784ce1.tar.gz",
               "descriptorUri": "a6a9508953f393f182f05f8beaa86b83325f4a535a5928580273e7fe26f79e78.json"
           }
       ]
   }
   ```

1. モデルをアップロードするには、`panorama-cli package-application` を実行します。

   ```
   $ panorama-cli package-application
   Uploading package SAMPLE_CODE
   Patch Version 1844d5a59150d33f6054b04bac527a1771fd2365e05f990ccd8444a5ab775809 already registered, ignoring upload
   Uploading package SSD_512_RESNET50_V1_VOC
   Patch version for the package 244a63c74d01e082ad012ebf21e67eef5d81ce0de4d6ad1ae2b69d0bc498c8fd
   upload: assets/b1a1589afe449b346ff47375c284a1998c3e1522b418a7be8910414911784ce1.tar.gz to s3://arn:aws:s3:us-west-2:454554846382:accesspoint/panorama-123456789012-wc66m5eishf4si4sz5jefhx
   63a/123456789012/nodePackages/SSD_512_RESNET50_V1_VOC/binaries/b1a1589afe449b346ff47375c284a1998c3e1522b418a7be8910414911784ce1.tar.gz
   upload: assets/a6a9508953f393f182f05f8beaa86b83325f4a535a5928580273e7fe26f79e78.json to s3://arn:aws:s3:us-west-2:454554846382:accesspoint/panorama-123456789012-wc66m5eishf4si4sz5jefhx63
   a/123456789012/nodePackages/SSD_512_RESNET50_V1_VOC/binaries/a6a9508953f393f182f05f8beaa86b83325f4a535a5928580273e7fe26f79e78.json
   {
       "ETag": "\"2381dabba34f4bc0100c478e67e9ab5e\"",
       "ServerSideEncryption": "AES256",
       "VersionId": "KbY5fpESdpYamjWZ0YyGqHo3.LQQWUC2"
   }
   Registered SSD_512_RESNET50_V1_VOC with patch version 244a63c74d01e082ad012ebf21e67eef5d81ce0de4d6ad1ae2b69d0bc498c8fd
   Uploading package SQUEEZENET_PYTORCH_V1
   Patch Version 568138c430e0345061bb36f05a04a1458ac834cd6f93bf18fdacdffb62685530 already registered, ignoring upload
   ```

1. アプリケーションコードを更新します。ほとんどのコードは再利用できます。モデルのレスポンスに固有のコードは。`process_results` メソッド内にあります。

   ```
       def process_results(self, inference_results, stream):
           """Processes output tensors from a computer vision model and annotates a video frame."""
           for class_tuple in inference_results:
               indexes = self.topk(class_tuple[0])
           for j in range(2):
               label = 'Class [%s], with probability %.3f.'% (self.classes[indexes[j]], class_tuple[0][indexes[j]])
               stream.add_label(label, 0.1, 0.25 + 0.1*j)
   ```

   モデルに応じて、`preprocess` メソッドを更新する必要があることもあります。

## 画像の前処理
<a name="gettingstarted-sample-preprocessing"></a>

アプリケーションがイメージをモデルに送信する前に、イメージのサイズを変更してカラーデータを正規化することで、イメージを推論できるように準備します。アプリケーションが使用するモデルには、最初のレイヤーの入力数に合わせて、3 つのカラーチャンネルを含む 224 x 224 ピクセルの画像が必要です。アプリケーションは、各色の値を 0 から 1 の間の数値に変換し、その色の平均値を引いて標準偏差で割ることによって調整します。最後に、カラーチャンネルを結合し、モデルが処理できるNumPy 配列に変換します。

**Example [アプリケーション.py](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/packages/123456789012-SAMPLE_CODE-1.0/application.py) — 前処理**  

```
    def preprocess(self, img, width):
        resized = cv2.resize(img, (width, width))
        mean = [0.485, 0.456, 0.406]
        std = [0.229, 0.224, 0.225]
        img = resized.astype(np.float32) / 255.
        img_a = img[:, :, 0]
        img_b = img[:, :, 1]
        img_c = img[:, :, 2]
        # Normalize data in each channel
        img_a = (img_a - mean[0]) / std[0]
        img_b = (img_b - mean[1]) / std[1]
        img_c = (img_c - mean[2]) / std[2]
        # Put the channels back together
        x1 = [[[], [], []]]
        x1[0][0] = img_a
        x1[0][1] = img_b
        x1[0][2] = img_c
        return np.asarray(x1)
```

このプロセスにより、0 を中心とした予測可能な範囲内のモデル値が得られます。これはトレーニングデータセット内の画像に適用される前処理と一致します。これは標準的な方法ですが、モデルごとに異なる場合があります。

## Python 用 SDK によるメトリクスのアップロード
<a name="gettingstarted-sample-metrics"></a>

サンプルアプリケーションは Python 用 SDK を使用して Amazon CloudWatch にメトリクスをアップロードします。

**Example [アプリケーション.py](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/packages/123456789012-SAMPLE_CODE-1.0/application.py) — Python 用 SDK**  

```
    def process_streams(self):
        """Processes one frame of video from one or more video streams."""
        ...
            logger.info('epoch length: {:.3f} s ({:.3f} FPS)'.format(epoch_time, epoch_fps))
            logger.info('avg inference time: {:.3f} ms'.format(avg_inference_time))
            logger.info('max inference time: {:.3f} ms'.format(max_inference_time))
            logger.info('avg frame processing time: {:.3f} ms'.format(avg_frame_processing_time))
            logger.info('max frame processing time: {:.3f} ms'.format(max_frame_processing_time))
            self.inference_time_ms = 0
            self.inference_time_max = 0
            self.frame_time_ms = 0
            self.frame_time_max = 0
            self.epoch_start = time.time()
            self.put_metric_data('AverageInferenceTime', avg_inference_time)
            self.put_metric_data('AverageFrameProcessingTime', avg_frame_processing_time)
 
    def put_metric_data(self, metric_name, metric_value):
        """Sends a performance metric to CloudWatch."""
        namespace = 'AWSPanoramaApplication'
        dimension_name = 'Application Name'
        dimension_value = 'aws-panorama-sample'
        try:
            metric = self.cloudwatch.Metric(namespace, metric_name)
            metric.put_data(
                Namespace=namespace,
                MetricData=[{
                    'MetricName': metric_name,
                    'Value': metric_value,
                    'Unit': 'Milliseconds',
                    'Dimensions': [
                        {
                            'Name': dimension_name,
                            'Value': dimension_value
                        },
                        {
                            'Name': 'Device ID',
                            'Value': self.device_id
                        }
                    ]
                }]
            )
            logger.info("Put data for metric %s.%s", namespace, metric_name)
        except ClientError:
            logger.warning("Couldn't put data for metric %s.%s", namespace, metric_name)
        except AttributeError:
            logger.warning("CloudWatch client is not available.")
```

デプロイ時に割り当てたランタイムロールから権限を取得します。ロールは `aws-panorama-sample.yml` CloudFormation テンプレートで定義されます。

**Example [aws-panorama-サンプル.yml](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/aws-panorama-sample.yml)**  

```
Resources:
  runtimeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"		 	 	 
        Statement:
          -
            Effect: Allow
            Principal:
              Service:
                - panorama.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: cloudwatch-putmetrics
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action: 'cloudwatch:PutMetricData'
                Resource: '*'
      Path: /service-role/
```

サンプルアプリケーションは、Python 用の SDK とその他の依存関係をピップでインストールします。アプリケーションコンテナをビルドすると、`Dockerfile` はコマンドを実行して、ベースイメージに付属しているものの上にライブラリをインストールします。

**Example [Dockerfile](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/packages/123456789012-SAMPLE_CODE-1.0/Dockerfile)**  

```
FROM public.ecr.aws/panorama/panorama-application
WORKDIR /panorama
COPY . .
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt
```

アプリケーションコードで AWS SDK を使用するには、まずテンプレートを変更して、アプリケーションが使用するすべての API アクションのアクセス許可を追加します。変更を行う`1-create-role.sh`たびに を実行して CloudFormation スタックを更新します。次に、変更内容をアプリケーションコードにデプロイします。

既存のリソースを変更または使用するアクションでは、ターゲット `Resource` の名前またはパターンを別のステートメントで指定して、このポリシーの範囲を最小限に抑えるのがベストプラクティスです。各サービスでサポートされているアクションとリソースの詳細については、サービス承認リファレンスの[「アクション、リソース、条件キー」](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)を参照してください。

## 次の手順
<a name="gettingstarted-sample-nextsteps"></a>

AWS Panorama アプリケーション CLI を使用してアプリケーションをビルドし、パッケージを最初から作成する手順については、CLI の README を参照してください。

****
+ [github.com/aws/aws-panorama-cli](https://github.com/aws/aws-panorama-cli)

デプロイ前にアプリケーションコードを検証するために使用できるその他のサンプルコードとテストユーティリティについては、AWS Panorama サンプルリポジトリをご覧ください。

****
+ [github.com/aws-samples/aws-panorama-samples](https://github.com/aws-samples/aws-panorama-samples)