Desarrollo de aplicaciones de AWS Panorama - AWS Panorama

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Desarrollo de aplicaciones de AWS Panorama

Puede utilizar la aplicación de muestra de para obtener información sobre la estructura de la aplicación de AWS Panorama y como punto de partida para su propia aplicación.

El siguiente diagrama muestra los componentes principales de la aplicación que se ejecuta en un dispositivo de AWS Panorama. El código de la aplicación utiliza el SDK de aplicaciones de AWS Panorama para obtener imágenes e interactuar con el modelo, al que no tiene acceso directo. La aplicación envía vídeo a una pantalla conectada, pero no envía datos de imagen fuera de la red local.

Aplicación de muestra de arquitectura de AWS Panorama.

En este ejemplo, la aplicación utiliza el SDK de aplicaciones de AWS Panorama para obtener fotogramas de vídeo de una cámara, preprocesar los datos de vídeo y enviar los datos a un modelo de visión artificial que detecta objetos. La aplicación muestra el resultado en una pantalla HDMI conectada al dispositivo.

El manifiesto de la aplicación

El manifiesto de la aplicación es un archivo cuyo nombre es graph.json en la carpeta graphs. El manifiesto define los componentes de la aplicación, que son paquetes, nodos y periferias.

Los paquetes son archivos de código, configuración y binarios para el código, los modelos, las cámaras y las pantallas de la aplicación. La aplicación de muestra utiliza 4 paquetes:

ejemplo graphs/aws-panorama-sample/graph.json: paquetes
"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" } ],

Los dos primeros paquetes se definen dentro de la aplicación, en el directorio packages. Contienen el código y el modelo específicos de esta aplicación. Los dos segundos paquetes son paquetes genéricos de cámara y pantalla proporcionados por el servicio AWS Panorama. El paquete abstract_rtsp_media_source es un marcador de posición para una cámara que usted puede anular durante la implementación. El paquete hdmi_data_sink representa el conector de salida HDMI del dispositivo.

Los nodos son interfaces de paquetes, así como parámetros ajenos al paquete que pueden tener valores predeterminados que se anulan en el momento de la implementación. Los paquetes de código y modelo definen las interfaces en los archivos package.json que especifican las entradas y las salidas, que pueden ser transmisiones de vídeo o un tipo de datos básico, como un float, un booleano o una cadena.

Por ejemplo, el nodo code_node hace referencia a una interfaz del paquete SAMPLE_CODE.

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

Esta interfaz se define en el archivo de configuración del paquete, package.json. La interfaz especifica que el paquete es de lógica empresarial y que toma como entradas una secuencia de vídeo denominada video_in y un número de coma flotante denominado threshold. La interfaz también especifica que el código requiere un búfer de flujo de vídeo denominado video_out para enviar el vídeo a una pantalla

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

Volviendo al manifiesto de la aplicación, el nodo camera_node representa una transmisión de vídeo de una cámara. Incluye un decorador que aparece en la consola cuando despliegue la aplicación y le pide que seleccione una secuencia de cámara.

ejemplo graphs/aws-panorama-sample/graph.json – Nodo de cámara
{ "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 de parámetros, threshold_param, define el parámetro de umbral de confianza utilizado por el código de la aplicación. Tiene un valor predeterminado de 60 y se puede anular durante la implementación.

ejemplo graphs/aws-panorama-sample/graph.json: nodo de parámetros
{ "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 sección final del manifiesto de la aplicación, edges, establece conexiones entre nodos. El flujo de vídeo de la cámara y el parámetro de umbral se conectan a la entrada del nodo de código, y la salida de vídeo del nodo de código se conecta a la pantalla.

ejemplo graphs/aws-panorama-sample/graph.json: periferias
"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" } ]

Crear con la aplicación de muestra

Puede utilizar la aplicación de muestra como punto de partida para su propia aplicación.

El nombre de cada paquete debe ser exclusivo de su cuenta. Si tanto usted como otro usuario de su cuenta utilizan un nombre de paquete genérico, por ejemplo code o model, es posible que obtengan una versión incorrecta del paquete cuando lo desplieguen. Cambie el nombre del paquete de códigos por uno que represente su aplicación.

Para cambiar el nombre del paquete de códigos
  1. Cambie el nombre de la carpeta del paquete: packages/123456789012-SAMPLE_CODE-1.0/.

  2. Actualice el nombre del paquete en las siguientes ubicaciones.

    • Manifiesto de la aplicacióngraphs/aws-panorama-sample/graph.json

    • Configuración de paquetepackages/123456789012-SAMPLE_CODE-1.0/package.json

    • Script de compilación3-build-container.sh

