Sviluppo di applicazioni AWS Panorama - AWS Panorama

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Sviluppo di applicazioni AWS Panorama

È possibile utilizzare l'applicazione di esempio per imparare a conoscere la struttura dell'applicazione AWS Panorama e come punto di partenza per la tua applicazione.

Il seguente diagramma mostra i componenti principali dell'applicazione in esecuzione su AWS Panorama Appliance. Il codice dell'applicazione utilizza l'SDK dell'applicazione AWS Panorama per ottenere immagini e interagire con il modello, a cui non ha accesso diretto. L'applicazione invia video a uno schermo collegato ma non invia dati immagine al di fuori della rete locale.

Architettura dell'applicazione AWS Panorama di esempio.

In questo esempio, l'applicazione utilizza l'SDK dell'applicazione AWS Panorama per ottenere fotogrammi di video da una telecamera, preelaborare i dati video e inviare i dati a un modello di visione artificiale che rileva gli oggetti. L'applicazione visualizza il risultato su un display HDMI collegato all'apparecchio.

Manifest dell'applicazione

Il manifesto dell'applicazione è un file denominatograph.jsonnellagraphsfolder. Il manifesto definisce i componenti dell'applicazione, che sono pacchetti, nodi e bordi.

I pacchetti sono codice, file di configurazione e binari per il codice dell'applicazione, i modelli, le fotocamere e i display. L'applicazione PHP PHP di esempio utilizza 4 pacchetti:

Esempio graphs/aws-panorama-sample/graph.json— Pacchetti
"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" } ],

I primi due pacchetti sono definiti all'interno dell'applicazione, nellapackagesdirectory. Contengono il codice e il modello specifici di questa applicazione. I secondi due pacchetti sono pacchetti generici di telecamere e display forniti dal servizio AWS Panorama. Laabstract_rtsp_media_sourcepackage è un segnaposto per una fotocamera che si sostituisce durante la distribuzione. Lahdmi_data_sinkpackage rappresenta il connettore di uscita HDMI sul dispositivo.

I nodi sono interfacce per i pacchetti, così come parametri non di pacchetto che possono avere valori predefiniti che vengono sovrascritti al momento della distribuzione. I pacchetti di codice e modello definiscono le interfacce inpackage.jsonfile che specificano ingressi e uscite, che possono essere flussi video o un tipo di dati di base come float, booleano o stringa.

Ad esempio, le ricettecode_nodenode si riferisce a un'interfaccia dalSAMPLE_CODEpacchetto.

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

Questa interfaccia è definita nel file di configurazione del pacchetto,package.json. L'interfaccia specifica che il pacchetto è business logic e che richiede un flusso video denominatovideo_ine un numero in virgola mobile denominatothresholdcome ingressi. L'interfaccia specifica inoltre che il codice richiede un buffer di flusso video denominatovideo_outper trasmettere video su uno schermo

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

Di nuovo nel manifesto dell'applicazione, ilcamera_nodenode rappresenta un flusso video proveniente da una telecamera. Include un decoratore che appare nella console quando si distribuisce l'applicazione, che richiede di scegliere un flusso della telecamera.

Esempio graphs/aws-panorama-sample/graph.json— Nodo 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." } },

Un nodo parametro,threshold_param, definisce il parametro della soglia di confidenza utilizzato dal codice dell'applicazione. Il valore predefinito è 60 e può essere ignorato durante la distribuzione.

Esempio graphs/aws-panorama-sample/graph.json— nodo Parametro
{ "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 sezione finale del manifesto dell'applicazione,edges, effettua connessioni tra i nodi. Il flusso video della telecamera e il parametro threshold si connettono all'ingresso del nodo di codice e l'uscita video dal nodo di codice si connette al display.

Esempio graphs/aws-panorama-sample/graph.json— Bordi
"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" } ]

Creazione con l'applicazione di esempio

È possibile utilizzare l'applicazione di esempio come punto di partenza per la tua applicazione.

Il nome di ciascun pacchetto deve essere univoco nell'account. Se tu e un altro utente nel tuo account utilizzate entrambi un nome di pacchetto generico comecodeomodel, potresti ottenere la versione sbagliata del pacchetto quando esegui la distribuzione. Modifica il nome del pacchetto di codice in uno che rappresenta la tua applicazione.

Per rinominare il pacchetto di codice
  1. Rinominare la cartella dei pacchetti:packages/123456789012-SAMPLE_CODE-1.0/.

  2. Aggiorna il nome del pacchetto nelle seguenti posizioni.

    • Manifest dell'applicazionegraphs/aws-panorama-sample/graph.json

    • Configurazione di Packagepackages/123456789012-SAMPLE_CODE-1.0/package.json

    • Script di compilazione3-build-container.sh

Per aggiornare il codice dell'applicazione
  1. Modificare il codice dell'applicazione inpackages/123456789012-SAMPLE_CODE-1.0/src/application.py.

  2. Per compilare il container, esegui3-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 elimina automaticamente la vecchia risorsa contenitore dalassetse aggiorna la configurazione del pacchetto.

  3. Per caricare i pacchetti, esegui4-package-application.py.

  4. Aprire la console AWS PanoramaPagina Applicazioni distribuite.

  5. Scegliere un'applicazione.

  6. Scegliere Replace (Sostituisci).

  7. Completare i passaggi per implementare l'applicazione. Se necessario, è possibile apportare modifiche al manifesto dell'applicazione, ai flussi della telecamera o ai parametri.

