Entwicklung von AWS-Panorama-Anwendungen - AWS Panorama

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Entwicklung von AWS-Panorama-Anwendungen

Sie können die Beispielanwendung verwenden, um mehr über die Anwendungsstruktur von AWS Panorama zu erfahren, und sie als Ausgangspunkt für Ihre eigene Anwendung verwenden.

Das folgende Diagramm zeigt die Hauptkomponenten der Anwendung, die auf einer AWS Panorama Appliance ausgeführt wird. Der Anwendungscode verwendet das AWS Panorama Application SDK, um Bilder abzurufen und mit dem Modell zu interagieren, auf das er keinen direkten Zugriff hat. Die Anwendung gibt Video auf ein angeschlossenes Display aus, sendet jedoch keine Bilddaten außerhalb Ihres lokalen Netzwerks.

Beispielanwendungsarchitektur für AWS Panorama.

In diesem Beispiel verwendet die Anwendung das AWS Panorama Application SDK, um Videobilder von einer Kamera abzurufen, die Videodaten vorzuverarbeiten und die Daten an ein Computer-Vision-Modell zu senden, das Objekte erkennt. Die Anwendung zeigt das Ergebnis auf einem HDMI-Display an, das an die Appliance angeschlossen ist.

Das Anwendungsmanifest

Das Anwendungsmanifest ist eine Datei, die graph.json im graphs Ordner benannt ist. Das Manifest definiert die Komponenten der Anwendung, bei denen es sich um Pakete, Knoten und Kanten handelt.

Pakete sind Code-, Konfigurations- und Binärdateien für Anwendungscode, Modelle, Kameras und Displays. Die Beispielanwendung verwendet 4 Pakete:

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

Die ersten beiden Pakete sind innerhalb der Anwendung im packages Verzeichnis definiert. Sie enthalten den Code und das Modell, die für diese Anwendung spezifisch sind. Bei den zweiten beiden Paketen handelt es sich um generische Kamera- und Display-Pakete, die vom AWS Panorama Panorama-Service bereitgestellt werden. Das abstract_rtsp_media_source Paket ist ein Platzhalter für eine Kamera, den Sie bei der Bereitstellung überschreiben. Das hdmi_data_sink Paket stellt den HDMI-Ausgangsanschluss am Gerät dar.

Knoten sind Schnittstellen zu Paketen sowie nicht paketspezifische Parameter, die Standardwerte haben können, die Sie bei der Bereitstellung überschreiben. Die Code- und Modellpakete definieren Schnittstellen in package.json Dateien, die Eingaben und Ausgaben angeben. Dabei kann es sich um Videostreams oder um einen grundlegenden Datentyp wie Float, Boolean oder String handeln.

Der code_node Knoten bezieht sich beispielsweise auf eine Schnittstelle aus dem SAMPLE_CODE Paket.

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

Diese Schnittstelle ist in der Paketkonfigurationsdatei definiert,package.json. Die Schnittstelle gibt an, dass es sich bei dem Paket um Geschäftslogik handelt und dass es einen Videostream mit einem Namen video_in und eine angegebene Fließkommazahl threshold als Eingaben verwendet. Die Schnittstelle gibt außerdem an, dass der Code einen Videostream-Puffer benötigt, der benannt istvideo_out, um Video auf einem Bildschirm auszugeben

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

Zurück im Anwendungsmanifest steht der camera_node Knoten für einen Videostream von einer Kamera. Er enthält einen Decorator, der bei der Bereitstellung der Anwendung in der Konsole angezeigt wird und Sie auffordert, einen Kamerastream auszuwählen.

Beispiel graphs/aws-panorama-sample/graph.json— Kameraknoten
{ "name": "camera_node", "interface": "panorama::abstract_rtsp_media_source.rtsp_v1_interface", "overridable": true, "launch": "onAppStart", "decorator": { "title": "Camera", "description": "Choose a camera stream." } },

Ein Parameterknoten,threshold_param, definiert den vom Anwendungscode verwendeten Konfidenzschwellenwert. Er hat einen Standardwert von 60 und kann während der Bereitstellung außer Kraft gesetzt werden.

