As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Desenvolvimento de aplicativos do AWS Panorama
Você pode usar a aplicação de exemplo para saber como usar a estrutura da aplicação do AWS Panorama e como ponto de partida para sua própria aplicação.
O diagrama a seguir mostra os principais componentes da aplicação em execução em um dispositivo AWS Panorama. O código da aplicação usa o SDK para aplicações do AWS Panorama para obter imagens e interagir com o modelo, ao qual ele não tem acesso direto. A aplicação envia vídeos para um monitor conectado, mas não envia dados de imagem para fora da rede local.
![Arquitetura da aplicação de exemplo do AWS Panorama.](images/sample-app.png)
Neste exemplo, a aplicação usa o SDK para aplicações do AWS Panorama para obter quadros de vídeo de uma câmera, pré-processar os dados do vídeo e enviar os dados para um modelo de visão computacional que detecta objetos. A aplicação exibe o resultado em um monitor HDMI conectado ao aparelho.
Seções
O manifesto da aplicação
O manifesto da aplicação é um arquivo chamado graph.json
na graphs
pasta. O manifesto define os componentes da aplicação, que são pacotes, nós e bordas.
Os pacotes são arquivos binários, de código e de configuração com informações de código de aplicação, modelos, câmeras e monitores. O aplicativo de exemplo usa 4 pacotes:
exemplo Pacotes do 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" } ],
Os dois primeiros pacotes são definidos na aplicação, no diretório packages
. Eles contêm o código e o modelo específicos dessa aplicação. Os dois segundos pacotes são pacotes genéricos de câmeras e monitor fornecidos pelo serviço AWS Panorama. O pacote abstract_rtsp_media_source
é um espaço reservado para uma câmera, que é substituído durante a implantação. O pacote hdmi_data_sink
representa o conector de saída HDMI no dispositivo.
Os nós são interfaces para pacotes, bem como parâmetros que não são de pacotes e que podem ter valores padrão que serão substituídos no momento da implantação. Os pacotes de código e modelo definem interfaces em arquivos package.json
que especificam entradas e saídas, que podem ser streams de vídeo ou um tipo de dados básico, como float, booleano ou string.
Por exemplo, o nó code_node
se refere a uma interface do pacote SAMPLE_CODE
.
"nodes": [ { "name": "code_node", "interface": "123456789012::SAMPLE_CODE.interface", "overridable": false, "launch": "onAppStart" },
Essa interface é definida no arquivo de configuração do pacote, package.json
. A interface especifica que o pacote é uma lógica de negócios e que usa um stream de vídeo chamado video_in
e um número de ponto flutuante chamado threshold
como entradas. A interface também especifica que o código requer um buffer de stream de vídeo chamado video_out
para enviar vídeo para um monitor.
exemplo 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 volta ao manifesto da aplicação, o nó camera_node
representa um stream de vídeo de uma câmera. Ele inclui um decorador que aparece no console quando você implanta a aplicação, solicitando que você escolha um stream de uma câmera.
exemplo Nós de câmera do graphs/aws-panorama-sample/graph.json
{ "name": "camera_node", "interface": "panorama::abstract_rtsp_media_source.rtsp_v1_interface", "overridable": true, "launch": "onAppStart", "decorator": { "title": "Camera", "description": "Choose a camera stream." } },
Um nó de parâmetro threshold_param
define o parâmetro de limite de confiança usado pelo código da aplicação. Ele tem um valor padrão de 60 e pode ser substituído durante a implantação.
exemplo Nó de parâmetro do 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." } }
A seção final do manifesto da aplicação, edges
, faz conexões entre os nós. O stream de vídeo da câmera e o parâmetro de limite se conectam à entrada do nó do código, e a saída de vídeo do nó do código se conecta ao monitor.
exemplo Bordas do 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" } ]
Compilação com a aplicação de exemplo
Você pode usar a aplicação exemplo como um ponto de partida para criar sua própria aplicação.
O nome de cada pacote deve ser exclusivo em sua conta. Se você e outro usuário da sua conta usarem um nome de pacote genérico, como code
oumodel
, você poderá obter a versão errada do pacote ao implantar. Altere o nome do pacote de código para um nome que represente sua aplicação.
Para renomear o pacote de código
-
Renomeie a pasta do pacote:
packages/123456789012-
.SAMPLE_CODE
-1.0/ -
Atualize o nome do pacote nos seguintes locais.
-
Manifesto da aplicação:
graphs/aws-panorama-sample/graph.json
-
Configuração do pacote:
packages/123456789012-SAMPLE_CODE-1.0/package.json
-
Script de compilação:
3-build-container.sh
-
Para atualizar o código do aplicativo
-
Modifique o código da aplicação em
packages/123456789012-SAMPLE_CODE-1.0/src/application.py
. -
Para criar o contêiner, execute
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.gzA CLI exclui automaticamente o ativo de contêiner antigo da pasta
assets
e atualiza a configuração do pacote. -
Para carregar os pacotes, execute
4-package-application.py
. Abra a Página de aplicações implantadas
do console do AWS Panorama. Escolha a aplicação.
-
Selecione Replace (Substituir).
-
Conclua as etapas para implantar a aplicação. Se necessário, você pode fazer alterações no manifesto da aplicação, nos streams da câmera ou nos parâmetros.
Alteração do modelo de visão computacional
A aplicação de exemplo inclui um modelo de visão computacional. Para usar seu próprio modelo, modifique a configuração do nó do modelo e use a CLI da aplicação do AWS Panorama para importá-lo como um ativo.
O exemplo a seguir usa um modelo MXNet SSD ResNet50 que você pode baixar do repositório GitHub deste guia: ssd_512_resnet50_v1_voc.tar.gz
Para alterar o modelo da aplicação de exemplo
-
Renomeie a pasta do pacote de forma que o nome dela corresponda ao seu modelo. Por exemplo, para
packages/
.123456789012
-SSD_512_RESNET50_V1_VOC
-1.0/ -
Atualize o nome do pacote nos seguintes locais.
-
Manifesto da aplicação:
graphs/aws-panorama-sample/graph.json
-
Configuração do pacote:
packages/
123456789012
-SSD_512_RESNET50_V1_VOC
-1.0/package.json
-
-
No arquivo de configuração do pacote (
package.json
). Altere o valorassets
para uma matriz em branco.{ "nodePackage": { "envelopeVersion": "2021-01-01", "name": "SSD_512_RESNET50_V1_VOC", "version": "1.0", "description": "Compact classification model", "assets":
[]
, -
Abra o arquivo descritor do pacote (
descriptor.json
). Atualize os valoresframework
eshape
para que correspondam ao seu modelo.{ "mlModelDescriptor": { "envelopeVersion": "2021-01-01", "framework": "
MXNET
", "inputs": [ { "name": "data", "shape": [1, 3, 512, 512
] } ] } }O valor da forma,
1,3,512,512
, indica o número de imagens que o modelo usa como entrada (1), o número de canais em cada imagem (3- vermelho, verde e azul) e as dimensões da imagem (512 x 512). Os valores e a ordem da matriz variam entre os modelos. -
Importe o modelo com a CLI da aplicação do AWS Panorama. A CLI da aplicação do AWS Panorama copia os arquivos de modelo e descritor na pasta
assets
com nomes exclusivos e atualiza a configuração do pacote.aws-panorama-sample$
panorama-cli add-raw-model --model-asset-name model-asset \ --model-local-path
{ "name": "model-asset", "implementations": [ { "type": "model", "assetUri": "b1a1589afe449b346ff47375c284a1998c3e1522b418a7be8910414911784ce1.tar.gz", "descriptorUri": "a6a9508953f393f182f05f8beaa86b83325f4a535a5928580273e7fe26f79e78.json" } ] }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
-
Para fazer o upload do modelo, execute
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
-
Atualize o código do aplicativo. A maior parte do código pode ser reutilizada. O código específico para a resposta do modelo está no 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)
Dependendo do seu modelo, talvez você também precise atualizar o método
preprocess
.
Pré-processamento de imagens
Antes de a aplicação enviar uma imagem para o modelo, ela a prepara para inferência redimensionando-a e normalizando os dados de cores. O modelo usado pela aplicação requer uma imagem de 224 x 224 pixels com três canais de cores, para corresponder ao número de entradas em sua primeira camada. A aplicação ajusta cada valor de cor convertendo-o em um número entre 0 e 1, subtraindo o valor médio dessa cor e dividindo o resultado pelo desvio padrão. Finalmente, ela combina os canais de cores e os converte em uma matriz NumPy que o modelo pode processar.
exemplo application.py : pré-processamento
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)
Esse processo fornece os valores do modelo em uma faixa previsível centrada em torno de 0. O processo corresponde ao pré-processamento aplicado às imagens no conjunto de dados de treinamento, que é uma abordagem padrão, mas pode variar de acordo com o modelo.
Upload de métricas com o SDK para Python
A aplicação de exemplo usa o SDK para Python para carregar métricas para o Amazon CloudWatch.
exemplo 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.")
Ela obtém permissão de uma função de runtime que você atribui durante a implantação. A função é definida no modelo aws-panorama-sample.yml
do AWS CloudFormation.
exemplo 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/
A aplicação de exemplo instala o SDK para Python e outras dependências com pip. Quando você cria o contêiner da aplicação, o Dockerfile
executa comandos para instalar bibliotecas acima do que vem com a imagem base.
exemplo 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 o SDK AWS no código da sua aplicação, primeiro modifique o modelo para adicionar permissões para todas as ações de API que a aplicação utiliza. Atualize a pilha do AWS CloudFormation executando 1-create-role.sh
toda vez que você fizer uma alteração. Em seguida, implante as alterações no código da sua aplicação.
Para ações que modificam ou usam recursos existentes, é uma prática recomendada minimizar o escopo dessa política especificando um nome ou padrão para o destino Resource
em uma declaração separada. Para obter detalhes sobre as ações e os recursos compatíveis com cada serviço, consulte Ação, recursos e chaves de condição na Referência de autorização do serviço
Próximas etapas
Para obter instruções sobre como usar a CLI da aplicação do AWS Panorama para criar aplicações e pacotes do zero, consulte o README da CLI.
Para obter mais exemplos de código e um utilitário de teste que você pode usar para validar o código da sua aplicação antes da implantação, visite o repositório de exemplos do AWS Panorama.