{ "cells": [ { "cell_type": "markdown", "id": "72452dbc", "metadata": {}, "source": [ "## Lab 2. Object tracking\n", "\n", "This notebook is intended to be run along with the [Workshop document](https://catalog.workshops.aws/panorama-immersion-day/en-US/30-lab2-object-tracking/31-lab2)." ] }, { "cell_type": "markdown", "id": "636409e9", "metadata": {}, "source": [ "## Preparation" ] }, { "cell_type": "code", "execution_count": null, "id": "cb937fe4", "metadata": {}, "outputs": [], "source": [ "# Import libraries\n", "\n", "import sys\n", "import os\n", "import time\n", "import json\n", "import glob\n", "import tarfile\n", "\n", "import boto3\n", "import sagemaker\n", "import IPython\n", "import gluoncv\n", "\n", "sys.path.insert( 0, os.path.abspath( \"../common/test_utility\" ) )\n", "import panorama_test_utility" ] }, { "cell_type": "code", "execution_count": null, "id": "f07b2eef", "metadata": {}, "outputs": [], "source": [ "# Initialize variables and configurations\n", "\n", "boto3_session = boto3.session.Session()\n", "sm_session = sagemaker.Session()\n", "\n", "account_id = boto3.client(\"sts\").get_caller_identity()[\"Account\"]\n", "region = boto3_session.region_name\n", "s3_bucket = sm_session.default_bucket()\n", "sm_role = sagemaker.get_execution_role()\n", "\n", "print( \"account_id :\", account_id )\n", "print( \"region :\", region )\n", "print( \"s3_bucket :\", s3_bucket )\n", "print( \"sm_role :\", sm_role )" ] }, { "cell_type": "markdown", "id": "1c9df62a", "metadata": {}, "source": [ "## Start with \"People detection\" application" ] }, { "cell_type": "code", "execution_count": null, "id": "29a56d4a", "metadata": {}, "outputs": [], "source": [ "app_name = \"lab2\"\n", "\n", "!cd {app_name} && panorama-cli import-application" ] }, { "cell_type": "code", "execution_count": null, "id": "8ecd0353", "metadata": {}, "outputs": [], "source": [ "code_package_name = f\"{app_name}_code\"\n", "code_package_version = \"1.0\"\n", "source_filename = f\"./lab2/packages/{account_id}-{code_package_name}-{code_package_version}/src/app.py\"\n", "\n", "panorama_test_utility.preview_text_file(source_filename)" ] }, { "cell_type": "code", "execution_count": null, "id": "9ff8c892", "metadata": {}, "outputs": [], "source": [ "def export_model_and_create_targz( prefix, name, model ):\n", " os.makedirs( prefix, exist_ok=True )\n", " gluoncv.utils.export_block( os.path.join( prefix, name ), model, preprocess=False, layout=\"CHW\" )\n", "\n", " tar_gz_filename = f\"{prefix}/{name}.tar.gz\"\n", " with tarfile.open( tar_gz_filename, \"w:gz\" ) as tgz:\n", " tgz.add( f\"{prefix}/{name}-symbol.json\", f\"{name}-symbol.json\" )\n", " tgz.add( f\"{prefix}/{name}-0000.params\", f\"{name}-0000.params\" )\n", " \n", " print( f\"Exported : {tar_gz_filename}\" )\n", " \n", "# Export object detection model. Reset the classes for human detection only.\n", "people_detection_model = gluoncv.model_zoo.get_model('yolo3_mobilenet1.0_coco', pretrained=True)\n", "people_detection_model.reset_class([\"person\"], reuse_weights=['person'])\n", "export_model_and_create_targz( \"models\", \"yolo3_mobilenet1.0_coco_person\", people_detection_model )" ] }, { "cell_type": "code", "execution_count": null, "id": "269d2611", "metadata": {}, "outputs": [], "source": [ "model_package_name = f\"{app_name}_model\"\n", "model_package_version = \"1.0\"\n", "people_detection_model_name = \"people_detection_model\"\n", "\n", "!cd {app_name} && panorama-cli add-raw-model \\\n", " --model-asset-name {people_detection_model_name} \\\n", " --model-local-path ../models/yolo3_mobilenet1.0_coco_person.tar.gz \\\n", " --descriptor-path packages/{account_id}-{model_package_name}-{model_package_version}/descriptor.json \\\n", " --packages-path packages/{account_id}-{model_package_name}-{model_package_version}" ] }, { "cell_type": "code", "execution_count": null, "id": "30ee18ab", "metadata": {}, "outputs": [], "source": [ "people_detection_model_data_shape = '{\"data\":[1,3,480,600]}'\n", "\n", "%run ../common/test_utility/panorama_test_utility_compile.py \\\n", "\\\n", "--s3-model-location s3://{s3_bucket}/panorama-workshop/{app_name} \\\n", "\\\n", "--model-node-name {people_detection_model_name} \\\n", "--model-file-basename ./models/yolo3_mobilenet1.0_coco_person \\\n", "--model-data-shape '{people_detection_model_data_shape}' \\\n", "--model-framework MXNET" ] }, { "cell_type": "code", "execution_count": null, "id": "d408e9f5", "metadata": {}, "outputs": [], "source": [ "video_filepath = \"../../videos/TownCentreXVID.avi\"\n", "\n", "%run ../common/test_utility/panorama_test_utility_run.py \\\n", "\\\n", "--app-name {app_name} \\\n", "--code-package-name {code_package_name} \\\n", "--py-file {source_filename} \\\n", "\\\n", "--model-package-name {model_package_name} \\\n", "--model-node-name {people_detection_model_name} \\\n", "--model-file-basename ./models/yolo3_mobilenet1.0_coco_person \\\n", "\\\n", "--camera-node-name lab2_camera \\\n", "\\\n", "--video-file {video_filepath} \\\n", "--video-start 0 \\\n", "--video-stop 100 \\\n", "--video-step 10 \\\n", "\\\n", "--output-screenshots ./screenshots/%Y%m%d_%H%M%S" ] }, { "cell_type": "code", "execution_count": null, "id": "46d7b285", "metadata": {}, "outputs": [], "source": [ "# View latest screenshot image\n", "\n", "latest_screenshot_dirname = sorted( glob.glob( \"./screenshots/*\" ) )[-1]\n", "screenshot_filename = sorted( glob.glob( f\"{latest_screenshot_dirname}/*.png\" ) )[-1]\n", "\n", "print(screenshot_filename)\n", "IPython.display.Image( filename = screenshot_filename )" ] }, { "cell_type": "markdown", "id": "1d011d8b", "metadata": {}, "source": [ "## Extend to \"People tracking\" application" ] }, { "cell_type": "markdown", "id": "4eaa971f", "metadata": {}, "source": [ "
Manual edit needed: Manually edit the application source code referring to the Workshop document.
" ] }, { "cell_type": "code", "execution_count": null, "id": "8b1ebb33", "metadata": {}, "outputs": [], "source": [ "video_filepath = \"../../videos/TownCentreXVID.avi\"\n", "\n", "%run ../common/test_utility/panorama_test_utility_run.py \\\n", "\\\n", "--app-name {app_name} \\\n", "--code-package-name {code_package_name} \\\n", "--py-file {source_filename} \\\n", "\\\n", "--model-package-name {model_package_name} \\\n", "--model-node-name {people_detection_model_name} \\\n", "--model-file-basename ./models/yolo3_mobilenet1.0_coco_person \\\n", "\\\n", "--camera-node-name lab2_camera \\\n", "\\\n", "--video-file {video_filepath} \\\n", "--video-start 0 \\\n", "--video-stop 100 \\\n", "--video-step 10 \\\n", "\\\n", "--output-screenshots ./screenshots/%Y%m%d_%H%M%S" ] }, { "cell_type": "code", "execution_count": null, "id": "65b4e2b2", "metadata": {}, "outputs": [], "source": [ "# View 1st and last frame image with Object Tracking\n", "latest_screenshot_dirname = sorted( glob.glob( \"./screenshots/*\" ) )[-1]\n", "\n", "# This is the 1st frame \n", "screenshot_filename = sorted( glob.glob( f\"{latest_screenshot_dirname}/*.png\" ) )[0]\n", "print(screenshot_filename)\n", "IPython.display.Image( filename = screenshot_filename )" ] }, { "cell_type": "code", "execution_count": null, "id": "36851217", "metadata": {}, "outputs": [], "source": [ "# This is the 10th frame \n", "screenshot_filename = sorted( glob.glob( f\"{latest_screenshot_dirname}/*.png\" ) )[-1]\n", "print(screenshot_filename)\n", "IPython.display.Image( filename = screenshot_filename )" ] }, { "cell_type": "markdown", "id": "de44ca19", "metadata": {}, "source": [ "## Run the people tracking application on real device" ] }, { "cell_type": "code", "execution_count": null, "id": "6c66e481", "metadata": {}, "outputs": [], "source": [ "panorama_client = boto3.client(\"panorama\")" ] }, { "cell_type": "code", "execution_count": null, "id": "fe59fda4", "metadata": {}, "outputs": [], "source": [ "response = panorama_client.list_devices()\n", "for device in response[\"Devices\"]:\n", " if device[\"ProvisioningStatus\"]==\"SUCCEEDED\":\n", " break\n", "else:\n", " assert False, \"Provisioned device not found.\"\n", "\n", "device_id = device[\"DeviceId\"]\n", "\n", "print( \"%s : %s\" % (device[\"Name\"], device[\"DeviceId\"]) )" ] }, { "cell_type": "code", "execution_count": null, "id": "151f1bde", "metadata": {}, "outputs": [], "source": [ "!cd {app_name} && panorama-cli build-container --container-asset-name code --package-path packages/{account_id}-{code_package_name}-{code_package_version}" ] }, { "cell_type": "code", "execution_count": null, "id": "001d9f2e", "metadata": {}, "outputs": [], "source": [ "!cd {app_name} && panorama-cli package-application" ] }, { "cell_type": "markdown", "id": "ada89f9c", "metadata": {}, "source": [ "
Manual operation needed: Look up data source name on the Management Console, referring to the Workshop document.
" ] }, { "cell_type": "markdown", "id": "2851ca5a", "metadata": {}, "source": [ "
Manual edit needed: Manually edit override manifest file referring to the Workshop document.
" ] }, { "cell_type": "code", "execution_count": null, "id": "c012c3d8", "metadata": {}, "outputs": [], "source": [ "response = panorama_client.describe_device( DeviceId = device_id )\n", "eth0_status = response[\"CurrentNetworkingStatus\"][\"Ethernet0Status\"][\"ConnectionStatus\"]\n", "eth1_status = response[\"CurrentNetworkingStatus\"][\"Ethernet1Status\"][\"ConnectionStatus\"]\n", "\n", "print( \"eth0 :\", eth0_status)\n", "print( \"eth1 :\", eth1_status)\n", "\n", "assert eth0_status==\"CONNECTED\" or eth1_status==\"CONNECTED\"" ] }, { "cell_type": "code", "execution_count": null, "id": "ba51d454", "metadata": {}, "outputs": [], "source": [ "def get_escaped_payload_from_json(filename):\n", " with open(filename) as fd:\n", " return json.dumps(json.loads(fd.read()))\n", "\n", "manifest_payload = get_escaped_payload_from_json( f\"./{app_name}/graphs/{app_name}/graph.json\" )\n", "override_payload = get_escaped_payload_from_json( f\"./{app_name}/graphs/{app_name}/override.json\" )\n", "\n", "response = panorama_client.create_application_instance(\n", " Name = app_name,\n", " DefaultRuntimeContextDevice = device_id,\n", " ManifestPayload = {\"PayloadData\":manifest_payload},\n", " ManifestOverridesPayload = {\"PayloadData\":override_payload},\n", ")\n", "\n", "application_instance_id = response[\"ApplicationInstanceId\"]\n", "\n", "response" ] }, { "cell_type": "code", "execution_count": null, "id": "6ba943bb", "metadata": {}, "outputs": [], "source": [ "def wait_deployment( application_instance_id ):\n", " \n", " progress_dots = panorama_test_utility.ProgressDots() \n", " while True:\n", " app = panorama_client.describe_application_instance( ApplicationInstanceId = application_instance_id )\n", " progress_dots.update_status( \"%s (%s)\" % (app[\"Status\"], app[\"StatusDescription\"]) )\n", " if app[\"Status\"] not in ( \"DEPLOYMENT_PENDING\", \"DEPLOYMENT_REQUESTED\", \"DEPLOYMENT_IN_PROGRESS\" ):\n", " break\n", " time.sleep(60)\n", "\n", "wait_deployment( application_instance_id )" ] }, { "cell_type": "code", "execution_count": null, "id": "befe2d82", "metadata": {}, "outputs": [], "source": [ "logs_url = panorama_test_utility.get_logs_url( region, device_id, application_instance_id )\n", "print( \"CloudWatch Logs URL :\" )\n", "print( logs_url )" ] }, { "cell_type": "markdown", "id": "f3353f43", "metadata": {}, "source": [ "
Manual operation needed: Confirm the application is running as expected by visitting the CloudWatch Logs link above and seeing HDMI display.
" ] }, { "cell_type": "code", "execution_count": null, "id": "563bd36c", "metadata": {}, "outputs": [], "source": [ "panorama_test_utility.remove_application( device_id, application_instance_id )" ] }, { "cell_type": "code", "execution_count": null, "id": "45ef6ade", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.13" } }, "nbformat": 4, "nbformat_minor": 5 }