Para actualizar el código de la aplicación
  1. Modifique el código de la aplicación en packages/123456789012-SAMPLE_CODE-1.0/src/application.py.

  2. Para crear el contenedor, ejecute 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 elimina automáticamente el activo contenedor anterior de la carpeta assets y actualiza la configuración del paquete.

  3. Para cargar los paquetes, ejecute 4-package-application.py.

  4. Abra la página Aplicaciones implementadas de la consola de AWS Panorama.

  5. Elija una aplicación.

  6. Elija Reemplazar.

  7. Complete los pasos para implementar la aplicación. Si es necesario, puede realizar cambios en el manifiesto de la aplicación, las transmisiones de la cámara o los parámetros.

Cambiar el modelo de visión artificial

La aplicación de muestra incluye un modelo de visión artificial. Para usar su propio modelo, modifique la configuración del nodo del modelo y utilice la CLI de la aplicación de AWS Panorama para importarlo como un activo.

El siguiente ejemplo usa un modelo ResNet50 de SSD MXNet que puedes descargar del repositorio de GitHub de esta guía: ssd_512_resnet50_v1_voc.tar.gz

Para cambiar el modelo de la aplicación de muestra
  1. Cambie el nombre de la carpeta del paquete para que coincida con su modelo. Por ejemplo, para packages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/.

  2. Actualice el nombre del paquete en las siguientes ubicaciones.

    • Manifiesto de la aplicacióngraphs/aws-panorama-sample/graph.json

    • Configuración de paquetepackages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/package.json

  3. En el archivo de configuración del paquete (package.json). Cambie el assets valor a una matriz en blanco.

    { "nodePackage": { "envelopeVersion": "2021-01-01", "name": "SSD_512_RESNET50_V1_VOC", "version": "1.0", "description": "Compact classification model", "assets": [],
  4. Abra el archivo descriptor del paquete (descriptor.json). Actualice los valores framework y shape para que coincidan con su modelo.

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

    El valor de forma, 1,3,512,512, indica el número de imágenes que el modelo toma como entrada (1), el número de canales de cada imagen (3: rojo, verde y azul) y las dimensiones de la imagen (512 x 512). Los valores y el orden de la matriz varían de un modelo a otro.

  5. Importe el modelo con la CLI de la aplicación de AWS Panorama. La CLI de la aplicación de AWS Panorama copia los archivos del modelo y del descriptor en la carpeta assets con nombres exclusivos y actualiza la configuración del paquete.

    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. Para cargar el modelo, ejecute 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
  7. Actualice el código de la aplicación. La mayor parte del código se puede reutilizar. El código específico de la respuesta del modelo está en el método 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)

    En función del modelo, es posible que también tenga que actualizar el método preprocess.

Preprocesamiento de imágenes

Antes de enviar una imagen al modelo, la prepara para la inferencia redimensionándola y normalizando los datos de color. El modelo que utiliza la aplicación requiere una imagen de 224 x 224 píxeles con tres canales de color, para que coincida con el número de entradas de su primera capa. La aplicación ajusta cada valor de color convirtiéndolo en un número entre 0 y 1, restando el valor promedio de ese color y dividiéndolo por la desviación estándar. Finalmente, combina los canales de color y los convierte en una matriz NumPy que el modelo puede procesar.

ejemplo application.py: preprocesamiento
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)

Este proceso proporciona al modelo valores en un rango predecible centrado alrededor de 0. Coincide con el preprocesamiento aplicado a las imágenes del conjunto de datos de entrenamiento, que es un enfoque estándar, pero puede variar según el modelo.

Carga de métricas con el SDK para Python

La aplicación de muestra usa el SDK para Python para cargar métricas en Amazon CloudWatch.

ejemplo application.py: SDK para 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.")

Obtiene el permiso de un rol de tiempo de ejecución que usted asigna durante la implementación. El rol se define en la plantilla aws-panorama-sample.yml AWS CloudFormation.

ejemplo 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/

La aplicación de muestra instala el SDK para Python y otras dependencias con pip. Al crear el contenedor de aplicaciones, Dockerfile ejecuta comandos para instalar bibliotecas sobre lo que viene con la imagen base.

ejemplo 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

Para usar el SDK de AWS en el código de la aplicación, primero modifique la plantilla para añadir permisos a todas las acciones de la API que utilice la aplicación. Actualice la pila AWS CloudFormation ejecutando 1-create-role.sh cada vez que realice un cambio. Luego, implemente los cambios en el código de su aplicación.

En el caso de las acciones que modifican o utilizan los recursos existentes, se recomienda minimizar el alcance de esta política especificando un nombre o patrón para el objetivo Resource en una declaración aparte. Para obtener información sobre las acciones y los recursos que admite cada servicio, consulte Acciones, recursos y claves de condiciones en la Referencia de autorización de servicios

Pasos siguientes

Para obtener instrucciones sobre el uso de la CLI de aplicaciones de AWS Panorama para crear aplicaciones y paquetes desde cero, consulte el README de la CLI.

Para obtener más código de muestra y una utilidad de prueba que pueda usar para validar el código de la aplicación antes de la implementación, visite el repositorio de muestras de AWS Panorama.