From 6968c1e9f0726b4c14d59a61c24745d77ee8f0b4 Mon Sep 17 00:00:00 2001 From: maxsitt <87697856+maxsitt@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:09:41 +0100 Subject: [PATCH] Add SDK examples Add installation instructions and example scripts to use the DepthAI SDK. --- sdk/README.md | 91 +++++++++++++++++++ .../requirements_sdk.txt | 26 ++++-- sdk/sdk_cam_preview.py | 27 ++++++ sdk/sdk_video_capture.py | 81 +++++++++++++++++ sdk/sdk_yolo_preview.py | 50 ++++++++++ sdk/sdk_yolo_tracker_preview.py | 61 +++++++++++++ 6 files changed, 328 insertions(+), 8 deletions(-) create mode 100644 sdk/README.md rename requirements_sdk.txt => sdk/requirements_sdk.txt (52%) create mode 100644 sdk/sdk_cam_preview.py create mode 100644 sdk/sdk_video_capture.py create mode 100644 sdk/sdk_yolo_preview.py create mode 100644 sdk/sdk_yolo_tracker_preview.py diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 0000000..99fbe55 --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,91 @@ +# Insect Detect - DIY camera trap for automated insect monitoring + + + +[![DOI](https://zenodo.org/badge/580886977.svg)](https://zenodo.org/badge/latestdoi/580886977) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://choosealicense.com/licenses/gpl-3.0/) + +# DepthAI SDK + +The [DepthAI SDK](https://docs.luxonis.com/projects/sdk/en/latest/) is built on top +of the [DepthAI Python API](https://docs.luxonis.com/projects/api/en/latest/) and +contains classes and functions that can make the development of common tasks easier. + +DepthAI SDK is in alpha stage until depthai-sdk 2.0. + +--- + +## Installation + +Please make sure that you followed [all steps](https://maxsitt.github.io/insect-detect-docs/software/pisetup/) +to set up your Raspberry Pi before using the OAK-1 camera. + +Install the required dependencies for Raspberry Pi + OAK by running: + +``` +sudo curl -fL https://docs.luxonis.com/install_dependencies.sh | bash +``` + +Install the python3-venv package: + +``` +sudo apt-get install python3-venv +``` + +Create a virtual environment to avoid dependency and version conflicts of the installed packages: + +``` +python3 -m venv env_sdk +``` + +Activate the virtual environment: + +``` +source env_sdk/bin/activate +``` + +Update pip: + +``` +python3 -m pip install --upgrade pip +``` + +Install the required packages by running: + +``` +python3 -m pip install -r insect-detect/sdk/requirements_sdk.txt +``` + +After installing these packages, install the depthai-sdk with: + +``` +python3 -m pip install --no-dependencies depthai-sdk==1.13.1 +``` + +You can now test the example SDK scripts, e.g. by running: + +``` +python3 insect-detect/sdk/sdk_cam_preview.py +``` + +If you want to deactivate the virtual environment, run: + +``` +deactivate +``` + +--- + +## License + +All Python scripts are licensed under the GNU General Public License v3.0 +([GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/)). + +## Citation + +You can cite this repository as: + +``` +Sittinger, M. (2023). Insect Detect - Software for automated insect monitoring +with a DIY camera trap system (v1.6). Zenodo. https://doi.org/10.5281/zenodo.7472238 +``` diff --git a/requirements_sdk.txt b/sdk/requirements_sdk.txt similarity index 52% rename from requirements_sdk.txt rename to sdk/requirements_sdk.txt index ee5fc1e..7b8bb00 100644 --- a/requirements_sdk.txt +++ b/sdk/requirements_sdk.txt @@ -8,15 +8,25 @@ # If you are using Raspberry Pi Zero W (v1.1), install libusb-1.0 with: # sudo apt-get install libusb-1.0-0-dev -# Install packages with: -# python3 -m pip install -r requirements_sdk.txt +# Install the required packages with: +# python3 -m pip install -r insect-detect/sdk/requirements_sdk.txt -# After installing these packages, install the depthai-sdk with: -# python3 -m pip install --no-dependencies depthai-sdk==1.11.0 +# After installing these packages, install the depthai-sdk package with: +# python3 -m pip install --no-dependencies depthai-sdk==1.13.1 --r requirements.txt +depthai==2.23.0.0 depthai-pipeline-graph==0.0.5 -PyTurboJPEG==1.6.4 -marshmallow==3.17.0 +opencv-python==4.6.0.66 +numpy==1.25.2 +psutil==5.9.6 +av==10.0.0 +PyTurboJPEG==1.7.2 +marshmallow==3.20.1 xmltodict==0.13.0 -requests==2.26.0 \ No newline at end of file +Qt.py==1.3.7 +types-pyside2==5.15.2.1.6 +PyYAML==6.0.1 +jmespath==1.0.1 +six==1.16.0 +requests==2.31.0 +AHRS==0.3.1 \ No newline at end of file diff --git a/sdk/sdk_cam_preview.py b/sdk/sdk_cam_preview.py new file mode 100644 index 0000000..8ca2534 --- /dev/null +++ b/sdk/sdk_cam_preview.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +''' +Author: Maximilian Sittinger (https://github.com/maxsitt) +Website: https://maxsitt.github.io/insect-detect-docs/ +License: GNU GPLv3 (https://choosealicense.com/licenses/gpl-3.0/) + +This Python script does the following: +- show downscaled frames + fps in a new window (e.g. via X11 forwarding) + -> "isp_scale=(1, 4)" will downscale 1920x1080 px to 480x270 px + +based on open source scripts available at https://github.com/luxonis/depthai/tree/main/depthai_sdk +''' + +from depthai_sdk import OakCamera + +with OakCamera(usb_speed="usb2") as oak: +#with OakCamera(usb_speed="usb2", rotation=180) as oak: + cam_rgb = oak.camera("RGB", resolution="1080p", fps=8) + cam_rgb.config_color_camera(isp_scale=(1, 4), interleaved=False, color_order="BGR") + + visualizer = oak.visualize(cam_rgb.out.main, fps=True) + + oak.start(blocking=False) + + while oak.running(): + oak.poll() diff --git a/sdk/sdk_video_capture.py b/sdk/sdk_video_capture.py new file mode 100644 index 0000000..a2f7bb3 --- /dev/null +++ b/sdk/sdk_video_capture.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +''' +Author: Maximilian Sittinger (https://github.com/maxsitt) +Website: https://maxsitt.github.io/insect-detect-docs/ +License: GNU GPLv3 (https://choosealicense.com/licenses/gpl-3.0/) + +This Python script does the following: +- save encoded HQ frames (1080p or 4K resolution) with H.265 (HEVC) compression to .mp4 video file +- optional arguments: + "-minutes [min]" (default = 2) set recording time in minutes + -> e.g. "-minutes 5" for 5 min recording time + "-4k" (default = 1080p) record video in 4K resolution (3840x2160 px) + "-fps [fps]" (default = 25) set frame rate (frames per second) for video capture + -> e.g. "-fps 20" to decrease video file size + +based on open source scripts available at https://github.com/luxonis/depthai/tree/main/depthai_sdk +''' + +import argparse +import time +from datetime import datetime +from pathlib import Path + +import psutil +from depthai_sdk import OakCamera, RecordType + +# Define optional arguments +parser = argparse.ArgumentParser() +parser.add_argument("-minutes", "--min_rec_time", type=int, choices=range(1, 61), default=2, + help="set record time in minutes") +parser.add_argument("-4k", "--four_k_resolution", action="store_true", + help="record video in 4K resolution (3840x2160 px); default = 1080p") +parser.add_argument("-fps", "--frames_per_second", type=int, choices=range(1, 31), default=25, + help="set frame rate (frames per second) for video capture") +args = parser.parse_args() + +# Get recording time in min from optional argument (default: 2) +rec_time = args.min_rec_time * 60 +print(f"\nRecording time: {args.min_rec_time} min\n") + +# Get frame rate (frames per second) from optional argument (default: 25) +FPS = args.frames_per_second + +# Set video resolution +if args.four_k_resolution: + RES = "4K" +else: + RES = "1080p" + +# Create folder to save the videos +rec_start = datetime.now().strftime("%Y%m%d_%H-%M-%S") +save_path = f"insect-detect/sdk/videos/{rec_start}" +Path(f"{save_path}").mkdir(parents=True, exist_ok=True) + +# Get free disk space (MB) +disk_free = round(psutil.disk_usage("/").free / 1048576) + +# Create start_time variable to set recording time +start_time = time.monotonic() + +with OakCamera(usb_speed="usb2") as oak: +#with OakCamera(usb_speed="usb2", rotation=180) as oak: + cam_rgb = oak.camera("RGB", resolution=RES, fps=FPS, encode="H265") + + oak.record(cam_rgb.out.encoded, save_path, RecordType.VIDEO) + + oak.start(blocking=False) + + while oak.running(): + if time.monotonic() - start_time > rec_time or disk_free < 200: + break + + # Update free disk space (MB) + disk_free = round(psutil.disk_usage("/").free / 1048576) + + oak.poll() + +# Print duration, resolution, fps and path of saved video + free disk space to console +print(f"\nSaved {args.min_rec_time} min {RES} video with {FPS} fps to {save_path}.") +print(f"\nFree disk space left: {disk_free} MB") diff --git a/sdk/sdk_yolo_preview.py b/sdk/sdk_yolo_preview.py new file mode 100644 index 0000000..619de3d --- /dev/null +++ b/sdk/sdk_yolo_preview.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +''' +Author: Maximilian Sittinger (https://github.com/maxsitt) +Website: https://maxsitt.github.io/insect-detect-docs/ +License: GNU GPLv3 (https://choosealicense.com/licenses/gpl-3.0/) + +This Python script does the following: +- run a custom YOLO object detection model (.blob format) on-device (Luxonis OAK) + -> inference on downscaled LQ frames (e.g. 320x320 px) +- show downscaled frames + model output (bounding box, label, confidence) + fps + in a new window (e.g. via X11 forwarding) + -> "isp_scale=(1, 4)" will downscale 1920x1080 px to 480x270 px + +based on open source scripts available at https://github.com/luxonis/depthai/tree/main/depthai_sdk +''' + +from depthai_sdk import OakCamera +from depthai_sdk.visualize.configs import BboxStyle + +with OakCamera(usb_speed="usb2") as oak: +#with OakCamera(usb_speed="usb2", rotation=180) as oak: + cam_rgb = oak.camera("RGB", resolution="1080p", fps=8) + cam_rgb.config_color_camera(isp_scale=(1, 4), interleaved=False, color_order="BGR") + + nn = oak.create_nn("/home/pi/insect-detect/models/json/yolov5_v7_320.json", input=cam_rgb) # YOLOv5n + #nn = oak.create_nn("/home/pi/insect-detect/models/json/yolov6_v8_320.json", input=cam_rgb) # YOLOv6n + nn.config_nn(resize_mode="stretch", conf_threshold=0.5) + + # Control auto focus and auto exposure with detections (bbox area) + #cam_rgb.control_with_nn(nn, auto_focus=True, auto_exposure=True, debug=False) + + visualizer = oak.visualize(nn.out.main, fps=True) # downscaled frames (480x270 px) + #visualizer = oak.visualize(nn.out.passthrough, fps=True) # downscaled + stretched frame (320x320 px) + visualizer.detections( + bbox_style=BboxStyle.ROUNDED_CORNERS, + #bbox_style=BboxStyle.RECTANGLE, + fill_transparency=0 + ).text( + font_face=0, + font_color=(255, 255, 255), + font_thickness=1, + font_scale=0.5, + auto_scale=False + ) + + oak.start(blocking=False) + + while oak.running(): + oak.poll() diff --git a/sdk/sdk_yolo_tracker_preview.py b/sdk/sdk_yolo_tracker_preview.py new file mode 100644 index 0000000..3b4aa5c --- /dev/null +++ b/sdk/sdk_yolo_tracker_preview.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +''' +Author: Maximilian Sittinger (https://github.com/maxsitt) +Website: https://maxsitt.github.io/insect-detect-docs/ +License: GNU GPLv3 (https://choosealicense.com/licenses/gpl-3.0/) + +This Python script does the following: +- run a custom YOLO object detection model (.blob format) on-device (Luxonis OAK) + -> inference on downscaled LQ frames (e.g. 320x320 px) +- use an object tracker to track detected objects and assign unique tracking IDs (on-device) +- show downscaled frames + model/tracker output (bounding box, label, confidence, + tracklet trail) + fps in a new window (e.g. via X11 forwarding) + -> "isp_scale=(1, 4)" will downscale 1920x1080 px to 480x270 px + +based on open source scripts available at https://github.com/luxonis/depthai/tree/main/depthai_sdk +''' + +import depthai as dai +from depthai_sdk import OakCamera +from depthai_sdk.visualize.configs import BboxStyle + +with OakCamera(usb_speed="usb2") as oak: +#with OakCamera(usb_speed="usb2", rotation=180) as oak: + cam_rgb = oak.camera("RGB", resolution="1080p", fps=8) + cam_rgb.config_color_camera(isp_scale=(1, 4), interleaved=False, color_order="BGR") + + nn = oak.create_nn("/home/pi/insect-detect/models/json/yolov5_v7_320.json", input=cam_rgb, tracker=True) # YOLOv5n + #nn = oak.create_nn("/home/pi/insect-detect/models/json/yolov6_v8_320.json", input=cam_rgb, tracker=True) # YOLOv6n + nn.config_nn(resize_mode="stretch", conf_threshold=0.5) + + nn.config_tracker( + tracker_type=dai.TrackerType.ZERO_TERM_IMAGELESS, + #tracker_type=dai.TrackerType.SHORT_TERM_IMAGELESS, # better for low fps + assignment_policy=dai.TrackerIdAssignmentPolicy.UNIQUE_ID, + threshold=0.1 + ) + + # Control auto focus and auto exposure with detections (bbox area) + #cam_rgb.control_with_nn(nn, auto_focus=True, auto_exposure=True, debug=False) + + visualizer = oak.visualize(nn.out.tracker, fps=True) # downscaled frames (480x270 px) + visualizer.detections( + bbox_style=BboxStyle.ROUNDED_CORNERS, + #bbox_style=BboxStyle.RECTANGLE, + fill_transparency=0 + ).text( + font_face=0, + font_color=(255, 255, 255), + font_thickness=1, + font_scale=0.5, + auto_scale=False + ).tracking( + max_length=300, # tracklet trail length + line_thickness=1 # tracklet trail thickness + ) + + oak.start(blocking=False) + + while oak.running(): + oak.poll()