Skip to content

Line_Zones getting triggered by every single object detected, not just the ones crossing the line #210

@sim0wastaken

Description

@sim0wastaken

Search before asking

  • I have searched the Supervision issues and found no similar bug report.

Bug

Hello everyone,
I have been trying to play around with YoloV8 and Supervision for traffic lanes monitoring

So far, I've been able to successfully implement a polygon zone counting and one single line zone counter of in/out

However, when I tried implementing multiple linezones counters, I found that they get triggered by every single object detected in the frame

In my scenario:

2 ways highways with each way having 4 lanes
I have set up 1 Line for each lane in both directions of the highways
When I run my program, the Lines' counters get updated as if they were triggered by every single car inside the frame

In this screenshot you can see how each line gets triggered by every single object inside the detection area
image

Environment

  • Supervision 0.11.0
  • Windows 11
  • Python 3.10.4
  • RTX3060

Minimal Reproducible Example

I was unable to figure out which part of my code caused the issue

import supervision as sv
import numpy as np

# Person, cats, dogs, vehicles, boats, knives, scissors, street signs
#classes=[0,1,2,3,5,6,7,8,11,14,15,16,24,25,26,28,42,43,44]

if __name__ == "__main__":

    # Load the model
    model = YOLO("yolov8x.pt")
    
    # Open a connection to the webcam
    cap = cv2.VideoCapture('Samples/highway1.mp4')
    
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    
    # Set window dimensions (Only works on my laptop's webcam??)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, frame_width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)
    
    # Area of Interest parameters
    # Polygon for area of detections
    polygon = np.array([
        [0, 390],    # A 
        [1280, 390], # B
        [1280, 720], # C
        [0, 720]     # D
        ])
    
    # TEST LINE
    testline_start = sv.Point(360, 360)
    testline_end = (400, 400)
    testline_zone = sv.LineZone(start=testline_start, end=testline_end)
    testline_annotator = sv.LineZoneAnnotator()
    
    # LEFT SIDE LINES
    # Line 1
    line1_start = sv.Point(69, 490)
    line1_end = sv.Point(200, 490)
    # Line 2
    line2_start = sv.Point(110, 557)
    line2_end = sv.Point(258, 557)
    # Line 3
    line3_start = sv.Point(315, 527)
    line3_end = sv.Point(456, 527)
    
    # RIGHT SIDE LINES
    # Line 4
    line4_start = sv.Point(803, 502)
    line4_end = sv.Point(926, 502)
    # Line 5
    line5_start = sv.Point(1012, 570)
    line5_end = sv.Point(1181, 570)
    # Line 6
    line6_start = sv.Point(1050, 482)
    line6_end =sv.Point(1173, 482)
    
    # Initiate polygon annotators
    Polygon = sv.PolygonZone(polygon=polygon, frame_resolution_wh=[frame_width, frame_height])
    Polygon_Annotator = sv.PolygonZoneAnnotator(zone=Polygon, color=sv.Color.white(), thickness=2, text_thickness=2, text_scale=1)
        
    # Initialize bounding boxes annotator
    Box_Annotator = sv.BoxAnnotator(thickness=2, text_thickness=1, text_scale=0.5)
    
    # Initialize lines annotators
    Line1 = sv.LineZone(start=line1_start, end=line1_end)
    Line1_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)

    Line2 = sv.LineZone(start=line2_start, end=line2_end)
    Line2_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)
    
    Line3 = sv.LineZone(start=line3_start, end=line3_end)
    Line3_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)
    
    Line4 = sv.LineZone(start=line4_start, end=line4_end)
    Line4_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)
    
    Line5 = sv.LineZone(start=line5_start, end=line5_end)
    Line5_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)
    
    Line6 = sv.LineZone(start=line6_start, end=line6_end)
    Line6_Annotator = sv.LineZoneAnnotator(thickness=1, text_thickness=1, text_scale=0.4)
    

    # Define the window name
    window_name = 'Video file'
    
    while True:
        # Read a frame from the video file
        ret, frame = cap.read()

        # If the frame was successfully read
        if ret:
            # Predict
            for result in model.track(frame, device='0', classes=[2, 3, 4, 7, 8], tracker='botsort.yaml', stream=True):

                # Get detections results for Supervision
                detections = sv.Detections.from_yolov8(result)
                
                # Polygon triggers
                mask = Polygon.trigger(detections=detections)
                detections = detections[mask]
                
                # Only get tracker ids if we actually have detections, otherwise will give NoneType error
                if result.boxes.id is not None:
                    detections.tracker_id = result.boxes.id.cpu().numpy().astype(int)
                
                # Get labels to draw on each detected object
                labels = []
                for detection in detections:
                    xyxy, mask, confidence, class_id, tracker_id = detection
                    if class_id is not None and confidence is not None:
                        labels.append(f"#{tracker_id} {model.model.names[class_id]} {confidence:0.2f}")
                
                # Draw the labels    
                frame = Box_Annotator.annotate(frame, detections=detections, labels=labels)
                
                # Draw Polygon
                frame = Polygon_Annotator.annotate(scene=frame)
                
                # Draw the line
                Line1_Annotator.annotate(frame, Line1)
                Line2_Annotator.annotate(frame, Line2)
                Line3_Annotator.annotate(frame, Line3)
                Line4_Annotator.annotate(frame, Line4)
                Line5_Annotator.annotate(frame, Line5)
                Line6_Annotator.annotate(frame, Line6)
                testline_annotator.annotate(frame, testline_zone)
                
                # Line triggers
                Line1.trigger(detections=detections)
                Line2.trigger(detections=detections)
                Line3.trigger(detections=detections)
                Line4.trigger(detections=detections)
                Line5.trigger(detections=detections)
                Line6.trigger(detections=detections)
                testline_zone.trigger(detections=detections)
                
                # Show video    
                cv2.imshow(window_name, frame)

            # If the user presses 'q', or the window is closed, exit the loop
            if cv2.waitKey(1) & 0xFF == ord('q') or cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE) < 1:
                break
        else:
            print("Unable to read frame")
            break

    # Release the webcam and destroy all windows
    cap.release()
    cv2.destroyAllWindows()

Additional

Yes

Are you willing to submit a PR?

  • Yes I'd like to help by submitting a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingduplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions