

Avis de fin de support : le 31 mai 2026, AWS le support de AWS Panorama. Après le 31 mai 2026, vous ne pourrez plus accéder à la AWS Panorama console ni aux AWS Panorama ressources. Pour plus d'informations, voir [AWS Panorama fin du support](https://docs.aws.amazon.com/panorama/latest/dev/panorama-end-of-support.html). 

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Développement d'applications AWS Panorama
<a name="gettingstarted-sample"></a>

Vous pouvez utiliser l'exemple d'application pour en savoir plus sur la structure de l'application AWS Panorama et comme point de départ pour votre propre application.

Le schéma suivant montre les principaux composants de l'application exécutée sur une appliance AWS Panorama. Le code de l'application utilise le SDK d'application AWS Panorama pour obtenir des images et interagir avec le modèle, auquel il n'a pas d'accès direct. L'application émet une vidéo sur un écran connecté mais n'envoie pas de données d'image en dehors de votre réseau local.

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


Dans cet exemple, l'application utilise le SDK de l'application AWS Panorama pour obtenir des images vidéo d'une caméra, prétraiter les données vidéo et les envoyer à un modèle de vision par ordinateur qui détecte des objets. L'application affiche le résultat sur un écran HDMI connecté à l'appareil.

**Topics**
+ [Le manifeste de l'application](#gettingstarted-sample-manifest)
+ [Création à l'aide de l'exemple d'application](#gettingstarted-sample-adapting)
+ [Modification du modèle de vision par ordinateur](#gettingstarted-sample-model)
+ [Prétraitement des images](#gettingstarted-sample-preprocessing)
+ [Téléchargement de métriques avec le SDK pour Python](#gettingstarted-sample-metrics)
+ [Étapes suivantes](#gettingstarted-sample-nextsteps)

## Le manifeste de l'application
<a name="gettingstarted-sample-manifest"></a>

Le manifeste de l'application est un fichier nommé `graph.json` dans le `graphs` dossier. Le manifeste définit les composants de l'application, à savoir les packages, les nœuds et les arêtes.

Les packages sont des fichiers de code, de configuration et binaires pour le code d'application, les modèles, les caméras et les écrans. L'exemple d'application utilise 4 packages :

**Example `graphs/aws-panorama-sample/graph.json`— Forfaits**  

```
        "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"
            }
        ],
```

Les deux premiers packages sont définis dans l'application, dans le `packages` répertoire. Ils contiennent le code et le modèle spécifiques à cette application. Les deux autres packages sont des packages de caméra et d'écran génériques fournis par le service AWS Panorama. Le `abstract_rtsp_media_source` package est un espace réservé pour une caméra que vous pouvez remplacer lors du déploiement. Le `hdmi_data_sink` boîtier représente le connecteur de sortie HDMI de l'appareil.

Les nœuds sont des interfaces vers des packages, ainsi que des paramètres autres que les packages qui peuvent avoir des valeurs par défaut que vous pouvez remplacer au moment du déploiement. Les packages de code et de modèle définissent des interfaces dans `package.json` des fichiers qui spécifient les entrées et les sorties, qui peuvent être des flux vidéo ou un type de données de base tel qu'un flottant, un booléen ou une chaîne.

Par exemple, le `code_node` nœud fait référence à une interface du `SAMPLE_CODE` package.

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

Cette interface est définie dans le fichier de configuration du package,`package.json`. L'interface indique que le package est basé sur la logique métier et qu'il prend en entrée un flux vidéo nommé `video_in` et un nombre à virgule flottante `threshold` nommé. L'interface indique également que le code nécessite un tampon de flux vidéo nommé `video_out` pour afficher la vidéo sur un écran.

**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"
                    }
                ]
            }
        ]
    }
}
```

De retour dans le manifeste de l'application, le `camera_node` nœud représente un flux vidéo provenant d'une caméra. Il inclut un décorateur qui apparaît dans la console lorsque vous déployez l'application et vous invite à choisir un flux de caméra.

**Example `graphs/aws-panorama-sample/graph.json`— Nœud de caméra**  

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

Un nœud de paramètres définit `threshold_param` le paramètre de seuil de confiance utilisé par le code de l'application. Il a une valeur par défaut de 60 et peut être remplacé lors du déploiement.

**Example `graphs/aws-panorama-sample/graph.json`— Nœud de paramètres**  

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

La dernière section du manifeste de l'application établit `edges` les connexions entre les nœuds. Le flux vidéo de la caméra et le paramètre de seuil sont connectés à l'entrée du nœud de code, tandis que la sortie vidéo du nœud de code est connectée à l'écran.

**Example `graphs/aws-panorama-sample/graph.json`— Bords**  

```
        "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"
            }
        ]