Modifica del modello di visione artificiale

L'applicazione di esempio include un modello di visione artificiale. Per utilizzare il tuo modello, modifica la configurazione del nodo del modello e utilizza l'interfaccia a riga di comando dell'applicazione AWS Panorama per importarlo come risorsa.

L'esempio seguente utilizza un SSD MXNet ResNet50 modelli scaricabili da questa guida GitHub repo:ssd_512_resnet50_v1_voc.tar.gz

Per modificare il modello dell'applicazione di esempio
  1. Rinominare la cartella dei pacchetti in base al modello. Ad esempio, perpackages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/.

  2. Aggiorna il nome del pacchetto nelle seguenti posizioni.

    • Manifest dell'applicazionegraphs/aws-panorama-sample/graph.json

    • Configurazione di Packagepackages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/package.json

  3. Nel file di configurazione del pacchetto (package.json). Modifica il file.assetsvalore a un array vuoto.

    { "nodePackage": { "envelopeVersion": "2021-01-01", "name": "SSD_512_RESNET50_V1_VOC", "version": "1.0", "description": "Compact classification model", "assets": [],
  4. Apri il file descrittore del pacchetto (descriptor.json). Aggiornamento diframeworkeshapevalori corrispondenti al tuo modello.

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

    Il valore performa,1,3,512,512, indica il numero di immagini che il modello prende come input (1), il numero di canali in ciascuna immagine (3: rosso, verde e blu) e le dimensioni dell'immagine (512 x 512). I valori e l'ordine dell'array variano a seconda dei modelli.

  5. Importa il modello con l'interfaccia a riga di comando dell'applicazione AWS Panorama. L'interfaccia a riga di comando dell'applicazione AWS Panorama copia i file del modello e del descrittore nelassetscartella con nomi univoci e aggiorna la configurazione del pacchetto.

    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" } ] }
  6. Per caricare il modello, eseguipanorama-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
  7. Aggiornamento del codice dell'applicazione. La maggior parte del codice può essere riutilizzata. Il codice specifico per la risposta del modello è nellaprocess_resultsMetodo.

    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)

    In base al modello in uso, potrebbe anche essere necessario aggiornare ilpreprocessMetodo.

Pre-elaborazione di immagini

Prima che l'applicazione invii un'immagine al modello, la prepara per l'inferenza ridimensionandola e normalizzando i dati colore. Il modello utilizzato dall'applicazione richiede un'immagine di 224 x 224 pixel con tre canali di colore, per corrispondere al numero di input nel suo primo livello. L'applicazione regola ogni valore di colore convertendolo in un numero compreso tra 0 e 1, sottraendo il valore medio per quel colore e dividendo per la deviazione standard. Infine, combina i canali di colore e li converte in un NumPy array che il modello può elaborare.

Esempio application.py— Pre-elaborazione
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)

Questo processo fornisce i valori del modello in un intervallo prevedibile centrato attorno a 0. Corrisponde alla pre-elaborazione applicata alle immagini nel set di dati di addestramento, che è un approccio standard ma può variare in base al modello.

Caricamento di metriche con SDK per Python

L'applicazione PHP PHP PHP PHP di esempio utilizza SDK per Python per caricare le metriche su Amazon. CloudWatch.

Esempio application.py— SDK per 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.")

Ottiene l'autorizzazione da un ruolo di runtime assegnato durante la distribuzione. Il ruolo è definito nellaaws-panorama-sample.yml AWS CloudFormationModello.

Esempio 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'applicazione di esempio installa l'SDK per Python e altre dipendenze con pip. Quando si crea il contenitore dell'applicazione, ilDockerfileesegue comandi per installare le librerie in cima a ciò che viene fornito con l'immagine di base.

Esempio 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

Per utilizzare il pluginAWSSDK nel codice dell'applicazione, prima modifica il modello per aggiungere le autorizzazioni per tutte le azioni API utilizzate dall'applicazione. Aggiornamento diAWS CloudFormationstack eseguendo il1-create-role.shogni volta che apporti una modifica. Quindi, implementa le modifiche al codice dell'applicazione.

Per le azioni che modificano o utilizzano risorse esistenti, è consigliabile ridurre al minimo l'ambito di questo criterio specificando un nome o un modello per la destinazione.Resourcein una dichiarazione separata. Per i dettagli sulle azioni e le risorse supportate da ciascun servizio, vedere.Operazioni, risorse e chiavi di condizionenella Service Authorization Reference

Fasi successive

Per istruzioni sull'utilizzo dell'interfaccia a riga di comando di AWS Panorama Application per creare applicazioni e creare pacchetti da zero, consulta il README dell'interfaccia della riga di comando.

Per ulteriori esempi di codice e un'utilità di test da utilizzare per convalidare il codice dell'applicazione prima della distribuzione, visita il repository di campioni di AWS Panorama.