Beispiel graphs/aws-panorama-sample/graph.json— Parameterknoten
{ "name": "threshold_param", "interface": "float32", "value": 60.0, "overridable": true, "decorator": { "title": "Confidence threshold", "description": "The minimum confidence for a classification to be recorded." } }

Der letzte Abschnitt des Anwendungsmanifests stellt Verbindungen zwischen Knoten her. edges Der Videostream der Kamera und der Schwellenwertparameter sind mit dem Eingang des Codeknotens verbunden, und der Videoausgang des Codeknotens ist mit dem Display verbunden.

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

Bauen mit der Beispielanwendung

Sie können die Beispielanwendung als Ausgangspunkt für Ihre eigene Anwendung verwenden.

Der Name jedes Pakets muss in Ihrem Konto eindeutig sein. Wenn Sie und ein anderer Benutzer in Ihrem Konto beide einen generischen Paketnamen wie code oder verwendenmodel, erhalten Sie bei der Bereitstellung möglicherweise die falsche Version des Pakets. Ändern Sie den Namen des Codepakets in einen Namen, der Ihrer Anwendung entspricht.

Um das Codepaket umzubenennen
  1. Benennen Sie den Paketordner um:packages/123456789012-SAMPLE_CODE-1.0/.

  2. Aktualisieren Sie den Paketnamen an den folgenden Speicherorten.

    • Anwendungsmanifestgraphs/aws-panorama-sample/graph.json

    • Paketkonfigurationpackages/123456789012-SAMPLE_CODE-1.0/package.json

    • Skript erstellen3-build-container.sh

Um den Code der Anwendung zu aktualisieren
  1. Ändern Sie den Anwendungscode inpackages/123456789012-SAMPLE_CODE-1.0/src/application.py.

  2. Führen Sie den Befehl aus, um den Container zu erstellen3-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

    Die CLI löscht automatisch das alte Container-Asset aus dem assets Ordner und aktualisiert die Paketkonfiguration.

  3. Führen 4-package-application.py Sie den Befehl aus, um die Pakete hochzuladen.

  4. Öffnen Sie die Seite Bereitgestellte Anwendungen der AWS-Panorama-Konsole.

  5. Wählen Sie eine Anwendung aus.

  6. Wählen Sie Replace (Ersetzen) aus.

  7. Führen Sie die Schritte zur Bereitstellung der Anwendung aus. Bei Bedarf können Sie Änderungen am Anwendungsmanifest, an den Kamerastreams oder an den Parametern vornehmen.

Änderung des Computer-Vision-Modells

Die Beispielanwendung umfasst ein Computer-Vision-Modell. Um Ihr eigenes Modell zu verwenden, ändern Sie die Konfiguration des Modellknotens und verwenden Sie die AWS Panorama Application CLI, um es als Asset zu importieren.

Im folgenden Beispiel wird ein MXNet SSD ResNet 50-Modell verwendet, das Sie aus dem GitHub Repo dieses Handbuchs herunterladen können: ssd_512_resnet50_v1_voc.tar.gz