```

## Création à l'aide de l'exemple d'application
<a name="gettingstarted-sample-adapting"></a>

Vous pouvez utiliser l'exemple d'application comme point de départ pour votre propre application.

Le nom de chaque package doit être unique dans votre compte. Si vous et un autre utilisateur de votre compte utilisez un nom de package générique tel que `code` ou`model`, il est possible que vous obteniez la mauvaise version du package lors du déploiement. Remplacez le nom du package de code par un nom qui représente votre application.

**Pour renommer le package de code**

1. Renommez le dossier du package :`packages/123456789012-SAMPLE_CODE-1.0/`.

1. Mettez à jour le nom du package aux emplacements suivants.

****
   + **Manifeste de candidature** — `graphs/aws-panorama-sample/graph.json`
   + **Configuration du package** — `packages/123456789012-SAMPLE_CODE-1.0/package.json`
   + **Script de construction** — `3-build-container.sh`

**Pour mettre à jour le code de l'application**

1. Modifiez le code de l'application dans`packages/123456789012-SAMPLE_CODE-1.0/src/application.py`.

1. Pour créer le conteneur, exécutez`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
   ```

   La CLI supprime automatiquement l'ancien actif de conteneur du `assets` dossier et met à jour la configuration du package.

1. Pour télécharger les packages, exécutez`4-package-application.py`.

1. Ouvrez la [page des applications déployées](https://console.aws.amazon.com/panorama/home#deployed-applications) de la console AWS Panorama.

1. Choisissez une application.

1. Choisissez **Remplacer**.

1. Suivez les étapes pour déployer l'application. Si nécessaire, vous pouvez apporter des modifications au manifeste de l'application, aux flux de caméra ou aux paramètres.

## Modification du modèle de vision par ordinateur
<a name="gettingstarted-sample-model"></a>

L'exemple d'application inclut un modèle de vision par ordinateur. Pour utiliser votre propre modèle, modifiez la configuration du nœud du modèle et utilisez la CLI d'application AWS Panorama pour l'importer en tant que ressource.

[L'exemple suivant utilise un modèle MXNet SSD ResNet 50 que vous pouvez télécharger depuis le GitHub dépôt de ce guide : 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)

**Pour modifier le modèle de l'application d'exemple**

1. Renommez le dossier du package en fonction de votre modèle. Par exemple, pour`packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/`.

1. Mettez à jour le nom du package aux emplacements suivants.

****
   + **Manifeste de candidature** — `graphs/aws-panorama-sample/graph.json`
   + **Configuration du package** — `packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/package.json`

1. Dans le fichier de configuration du package (`package.json`). Remplacez la `assets` valeur par un tableau vide.

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

1. Ouvrez le fichier descripteur du package (`descriptor.json`). Mettez à jour les `shape` valeurs `framework` et pour qu'elles correspondent à votre modèle.

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

   La valeur de la **forme** indique le nombre d'images que le modèle prend en entrée (1), le nombre de canaux dans chaque image (3 : rouge, vert et bleu) et les dimensions de l'image (512 x 512). `1,3,512,512` Les valeurs et l'ordre du tableau varient selon les modèles.

1. Importez le modèle à l'aide de l'interface de ligne de commande de l'application AWS Panorama. La CLI de l'application AWS Panorama copie les fichiers de modèle et de descripteur dans le `assets` dossier avec des noms uniques, et met à jour la configuration du package.

   ```
   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. Pour télécharger le modèle, exécutez`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. Mettez à jour le code de l'application. La majeure partie du code peut être réutilisée. Le code spécifique à la réponse du modèle se trouve dans la `process_results` méthode.

   ```
       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)
   ```

   En fonction de votre modèle, vous devrez peut-être également mettre à jour la `preprocess` méthode.

## Prétraitement des images
<a name="gettingstarted-sample-preprocessing"></a>

Avant que l'application n'envoie une image au modèle, elle la prépare pour l'inférence en la redimensionnant et en normalisant les données de couleur. Le modèle utilisé par l'application nécessite une image de 224 x 224 pixels avec trois canaux de couleur, pour correspondre au nombre d'entrées de sa première couche. L'application ajuste chaque valeur de couleur en la convertissant en un nombre compris entre 0 et 1, en soustrayant la valeur moyenne de cette couleur et en la divisant par l'écart type. Enfin, il combine les canaux de couleur et les convertit en un NumPy tableau que le modèle peut traiter.

**Example [application.py](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/packages/123456789012-SAMPLE_CODE-1.0/application.py) — Prétraitement**  

```
    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)
