diff --git a/.github/workflows/example-checks.yml b/.github/workflows/example-checks.yml index e87ba75..7fa2955 100644 --- a/.github/workflows/example-checks.yml +++ b/.github/workflows/example-checks.yml @@ -15,11 +15,17 @@ jobs: run: | # Find directories that do not start with dot acap_list="$(find . -maxdepth 1 -type d -printf '%f\n' |grep -v '^[.]' | sort)" - # Find lines starting with '* [' - # The grep removes anything but '[*]', then remove entries with space - # or capital letter and finally removes the brackets. - endline="$(sed -n '/## Docker Hub images/=' README.md)" - readme_examples="$(sed -n "1,${endline}!d ; /* \[/p" README.md | grep -oe '\[.*\]' | grep -v '[A-Z ]' | grep -oe '[0-9a-z-]*')" + + # Find example application links in README.md + # The regular expression '^\* \[[0-9a-z-]*\]' matches lines starting with '* [' + # followed by alphanumeric characters and hyphens, and a closing ']' + example_links="$(grep -o '^\* \[[0-9a-z-]*\]' README.md)" + + # Remove '* [' prefix and trailing ']' from example links + # The sed command uses two substitutions: + # 1. 's/^\* \[//' removes the '* [' prefix from the start of the line + # 2. 's/\]$//' removes the trailing ']' from the end of the line + readme_examples="$(echo "$example_links" | sed 's/^\* \[//;s/\]$//')" # Control that all examples have an entry in README common=$(printf "${acap_list}\n${readme_examples}" | sort | uniq -d) diff --git a/.github/workflows/hello-world-python.yml b/.github/workflows/hello-world-python.yml index 4c86aa1..35796b5 100644 --- a/.github/workflows/hello-world-python.yml +++ b/.github/workflows/hello-world-python.yml @@ -25,4 +25,5 @@ jobs: imagetag: ${{ env.EXREPO }}_${{ env.EXNAME }}:1.0 run: | cd $EXNAME + docker run --rm --privileged multiarch/qemu-user-static --credential yes --persistent yes docker build --no-cache --tag $imagetag . diff --git a/.github/workflows/object-detector-python.yml b/.github/workflows/object-detector-python.yml index b846326..bfae510 100644 --- a/.github/workflows/object-detector-python.yml +++ b/.github/workflows/object-detector-python.yml @@ -31,5 +31,6 @@ jobs: modeltag: ${{ env.EXREPO }}_${{ env.EXNAME }}-${{ matrix.chip }}-model:1.0 run: | cd $EXNAME + docker run --rm --privileged multiarch/qemu-user-static --credential yes --persistent yes docker build --no-cache --build-arg CHIP=${{ matrix.chip }} --tag $imagetag . docker build --file Dockerfile.model --tag $modeltag . diff --git a/.github/workflows/opencv-qr-decoder-python.yml b/.github/workflows/opencv-qr-decoder-python.yml index 740394e..4b3db05 100644 --- a/.github/workflows/opencv-qr-decoder-python.yml +++ b/.github/workflows/opencv-qr-decoder-python.yml @@ -25,4 +25,5 @@ jobs: imagetag: ${{ env.EXREPO }}_${{ env.EXNAME }}:1.0 run: | cd $EXNAME + docker run --rm --privileged multiarch/qemu-user-static --credential yes --persistent yes docker build --no-cache --tag $imagetag . diff --git a/.github/workflows/parameter-api-python.yml b/.github/workflows/parameter-api-python.yml index 8c3729d..2ff7b8d 100644 --- a/.github/workflows/parameter-api-python.yml +++ b/.github/workflows/parameter-api-python.yml @@ -25,4 +25,5 @@ jobs: imagetag: ${{ env.EXREPO }}_${{ env.EXNAME }}:1.0 run: | cd $EXNAME + docker run --rm --privileged multiarch/qemu-user-static --credential yes --persistent yes docker build --no-cache --tag $imagetag . diff --git a/README.md b/README.md index 880155f..f36045f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,23 @@ [![CI](https://github.com/AxisCommunications/acap-computer-vision-sdk-examples/actions/workflows/ci.yml/badge.svg)](https://github.com/AxisCommunications/acap-computer-vision-sdk-examples/actions/workflows/ci.yml) +> [!IMPORTANT] +> The ACAP Computer Vision solution is deprecated from AXIS OS 12.0. +> +> - The deprecation of the ACAP Computer Vision solution only affects container applications. +> It will still be possible to build and run analytics, computer vision and machine learning applications on Axis devices using +> ACAP Native SDK. Examples can be found in the +> [ACAP Native SDK examples](https://github.com/AxisCommunications/acap-native-sdk-examples) repository. +> For more context about this transition, please visit the [Enhanced ACAP SDK news article](https://www.axis.com/developer-community/news/enhanced-acap-sdk). +> - `armv7hf` is no longer supported after AXIS OS 11.11. +> - `aarch64` will be supported until the end of the AXIS OS 12 LTS cycle. +> After this period, the components of the Computer Vision solution will no longer +> receive updates or support. +> - From AXIS OS 12.0, the artifact ACAP Computer Vision SDK in form of a +> container image is removed and utility libraries and scripts have been +> moved to [ACAP Runtime](https://github.com/AxisCommunications/acap-runtime). +> This means that the ACAP Computer Vision SDK is no longer needed to run container applications. + ## Mission Our mission is to provide an excellent development experience by enabling developers @@ -32,7 +49,7 @@ developers analytics experience. All examples are using Docker framework and has README file in its directory which shows overview, example directory structure and step-by-step instructions on how to run applications on the camera. -### Requirements +## Requirements ### Supported architectures @@ -40,7 +57,14 @@ The examples support the following architectures: * aarch64 -### Example applications for video analytics +### Required components + +The example applications make use of two special components: + +* [Docker ACAP](https://github.com/AxisCommunications/docker-acap) needs to be installed and running on the Axis device. It's required to deploy and run the example application. +* [ACAP runtime](https://github.com/AxisCommunications/acap-runtime) is used in a few examples to get access to [APIs](https://axiscommunications.github.io/acap-documentation/docs/api/computer-vision-sdk-apis.html). ACAP Runtime is a container image and the example applications will pull it from Docker Hub when starting. + +## Example applications Below is a list of examples available in the repository: @@ -60,12 +84,6 @@ Below is a list of examples available in the repository: * [web-server](./web-server/) * A C++ example which runs a Monkey web server on the camera. -### Docker Hub images - -The examples are based on the [ACAP Computer Vision SDK](https://github.com/AxisCommunications/acap-computer-vision-sdk). -This SDK is an image which contains APIs and tooling to build computer vision apps for running on camera, with support for Python. -Additionally, there is the [ACAP Native SDK](https://github.com/AxisCommunications/acap-native-sdk), which is more geared towards building ACAPs that uses AXIS-developed APIs directly, and primarily does so using C/C++. - ## How to work with Github repository You can help to make this repo a better one using the following commands. diff --git a/hello-world-python/Dockerfile b/hello-world-python/Dockerfile index 0cc8463..2ddb9a7 100644 --- a/hello-world-python/Dockerfile +++ b/hello-world-python/Dockerfile @@ -1,17 +1,15 @@ # syntax=docker/dockerfile:1 -ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 - - -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64 AS cv-sdk +ARG UBUNTU_VERSION=24.04 FROM arm64v8/ubuntu:${UBUNTU_VERSION} -# Get the Python package from the CV SDK -COPY --from=cv-sdk /axis/python / +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get update && apt-get install -y --no-install-recommends \ + python3 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/app -WORKDIR /app -COPY app/* /app +COPY app/* . CMD ["python3", "simply_hello.py"] diff --git a/hello-world-python/README.md b/hello-world-python/README.md index 7875bb9..89d09b4 100755 --- a/hello-world-python/README.md +++ b/hello-world-python/README.md @@ -2,9 +2,9 @@ # A minimal Python application -This example demonstrates how to create a simple Python application using the ACAP Computer Vision SDK and run it on an edge device. +This example demonstrates how to create a simple containerized Python application and run it on an edge device. -Going from zero to a Python application running on an AXIS device is quite easy. First, the application script is written, as in the hello-world script in [app/simply_hello.py](app/simply_hello.py). Next, the [Dockerfile](Dockerfile) which builds the application image is constructed. This needs to pull in packages from the ACAP Computer Vision SDK, as is done using the `COPY` commands. Finally, the application needs to be built and uploaded, as is specified below. +Going from zero to a Python application running on an Axis device is quite easy. First, the application script is written, as in the hello-world script in [app/simply_hello.py](app/simply_hello.py). Next, the [Dockerfile](Dockerfile) which builds the application image is constructed. The application needs to be built and uploaded, as is specified below. ## Example structure diff --git a/minimal-ml-inference/Dockerfile b/minimal-ml-inference/Dockerfile index 1b9c539..7760e06 100644 --- a/minimal-ml-inference/Dockerfile +++ b/minimal-ml-inference/Dockerfile @@ -1,24 +1,40 @@ # syntax=docker/dockerfile:1 +ARG RUNTIME_VERSION=2.0.0 ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 +ARG IMAGE=acap-runtime +ARG UBUNTU_VERSION=24.04 -# Specify which ACAP Computer Vision SDK to use -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64 AS cv-sdk +FROM ${REPO}/${IMAGE}:${RUNTIME_VERSION}-protofiles AS proto-image +FROM arm64v8/ubuntu:${UBUNTU_VERSION} AS runtime-image -# Define the runtime image -FROM arm64v8/ubuntu:${UBUNTU_VERSION} +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get update && apt-get install -y --no-install-recommends \ + python3 \ + python3-pip \ + python3-venv \ + ffmpeg \ + libsm6 \ + libxext6 \ + && rm -rf /var/lib/apt/lists/* -# Get packages from the CV SDK -COPY --from=cv-sdk /axis/python / -COPY --from=cv-sdk /axis/python-tfserving / -COPY --from=cv-sdk /axis/python-vdoproto / -COPY --from=cv-sdk /axis/python-numpy / -COPY --from=cv-sdk /axis/opencv / -COPY --from=cv-sdk /axis/openblas / +# Copy list of grpc dependencies +COPY --from=proto-image /build/requirements.txt . + +# Create a virtual environment for installations using pip +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +RUN pip install --no-cache-dir -r requirements.txt \ + numpy \ + opencv-python + +WORKDIR /opt/app + +# Install prebuilt TensorFlow and VDO proto files +COPY --from=proto-image /build/tf/proto_utils . +COPY --from=proto-image /build/vdo/proto_utils . # Copy the application script to the container -WORKDIR /app -COPY simple_inference.py . +COPY app/* . + CMD ["python3", "simple_inference.py"] diff --git a/minimal-ml-inference/Dockerfile.model b/minimal-ml-inference/Dockerfile.model index a14cf97..d0380a3 100644 --- a/minimal-ml-inference/Dockerfile.model +++ b/minimal-ml-inference/Dockerfile.model @@ -4,7 +4,6 @@ ARG UBUNTU_VERSION=22.04 FROM arm64v8/alpine as model-image - # Get SSD Mobilenet V2 ADD https://github.com/google-coral/edgetpu/raw/master/test_data/ssd_mobilenet_v2_coco_quant_postprocess.tflite models/ ADD https://github.com/google-coral/edgetpu/raw/master/test_data/coco_labels.txt models/ diff --git a/minimal-ml-inference/README.md b/minimal-ml-inference/README.md index 233e467..427b338 100755 --- a/minimal-ml-inference/README.md +++ b/minimal-ml-inference/README.md @@ -2,7 +2,7 @@ # A minimal, machine learning inference application -This example demonstrates how to create a simple Python application that performs inference on the camera image. This is done using the ACAP Computer Vision SDK. +This example demonstrates how to create a simple Python application that performs inference on the camera image. ## Overview @@ -14,7 +14,7 @@ Lastly, there is a third container that holds the deep learning model, which is ```text model -├── ssdlite-mobilenet-v2 - tflite model +├── ssdlite-mobilenet-v2 - TFLite model └── objects.txt - list of object labels ``` diff --git a/minimal-ml-inference/simple_inference.py b/minimal-ml-inference/app/simple_inference.py similarity index 100% rename from minimal-ml-inference/simple_inference.py rename to minimal-ml-inference/app/simple_inference.py diff --git a/minimal-ml-inference/config/env.aarch64.artpec8 b/minimal-ml-inference/config/env.aarch64.artpec8 index fcc563f..6e028d6 100644 --- a/minimal-ml-inference/config/env.aarch64.artpec8 +++ b/minimal-ml-inference/config/env.aarch64.artpec8 @@ -1,3 +1,3 @@ MODEL_PATH=/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized -INFERENCE_CHIP=12 \ No newline at end of file +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized +INFERENCE_CHIP=12 diff --git a/minimal-ml-inference/config/env.aarch64.cpu b/minimal-ml-inference/config/env.aarch64.cpu index ffcf77b..dce40e4 100644 --- a/minimal-ml-inference/config/env.aarch64.cpu +++ b/minimal-ml-inference/config/env.aarch64.cpu @@ -1,3 +1,3 @@ MODEL_PATH=/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized -INFERENCE_CHIP=2 \ No newline at end of file +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized +INFERENCE_CHIP=2 diff --git a/object-detector-python/Dockerfile b/object-detector-python/Dockerfile index a24de0d..613312d 100644 --- a/object-detector-python/Dockerfile +++ b/object-detector-python/Dockerfile @@ -1,20 +1,40 @@ # syntax=docker/dockerfile:1 +ARG RUNTIME_VERSION=2.0.0 ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 +ARG IMAGE=acap-runtime +ARG UBUNTU_VERSION=24.04 +FROM ${REPO}/${IMAGE}:${RUNTIME_VERSION}-protofiles AS proto-image +FROM arm64v8/ubuntu:${UBUNTU_VERSION} AS runtime-image -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64 AS cv-sdk -FROM arm64v8/ubuntu:${UBUNTU_VERSION} +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get update && apt-get install -y --no-install-recommends \ + python3 \ + python3-pip \ + python3-venv \ + ffmpeg \ + libsm6 \ + libxext6 \ + && rm -rf /var/lib/apt/lists/* -COPY --from=cv-sdk /axis/python / -COPY --from=cv-sdk /axis/python-numpy / -COPY --from=cv-sdk /axis/python-tfserving / -COPY --from=cv-sdk /axis/python-vdoproto / -COPY --from=cv-sdk /axis/opencv / -COPY --from=cv-sdk /axis/openblas / +# Copy list of grpc dependencies +COPY --from=proto-image /build/requirements.txt . + +# Create a virtual environment for installations using pip +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +RUN pip install --no-cache-dir -r requirements.txt \ + numpy \ + opencv-python + +WORKDIR /opt/app + +# Install prebuilt TensorFlow and VDO proto files +COPY --from=proto-image /build/tf/proto_utils . +COPY --from=proto-image /build/vdo/proto_utils . + +# Copy the application script to the container +COPY app/* . -WORKDIR /app -COPY app/* /app/ CMD ["python3", "detector.py"] diff --git a/object-detector-python/config/env.aarch64.artpec8 b/object-detector-python/config/env.aarch64.artpec8 index ffa0871..6e028d6 100644 --- a/object-detector-python/config/env.aarch64.artpec8 +++ b/object-detector-python/config/env.aarch64.artpec8 @@ -1,3 +1,3 @@ MODEL_PATH=/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized INFERENCE_CHIP=12 diff --git a/object-detector-python/config/env.aarch64.cpu b/object-detector-python/config/env.aarch64.cpu index 6773cf7..dce40e4 100644 --- a/object-detector-python/config/env.aarch64.cpu +++ b/object-detector-python/config/env.aarch64.cpu @@ -1,3 +1,3 @@ MODEL_PATH=/models/ssd_mobilenet_v2_coco_quant_postprocess.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized INFERENCE_CHIP=2 diff --git a/opencv-qr-decoder-python/Dockerfile b/opencv-qr-decoder-python/Dockerfile index 06846c1..b2d7ecb 100644 --- a/opencv-qr-decoder-python/Dockerfile +++ b/opencv-qr-decoder-python/Dockerfile @@ -1,19 +1,39 @@ # syntax=docker/dockerfile:1 +ARG RUNTIME_VERSION=2.0.0 ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 +ARG IMAGE=acap-runtime +ARG UBUNTU_VERSION=24.04 +FROM ${REPO}/${IMAGE}:${RUNTIME_VERSION}-protofiles AS proto-image +FROM arm64v8/ubuntu:${UBUNTU_VERSION} AS runtime-image -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64-runtime AS cv-sdk -FROM arm64v8/ubuntu:${UBUNTU_VERSION} -COPY --from=cv-sdk /axis/opencv / -COPY --from=cv-sdk /axis/openblas / -COPY --from=cv-sdk /axis/python-tfserving / -COPY --from=cv-sdk /axis/python-vdoproto / -COPY --from=cv-sdk /axis/python / -COPY --from=cv-sdk /axis/python-numpy / +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get update && apt-get install -y --no-install-recommends \ + python3 \ + python3-pip \ + python3-venv \ + ffmpeg \ + libsm6 \ + libxext6 \ + && rm -rf /var/lib/apt/lists/* + +# Copy list of grpc dependencies +COPY --from=proto-image /build/requirements.txt . + +# Create a virtual environment for installations using pip +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +RUN pip install --no-cache-dir -r requirements.txt \ + numpy \ + opencv-python + +WORKDIR /opt/app + +# Install prebuilt VDO proto files +COPY --from=proto-image /build/vdo/proto_utils . + +# Copy the application script to the container +COPY app/* . -WORKDIR /app -COPY app/qr.py . CMD ["python3", "qr.py"] diff --git a/opencv-qr-decoder-python/README.md b/opencv-qr-decoder-python/README.md index 1be9447..9c1f44e 100644 --- a/opencv-qr-decoder-python/README.md +++ b/opencv-qr-decoder-python/README.md @@ -8,7 +8,6 @@ It composes two different container images into an application that performs an The first container contains the actual program built in this example. It then uses [gRPC](https://grpc.io/)/[protobuf](https://developers.google.com/protocol-buffers) to call the second container, that is used to capture images from the camera. NumPy is used to preprocess the images and OpenCV to detect and decode any QR codes within the image. -Additionally, Python, NumPy and OpenBLAS are also copied from the Computer Vision SDK. ## Application layout diff --git a/opencv-qr-decoder-python/docker-compose.yml b/opencv-qr-decoder-python/docker-compose.yml index 9f7e356..aa4bc4a 100644 --- a/opencv-qr-decoder-python/docker-compose.yml +++ b/opencv-qr-decoder-python/docker-compose.yml @@ -13,7 +13,7 @@ services: volumes: - inference-server:/tmp inference-server: - image: axisecp/acap-runtime:1.3.1-aarch64-containerized + image: axisecp/acap-runtime:2.0.0-aarch64-containerized logging: driver: "json-file" options: diff --git a/parameter-api-python/Dockerfile b/parameter-api-python/Dockerfile index 9f63774..516c965 100644 --- a/parameter-api-python/Dockerfile +++ b/parameter-api-python/Dockerfile @@ -1,47 +1,38 @@ # syntax=docker/dockerfile:1 +ARG RUNTIME_VERSION=2.0.0 ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 +ARG IMAGE=acap-runtime +ARG UBUNTU_VERSION=24.04 +FROM ${REPO}/${IMAGE}:${RUNTIME_VERSION}-protofiles AS proto-image +FROM arm64v8/ubuntu:${UBUNTU_VERSION} AS runtime-image -# Specify which ACAP Computer Vision SDK version to use -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64 AS cv-sdk - -RUN <` is the password to the `root` user. - -Finally install the Docker image to the device: - -Navigate to the application page of the Axis device `http:///index.html#apps` -and enable `Allow unsigned apps` toggle. This will allow the installation of unsigned -applications. Use the following command to proceed with the application installation. +The built image needs to be uploaded to the device. This can be done through a registry or directly. In this case, the direct transfer is used by piping the compressed application directly to the device's Docker client: ```sh docker save $APP_NAME | docker --tlsverify --host tcp://$DEVICE_IP:$DOCKER_PORT load ``` +> [!NOTE] +> If the *acap-runtime* ([containerized ACAP Runtime](https://github.com/AxisCommunications/acap-runtime)) is not already present on the device, it will be pulled from Docker Hub +> when running `docker compose up`. +> If the pull action fails due to network connectivity, pull the image to your host system and load it to +> the device instead. + ### Run the container With the application image on the device, it can be started using `docker-compose.yml`: @@ -126,12 +88,10 @@ With the application image on the device, it can be started using `docker-compos ```sh docker --tlsverify --host tcp://$DEVICE_IP:$DOCKER_PORT compose up -# Cleanup +# Terminate with Ctrl-C and cleanup docker --tlsverify --host tcp://$DEVICE_IP:$DOCKER_PORT compose down --volumes ``` -where `ca.pem`, `cert.pem` and `key.pem` are the certificates generated when configuring TLS on Docker ACAP. - ### The expected output ```text @@ -140,7 +100,6 @@ parameter-api-python-parameter-api-1 | root.Brand.WebURL : http://www.axis.com parameter-api-python-parameter-api-1 | root.Image.I0.Enabled : yes parameter-api-python-parameter-api-1 | root.Brand.ProdFullName : AXIS Q1615 Mk III Network Camera parameter-api-python-parameter-api-1 | root.Brand.ProdNbr : Q1615 Mk III -parameter-api-python-parameter-api-1 | root.invalid : ``` ## License diff --git a/parameter-api-python/app/apis/keyvaluestore.proto b/parameter-api-python/app/apis/keyvaluestore.proto deleted file mode 100644 index d86f230..0000000 --- a/parameter-api-python/app/apis/keyvaluestore.proto +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (C) 2022 Axis Communications AB, Lund, Sweden - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; - -package keyvaluestore; - -// A simple key-value storage service -service KeyValueStore { - // Provides a value for each key request - rpc GetValues (Request) returns (Response) {} -} - -// The request message containing the key -message Request { - string key = 1; -} - -// The response message containing the value associated with the key -message Response { - string value = 1; -} diff --git a/parameter-api-python/app/src/parameter.py b/parameter-api-python/app/parameter.py similarity index 82% rename from parameter-api-python/app/src/parameter.py rename to parameter-api-python/app/parameter.py index 784e629..ef6abe4 100644 --- a/parameter-api-python/app/src/parameter.py +++ b/parameter-api-python/app/parameter.py @@ -34,7 +34,12 @@ def main(): # gRPC secure connection root_cert = open(sys.argv[1], 'rb').read() ssl_creds = grpc.ssl_channel_credentials(root_cert) - channel = grpc.secure_channel(target, ssl_creds) + + # Set the default authority to 'localhost' for secure connections + # This tells gRPC to use 'localhost' as the authority for the connection, + # which should match the server's certificate. + options = (('grpc.default_authority', 'localhost'),) + channel = grpc.secure_channel(target, ssl_creds, options=options) else: # gRPC insecure connection channel = grpc.insecure_channel(target) @@ -46,8 +51,7 @@ def main(): "root.Brand.WebURL", "root.Image.I0.Enabled", "root.Brand.ProdFullName", - "root.Brand.ProdNbr", - "root.invalid"] + "root.Brand.ProdNbr"] for param_name in param_names: try: diff --git a/parameter-api-python/docker-compose.yml b/parameter-api-python/docker-compose.yml index 04434d9..f159f87 100644 --- a/parameter-api-python/docker-compose.yml +++ b/parameter-api-python/docker-compose.yml @@ -1,8 +1,34 @@ -version: '3.3' - +version: "3.3" services: parameter-api: image: ${APP_NAME} - entrypoint: python3 parameter.py /certificates/server.pem volumes: - - /tmp:/tmp + - acap-runtime:/tmp + - parameter-api:/opt/certificates + + acap-runtime: + image: axisecp/acap-runtime:2.0.0-aarch64-containerized + logging: + driver: "json-file" + options: + max-file: "5" + max-size: "100k" + entrypoint: + [ + "/opt/app/acap_runtime/acapruntime", + "-k", + "/opt/app/certificates/server.key", + "-c", + "/opt/app/certificates/server.pem", + ] + volumes: + - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket + - /run/confcache/confcachesocket:/run/confcache/confcachesocket + - /usr/lib:/usr/lib + - /usr/bin:/usr/bin + - acap-runtime:/tmp + - parameter-api:/opt/app/certificates + +volumes: + parameter-api: {} + acap-runtime: {} diff --git a/pose-estimator-with-flask/Dockerfile b/pose-estimator-with-flask/Dockerfile index d6896d2..6d65b16 100644 --- a/pose-estimator-with-flask/Dockerfile +++ b/pose-estimator-with-flask/Dockerfile @@ -1,22 +1,40 @@ # syntax=docker/dockerfile:1 +ARG RUNTIME_VERSION=2.0.0 ARG REPO=axisecp -ARG SDK_VERSION=1.15 -ARG UBUNTU_VERSION=22.04 +ARG IMAGE=acap-runtime +ARG UBUNTU_VERSION=24.04 +FROM ${REPO}/${IMAGE}:${RUNTIME_VERSION}-protofiles AS proto-image +FROM arm64v8/ubuntu:${UBUNTU_VERSION} AS runtime-image -FROM ${REPO}/acap-computer-vision-sdk:${SDK_VERSION}-aarch64 AS cv-sdk -FROM arm64v8/ubuntu:${UBUNTU_VERSION} +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get update && apt-get install -y --no-install-recommends \ + python3 \ + python3-pip \ + python3-venv \ + ffmpeg \ + libsm6 \ + libxext6 \ + && rm -rf /var/lib/apt/lists/* -COPY --from=cv-sdk /axis/python / -COPY --from=cv-sdk /axis/python-numpy / -COPY --from=cv-sdk /axis/python-tfserving / -COPY --from=cv-sdk /axis/python-vdoproto / -COPY --from=cv-sdk /axis/opencv / -COPY --from=cv-sdk /axis/openblas / +# Copy list of grpc dependencies +COPY --from=proto-image /build/requirements.txt . -RUN pip install Flask +# Create a virtual environment for installations using pip +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +RUN pip install --no-cache-dir -r requirements.txt \ + numpy \ + opencv-python \ + Flask + +WORKDIR /opt/app + +# Install prebuilt TensorFlow and VDO proto files +COPY --from=proto-image /build/tf/proto_utils . +COPY --from=proto-image /build/vdo/proto_utils . + +COPY app/ . -WORKDIR /app -COPY app/ /app/ CMD ["python3", "detector_with_flask.py"] diff --git a/pose-estimator-with-flask/Dockerfile.model b/pose-estimator-with-flask/Dockerfile.model index f1e376e..d922f5d 100644 --- a/pose-estimator-with-flask/Dockerfile.model +++ b/pose-estimator-with-flask/Dockerfile.model @@ -1,6 +1,5 @@ # syntax=docker/dockerfile:1 - FROM arm64v8/alpine # Get SSD Mobilenet V2 diff --git a/pose-estimator-with-flask/config/env.aarch64.artpec8 b/pose-estimator-with-flask/config/env.aarch64.artpec8 index 77c2190..bcb8703 100644 --- a/pose-estimator-with-flask/config/env.aarch64.artpec8 +++ b/pose-estimator-with-flask/config/env.aarch64.artpec8 @@ -1,3 +1,3 @@ MODEL_PATH=/models/movenet_single_pose_lightning_ptq.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized INFERENCE_CHIP=12 diff --git a/pose-estimator-with-flask/config/env.aarch64.cpu b/pose-estimator-with-flask/config/env.aarch64.cpu index 231e652..f0740f8 100644 --- a/pose-estimator-with-flask/config/env.aarch64.cpu +++ b/pose-estimator-with-flask/config/env.aarch64.cpu @@ -1,3 +1,3 @@ MODEL_PATH=/models/movenet_single_pose_lightning_ptq.tflite -INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:1.3.1-aarch64-containerized +INFERENCE_SERVER_IMAGE=axisecp/acap-runtime:2.0.0-aarch64-containerized INFERENCE_CHIP=2 diff --git a/web-server/Dockerfile b/web-server/Dockerfile index 78c4606..bd3c230 100644 --- a/web-server/Dockerfile +++ b/web-server/Dockerfile @@ -1,10 +1,9 @@ # syntax=docker/dockerfile:1 -ARG UBUNTU_VERSION=22.04 +ARG UBUNTU_VERSION=24.04 FROM arm64v8/ubuntu:${UBUNTU_VERSION} as runtime-image - # Setup environment variables ENV DEBIAN_FRONTEND=noninteractive ENV BUILD_ROOT=/build-root diff --git a/web-server/README.md b/web-server/README.md index a8fa754..fb93fd6 100644 --- a/web-server/README.md +++ b/web-server/README.md @@ -2,7 +2,7 @@ # How to use web server in ACAP version 4 -This document explains briefly how to build and use the [Monkey web server](https://github.com/monkey/monkey) in ACAP version 4. Monkey is a fast and lightweight web server for Linux. It has been designed to be very scalable with low memory and CPU consumption, the perfect solution for Embedded Linux and high-end production environments. Besides the common features as HTTP server, it expose a flexible C API which aims to behave as a fully HTTP development framework, so it can be extended as desired through the plugins interface. The Monkey web server [documentation](http://monkey-project.com/documentation/1.5) describes the configuration in detail. +This document explains briefly how to build and use the [Monkey web server](https://github.com/monkey/monkey) in ACAP version 4. Monkey is a fast and lightweight web server for Linux. It has been designed to be very scalable with low memory and CPU consumption, the perfect solution for Embedded Linux and high-end production environments. Besides the common features as HTTP server, it expose a flexible C API which aims to behave as a fully HTTP development framework, so it can be extended as desired through the plugins interface. ## Structure of this application @@ -27,31 +27,14 @@ Meet the following requirements to ensure compatibility with the example: * Either [Docker Desktop](https://docs.docker.com/desktop/) version 4.11.1 or higher, * or [Docker Engine](https://docs.docker.com/engine/) version 20.10.17 or higher with BuildKit enabled using Docker Compose version 1.29.2 or higher -## Limitations +## Limitation -* Apache Reverse Proxy can not translate content with absolute addresses (e.g. `/image.png`) in the HTML page. Use only relative content (e.g. `image.png` or `../image.png`). More information how to handle relative URLs correctly with a reverse proxy [here](https://serverfault.com/questions/561892/how-to-handle-relative-urls-correctly-with-a-reverse-proxy). - -## Configure Apache to forward HTTP requests - -The Axis camera's web server can be accessed from a web browser either directly using a port number (e.g. ) or through the Apache server in the camera using a route (e.g. ). To configure the Apache server as a reverse proxy server, use the procedure shown below. - -```sh -# Do ssh login to the camera -ssh root@ - -# Add reverse proxy configuration to the Apache server, example: -cat >> /etc/apache2/httpd.conf < or . +Start by building the Docker image containing the web server code with examples. This will compile the code to an executable and create a container containing the executable, which can be uploaded to and run on the camera. After the web server is started it can be accessed from a web browser by navigating to http://:2001. ### Build the Docker image @@ -123,11 +106,11 @@ Home : http://monkey-project.com [+] Linux Features: TCP_FASTOPEN SO_REUSEPORT ``` -With the Monkey web server running, navigate to to see the served web page. If you managed to configure the Apache reverse proxy, the same page is also served at . +With the Monkey web server running, navigate to http://:2001 to see the served web page. ## C API Examples -Some C API examples are included in the web server container that has been built: `hello`, `list` and `quiz`. The current Docker image, starts the Monkey server `monkey` when using `CMD monkey` in the Dockerfile. To try another C API example, either re-build the Docker image with another `CMD` (i.e. `CMD hello`) or override it by using the `entrypoint` keyword in the `docker-compose.yml` file (i.e. `entrypoint: hello`). To see the result, use a web browser and navigate to or . +Some C API examples are included in the web server container that has been built: `hello`, `list` and `quiz`. The current Docker image, starts the Monkey server `monkey` when using `CMD monkey` in the Dockerfile. To try another C API example, either re-build the Docker image with another `CMD` (i.e. `CMD hello`) or override it by using the `entrypoint` keyword in the `docker-compose.yml` file (i.e. `entrypoint: hello`). To see the result, use a web browser and navigate to http://:2001. ## Proxy settings