Um das Modell der Beispielanwendung zu ändern
  1. Benennen Sie den Paketordner so um, dass er Ihrem Modell entspricht. Zum Beispiel zupackages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/.

  2. Aktualisieren Sie den Paketnamen an den folgenden Speicherorten.

    • Anwendungsmanifestgraphs/aws-panorama-sample/graph.json

    • Paketkonfigurationpackages/123456789012-SSD_512_RESNET50_V1_VOC-1.0/package.json

  3. In der Paketkonfigurationsdatei (package.json). Ändern Sie den assets Wert in ein leeres Array.

    { "nodePackage": { "envelopeVersion": "2021-01-01", "name": "SSD_512_RESNET50_V1_VOC", "version": "1.0", "description": "Compact classification model", "assets": [],
  4. Öffnen Sie die Paketdeskriptordatei (descriptor.json). Aktualisieren Sie die shape Werte framework und, sodass sie Ihrem Modell entsprechen.

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

    Der Wert für Form1,3,512,512, gibt die Anzahl der Bilder an, die das Modell als Eingabe verwendet (1), die Anzahl der Kanäle in jedem Bild (3 — Rot, Grün und Blau) und die Abmessungen des Bildes (512 x 512). Die Werte und die Reihenfolge des Arrays variieren je nach Modell.

  5. Importieren Sie das Modell mit der AWS Panorama Application CLI. Die AWS Panorama Application CLI kopiert die Modell- und Deskriptordateien in den assets Ordner mit eindeutigen Namen und aktualisiert die Paketkonfiguration.

    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. Führen panorama-cli package-application Sie den Befehl aus, um das Modell hochzuladen.

    $ 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. Aktualisieren Sie den Anwendungscode. Der größte Teil des Codes kann wiederverwendet werden. Der Code, der für die Antwort des Modells spezifisch ist, ist in der process_results Methode enthalten.

    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)

    Je nach Modell müssen Sie möglicherweise auch die preprocess Methode aktualisieren.

Vorverarbeitung von Bildern

Bevor die Anwendung ein Bild an das Modell sendet, bereitet sie es für die Inferenz vor, indem sie die Größe ändert und die Farbdaten normalisiert. Das von der Anwendung verwendete Modell benötigt ein 224 x 224 Pixel großes Bild mit drei Farbkanälen, um der Anzahl der Eingaben in der ersten Ebene zu entsprechen. Die Anwendung passt jeden Farbwert an, indem sie ihn in eine Zahl zwischen 0 und 1 umwandelt, den Durchschnittswert für diese Farbe subtrahiert und durch die Standardabweichung dividiert. Schließlich kombiniert sie die Farbkanäle und konvertiert sie in ein NumPy Array, das das Modell verarbeiten kann.

Beispiel application.py — Vorverarbeitung
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)

Durch diesen Vorgang erhält das Modell Werte in einem vorhersehbaren Bereich, dessen Mittelpunkt um 0 liegt. Er entspricht der Vorverarbeitung, die auf Bilder im Trainingsdatensatz angewendet wird. Dabei handelt es sich um einen Standardansatz, der jedoch je nach Modell variieren kann.

Metriken mit dem SDK für Python hochladen

Die Beispielanwendung verwendet das SDK für Python, um Metriken auf Amazon hochzuladen CloudWatch.

Beispiel application.py — SDK für 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.")

Es erhält die Erlaubnis von einer Runtime-Rolle, die Sie während der Bereitstellung zuweisen. Die Rolle ist in der aws-panorama-sample.yml AWS CloudFormation Vorlage definiert.

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

Die Beispielanwendung installiert das SDK für Python und andere Abhängigkeiten mit pip. Wenn Sie den Anwendungscontainer erstellen, Dockerfile führt er Befehle aus, um Bibliotheken zusätzlich zum Basisimage zu installieren.

Beispiel Docker-Datei
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

Um das AWS SDK in Ihrem Anwendungscode zu verwenden, ändern Sie zunächst die Vorlage, um Berechtigungen für alle API-Aktionen hinzuzufügen, die die Anwendung verwendet. Aktualisieren Sie den AWS CloudFormation Stack, indem Sie bei 1-create-role.sh jeder Änderung den ausführen. Stellen Sie dann Änderungen an Ihrem Anwendungscode bereit.

Bei Aktionen, die vorhandene Ressourcen ändern oder nutzen, empfiehlt es sich, den Geltungsbereich dieser Richtlinie zu minimieren, indem Sie Resource in einer separaten Anweisung einen Namen oder ein Muster für das Ziel angeben. Einzelheiten zu den Aktionen und Ressourcen, die von den einzelnen Diensten unterstützt werden, finden Sie unter Aktionen, Ressourcen und Bedingungsschlüssel in der Service Authorization Reference

Nächste Schritte

Anweisungen zur Verwendung der AWS Panorama Application CLI zum Erstellen von Anwendungen und Paketen von Grund auf finden Sie in der README-Datei der CLI.

Weitere Beispielcodes und ein Testprogramm, mit dem Sie Ihren Anwendungscode vor der Bereitstellung überprüfen können, finden Sie im AWS Panorama Samples Repository.