```

Ce processus fournit les valeurs du modèle dans une plage prévisible centrée autour de 0. Il correspond au prétraitement appliqué aux images de l'ensemble de données d'apprentissage, qui est une approche standard mais qui peut varier selon le modèle.

## Téléchargement de métriques avec le SDK pour Python
<a name="gettingstarted-sample-metrics"></a>

L'exemple d'application utilise le SDK pour Python pour télécharger des métriques sur Amazon CloudWatch.

**Example [application.py](https://github.com/awsdocs/aws-panorama-developer-guide/blob/main/sample-apps/aws-panorama-sample/packages/123456789012-SAMPLE_CODE-1.0/application.py) — SDK pour Python**  

```
    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.")
```

Il obtient l'autorisation d'un rôle d'exécution que vous attribuez lors du déploiement. Le rôle est défini dans le `aws-panorama-sample.yml` CloudFormation modèle.

**Example [aws-panorama-sample.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/
```

L'exemple d'application installe le SDK pour Python et les autres dépendances avec pip. Lorsque vous créez le conteneur d'applications, il `Dockerfile` exécute des commandes pour installer des bibliothèques au-dessus de ce qui est fourni avec l'image de base.

**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
```

Pour utiliser le AWS SDK dans le code de votre application, modifiez d'abord le modèle afin d'ajouter des autorisations pour toutes les actions d'API utilisées par l'application. Mettez à jour la CloudFormation pile en l'exécutant à `1-create-role.sh` chaque fois que vous apportez une modification. Déployez ensuite les modifications apportées au code de votre application.

Pour les actions qui modifient ou utilisent des ressources existantes, il est recommandé de minimiser la portée de cette politique en spécifiant un nom ou un modèle pour la cible `Resource` dans une déclaration séparée. Pour plus de détails sur les actions et les ressources prises en charge par chaque service, consultez la section [Actions, ressources et clés de condition](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html) dans la référence d'autorisation de service

## Étapes suivantes
<a name="gettingstarted-sample-nextsteps"></a>

Pour obtenir des instructions sur l'utilisation de la CLI d'application AWS Panorama pour créer des applications et créer des packages à partir de zéro, consultez le fichier README de l'interface de ligne de commande.

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

Pour obtenir d'autres exemples de code et un utilitaire de test que vous pouvez utiliser pour valider le code de votre application avant le déploiement, consultez le référentiel d'exemples AWS Panorama.

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