You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have searched the Supervision issues and found no similar feature requests.
Question
I'm trying to make a backend on the basis of Yolov8 and supervision.
I want to make threads within which I can process everything.
I took the Thread-Safe Example from the Yolo documentation as a basis.
Added my own logic, etc.
I encountered the following problem:
If I implement the code in such a way that I strictly specify the zones, everything works. Objects are detected, counted in zones, everything is displayed correctly. This works, but the zones are the same for all threads.
I'm trying to change the processing so that each thread works with its own zones. For example, on the first stream there can be two zones, and on the second - eight, etc.
As a result, I receive images from streams, but there are no zones on them, no object boundaries and nothing is displayed. There is only a counter in the upper left corner, but it always shows zero and is not completely visible.
Tell me, please, what could be the problem?
I am attaching the code, it works in everything except what is described above.
I tried to remove everything that was not needed, leaving only the key functions.
Thank you
from ultralytics import YOLO
from threading import Thread
import cv2
import numpy as np
import supervision as sv
import time
class ObjectTrackerThread(Thread):
def __init__(self, rtsp_url, frame_resolution_wh, output_file, zones):
super(ObjectTrackerThread, self).__init__()
# polygons = np.array([
# [[0, 0], [0.4, 0], [0.4, 1], [0, 1]],
# [[0.6, 0], [1, 0], [1, 1], [0.6, 1]]
# ])
# self.polygons = (polygons * np.array(frame_resolution_wh)).astype(int)
# self.zones = [sv.PolygonZone(polygon=polygon, frame_resolution_wh=frame_resolution_wh) for polygon in self.polygons]
self.zones = zones
self.model = YOLO("yolov8n.pt") # Updated model file
self.model.predict(source="0", show=False, stream=True, conf=0.9)
self.tracker = sv.ByteTrack()
self.colors = sv.ColorPalette.default()
self.box_annotator = sv.BoundingBoxAnnotator()
self.rtsp_url = rtsp_url
self.label_annotator = sv.LabelAnnotator(text_scale=2.0, text_thickness=4)
self.zone_annotators = [sv.PolygonZoneAnnotator(zone=zone, color=self.colors.by_idx(index), thickness=6, text_thickness=8, text_scale=4) for index, zone in enumerate(self.zones)]
self.box_annotators = [sv.BoxAnnotator(color=self.colors.by_idx(index), thickness=4, text_thickness=4, text_scale=2) for index in range(len(self.zones))]
self.trace_annotator = sv.TraceAnnotator(
color=self.colors, position=sv.Position.CENTER, trace_length=100, thickness=2
)
self.enter_times = {index: {} for index in range(len(self.zones))}
self.last_write_times = [time.time() for _ in range(len(self.zones))]
self.frame_resolution_wh = frame_resolution_wh
self.output_file = output_file
fourcc = cv2.VideoWriter_fourcc(*"XVID")
self.video_writer = cv2.VideoWriter(output_file, fourcc, 20.0, frame_resolution_wh)
def format_time(self, seconds):
hours, remainder = divmod(seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02}"
def run(self):
cap = cv2.VideoCapture(self.rtsp_url)
try:
if not cap.isOpened():
print(f"Error: Could not open RTSP stream {self.rtsp_url}")
return
while True:
ret, frame = cap.read()
if not ret:
print("Error: Failed to capture frame")
break
# Print frame shape for debugging
print(f"Thread {self.name} - Frame shape:", frame.shape)
processed_frame = self.process_frame(frame)
self.video_writer.write(processed_frame)
finally:
cap.release()
self.video_writer.release()
def process_frame(self, frame):
results = self.model(frame)[0]
print(results)
detections = sv.Detections.from_ultralytics(results)
detections = self.tracker.update_with_detections(detections)
annotated_frame = frame.copy()
for index, zone in enumerate(self.zones):
zone_value = zone.current_count
current_time = time.time()
if current_time - self.last_write_times[index] >= 10:
pass
mask = zone.trigger(detections=detections)
detections_filtered = detections[mask]
# Debugging information
print(f"Thread {self.name} - Zone {index} - Number of detections: {len(detections_filtered)}")
annotated_frame = self.zone_annotators[index].annotate(annotated_frame)
if len(detections_filtered) > 0:
labels = []
for class_id, tracker_id in zip(detections_filtered.class_id, detections_filtered.tracker_id):
if tracker_id not in self.enter_times[index]:
self.enter_times[index][tracker_id] = time.time()
entry_time = self.enter_times[index][tracker_id]
current_time = time.time()
time_difference = current_time - entry_time
formatted_time = self.format_time(time_difference)
labels.append(f"#{tracker_id} - {formatted_time}")
annotated_frame = self.box_annotators[index].annotate(annotated_frame, detections=detections_filtered, skip_label=True)
annotated_frame = self.label_annotator.annotate(annotated_frame, detections=detections_filtered, labels=labels)
annotated_frame = self.trace_annotator.annotate(annotated_frame, detections)
return annotated_frame
# Define frame_resolution_wh
frame_resolution_wh = (2560, 1440)
zones_thread_1 = [
sv.PolygonZone(polygon=np.array([[0, 0], [0.3, 0], [0.3, 1], [0, 1]], dtype=np.int32), frame_resolution_wh=frame_resolution_wh),
]
# Starting threads that each have their own model instance and process RTSP streams
ObjectTrackerThread("rtsp://]", frame_resolution_wh, "output_thread_1.avi", zones_thread_1).start()
This discussion was converted from issue #616 on April 01, 2024 07:40.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Search before asking
Question
I'm trying to make a backend on the basis of Yolov8 and supervision.
I want to make threads within which I can process everything.
I took the Thread-Safe Example from the Yolo documentation as a basis.
Added my own logic, etc.
I encountered the following problem:
If I implement the code in such a way that I strictly specify the zones, everything works. Objects are detected, counted in zones, everything is displayed correctly. This works, but the zones are the same for all threads.
I'm trying to change the processing so that each thread works with its own zones. For example, on the first stream there can be two zones, and on the second - eight, etc.
All I change is this.
As a result, I receive images from streams, but there are no zones on them, no object boundaries and nothing is displayed. There is only a counter in the upper left corner, but it always shows zero and is not completely visible.
Tell me, please, what could be the problem?
I am attaching the code, it works in everything except what is described above.
I tried to remove everything that was not needed, leaving only the key functions.
Thank you
Additional
No response
Beta Was this translation helpful? Give feedback.
All reactions