Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding example for unix domain events-based integration #50

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0955051
feat(haas): hailo as a service setup, unix domain event based
OriNachum Oct 2, 2024
6a8f9d8
fix(haas): adding testing tool for event mode"
OriNachum Oct 3, 2024
e5988ea
feat(haas): non-blocking loop for event communication test example
OriNachum Oct 3, 2024
21e120d
chore(haas): move unix domain events server to a module in a differen…
OriNachum Oct 3, 2024
c720ebe
chore(haas): update documentation with new events module
OriNachum Oct 3, 2024
8a8ce02
feat(haas): event on changes only
OriNachum Oct 5, 2024
d8c484f
Merge branch 'main' into main
OriNachum Oct 13, 2024
72e6cfa
chore(haas): update example per new template
OriNachum Oct 19, 2024
2a41b54
fix(haas): add missing event location
OriNachum Oct 19, 2024
6afe7a0
fix(haas): collect labels for event
OriNachum Oct 27, 2024
ffdf640
Merge branch 'main' into main
OriNachum Nov 6, 2024
0889efe
Merge branch 'hailo-ai:main' into main
OriNachum Nov 29, 2024
c02857f
feat(unix_domain_socket_server): implement object visibility detectio…
OriNachum Nov 29, 2024
1bffff6
fix(unix_domain_socket_server): add list support for new_data on send…
OriNachum Nov 29, 2024
0c7cbf7
fix(unix_domain_socket_server): accept new_data as a list of strings
OriNachum Nov 29, 2024
e453a62
fix(unix_domain_socket_server): missing tab
OriNachum Nov 29, 2024
97bf572
fix(unix_domain_socket_server): add missing _send_message method
OriNachum Nov 29, 2024
b70ac90
fix(unix_domain_socket_server): revert shutdown and make_serializable…
OriNachum Nov 29, 2024
90ceddc
fix(unix_domain_socket_server): event are not sent on time
OriNachum Nov 29, 2024
149c3e5
fix(unix_domain_socket_cervice): fixed input as list
OriNachum Nov 30, 2024
b154fee
fix(unix_domain_socket_server): refactor send_event method and improv…
OriNachum Nov 30, 2024
dc1642f
fix(unix_domain_socket_server): init last sent visible objects
OriNachum Nov 30, 2024
6e02f33
fix(unix_domain_socket_server): update call to _send_message
OriNachum Nov 30, 2024
04f695c
fix(unix_domain_socket_server): init current_visible_set
OriNachum Dec 1, 2024
8355c2c
fix(unix_domain_socket_server): improve visibility detection and mess…
OriNachum Dec 1, 2024
4897f49
fix(unix_domain_socket_server): simplify send_visible_objects method …
OriNachum Dec 1, 2024
dfd14a6
fix(unix_domain_socket_server): optimize visibility change detection …
OriNachum Dec 1, 2024
db0389d
fix(unix_domain_socket_server): reduce uptime window size for event t…
OriNachum Dec 1, 2024
8705cf2
fix(community): move community project to appropriate folder
OriNachum Dec 24, 2024
eb4e8da
fix(docs): Remove community project documentation
OriNachum Dec 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Visit the [Hailo Official Website](https://hailo.ai/) and [Hailo Community Forum
- [Detection Example](#detection-example)
- [Pose Estimation Example](#pose-estimation-example)
- [Instance Segmentation Example](#instance-segmentation-example)
- [Detection as a service Example](#detection-service-example)
- [CLIP Application](#clip-application)
- [Frigate Integration - Coming Soon](#frigate-integration---coming-soon)
- [Raspberry Pi Official Examples](#raspberry-pi-official-examples)
Expand Down Expand Up @@ -70,6 +71,10 @@ This application includes support for using retrained detection models. For more
##### [Instance Segmentation Example](doc/basic-pipelines.md#instance-segmentation-example)
![Instance Segmentation Example](doc/images/instance_segmentation.gif)

##### [Detection Service Example](doc/basic-pipelines.md#detection-service-example)
![Detection Service Example](doc/images/detection.gif)


#### CLIP Application

CLIP (Contrastive Language-Image Pretraining) predicts the most relevant text prompt on real-time video frames using the Hailo-8L AI processor.
Expand Down
46 changes: 46 additions & 0 deletions community_projects/UnixDomainSocketIntegration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Hailo UnixDomainSocketIntegration example

This exmaple is based on the detection pipeline. It is an example for converting a pipeline to event-based integration.
The demo model is Object detection, but this can be applied to any model.

The server measures 'uptime' of each object, and takes only objects with enough 'uptime' (To ignore flicering due bad detection)

## Installation
Follow the installation flow in the main README file, and then continue following this README file.

### Enable SPI
```bash
sudo raspi-config
```

- 3 Interface Options
- I4 SPI
- Yes
- reboot


### Navigate to the repository directory:
```bash
cd hailo-rpi5-examples
```

### Environment Configuration (Required for Each New Terminal Session)
Ensure your environment is set up correctly by sourcing the provided script. This script sets the required environment variables and activates the Hailo virtual environment. If the virtual environment does not exist, it will be created automatically.
```bash
source setup_env.sh
```
### Navigate to the example directory:
```bash
cd community_projects/UnixDomainSocketIntegration/
```
### Requirements Installation
Within the activated virtual environment, install the necessary Python packages:
```bash
pip install -r requirements.txt
```

### To Run the Simple Example:
```bash
python detection_service.py
```
- To close the application, press `Ctrl+C`.
102 changes: 102 additions & 0 deletions community_projects/UnixDomainSocketIntegration/detection_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
import os
import numpy as np
import cv2
import hailo
import sys

sys.path.append('../../basic_pipelines')

from hailo_rpi_common import (
get_caps_from_pad,
get_numpy_from_buffer,
app_callback_class,
)
from detection_pipeline import GStreamerDetectionApp

from unix_domain_socket_server import UnixDomainSocketServer

# Path for the Unix Domain Socket
SOCKET_PATH = "/tmp/gst_detection.sock"

# -----------------------------------------------------------------------------------------------
# User-defined class to be used in the callback function
# -----------------------------------------------------------------------------------------------
# Inheritance from the app_callback_class
class user_app_callback_class(app_callback_class):
def __init__(self):
super().__init__()
self.new_variable = 42 # New variable example

def new_function(self): # New function example
return "The meaning of life is: "

# -----------------------------------------------------------------------------------------------
# User-defined callback function
# -----------------------------------------------------------------------------------------------

# This is the callback function that will be called when data is available from the pipeline
def app_callback(pad, info, user_data):
# Get the GstBuffer from the probe info
buffer = info.get_buffer()
# Check if the buffer is valid
if buffer is None:
return Gst.PadProbeReturn.OK

# Using the user_data to count the number of frames
user_data.increment()
string_to_print = f"Frame count: {user_data.get_count()}\n"

# Get the caps from the pad
format, width, height = get_caps_from_pad(pad)

# If the user_data.use_frame is set to True, we can get the video frame from the buffer
frame = None
if user_data.use_frame and format is not None and width is not None and height is not None:
# Get video frame
frame = get_numpy_from_buffer(buffer, format, width, height)

# Get the detections from the buffer
roi = hailo.get_roi_from_buffer(buffer)
detections = roi.get_objects_typed(hailo.HAILO_DETECTION)

# Parse the detections
labels = []
detection_count = 0
for detection in detections:
label = detection.get_label()
labels.append(label)
bbox = detection.get_bbox()
confidence = detection.get_confidence()
if label == "person":
string_to_print += f"Detection: {label} {confidence:.2f}\n"
detection_count += 1
if user_data.use_frame:
# Note: using imshow will not work here, as the callback function is not running in the main thread
# Let's print the detection count to the frame
cv2.putText(frame, f"Detections: {detection_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Example of how to use the new_variable and new_function from the user_data
# Let's print the new_variable and the result of the new_function to the frame
cv2.putText(frame, f"{user_data.new_function()} {user_data.new_variable}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Convert the frame to BGR
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
user_data.set_frame(frame)

# Call events server to fire event of a new detection
user_data.socket_server.send_event(labels)

print(string_to_print)
return Gst.PadProbeReturn.OK

if __name__ == "__main__":
# Create an instance of the user app callback class
user_data = user_app_callback_class()

socket_server = UnixDomainSocketServer(SOCKET_PATH)
socket_server.start()
user_data.socket_server = socket_server

app = GStreamerDetectionApp(app_callback, user_data)
app.run()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
numpy<2.0.0
setproctitle
opencv-python
python-dotenv
DeepDiff
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import socket
import os
import time

# Path to the Unix Domain Socket (ensure it matches the server's socket path)
SOCKET_PATH = "/tmp/gst_detection.sock"

def main():
# Create a Unix Domain Socket
client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

try:
# Connect to the server's socket
client_socket.connect(SOCKET_PATH)
print(f"Connected to Unix Domain Socket at {SOCKET_PATH}")

# Set the socket to non-blocking mode
client_socket.setblocking(False)

# Listen for messages from the server
while True:
try:
# Try to receive data without blocking
data = client_socket.recv(1024)
if data:
print(f"Received data: {data.decode('utf-8')}")
else:
print("Server disconnected")
break

except BlockingIOError:
# No data available, continue loop
pass

# You can add a small sleep to prevent busy looping
time.sleep(0.01)

except FileNotFoundError:
print(f"Socket path '{SOCKET_PATH}' does not exist. Please ensure the server is running.")

except ConnectionRefusedError:
print("Could not connect to the server. Please make sure the server is running and accessible.")

except KeyboardInterrupt:
print("Client shut down by user")

finally:
# Close the socket
client_socket.close()

if __name__ == "__main__":
main()
Loading