supervision: line counter is not working anymore?

Search before asking

  • I have searched the Supervision issues and found no similar feature requests.

Question

this is my code I wanted to add multiple lines and count the objects, but the line counter is not working anymore with the latest supervision.

import os
import torch
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]="0"
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
import numpy as np
import json
from ultralytics import YOLO
import supervision as sv
# from supervision.tools.line_counter import LineCounter
# from supervision.geometry.dataclasses import Point


# LINE_START = Point(50, 1500)
# LINE_END = Point(3790, 1500)

# line_counter = LineCounter(start=LINE_START, end=LINE_END)

model = YOLO('yolov8n.pt')

def main_func(input_data,frame):

    global model

    if 'ignore' in input_data:
        return "ignore"
    else:

        input_data = json.loads(input_data)

        results= model.track(frame, imgsz=640, classes=0,tracker="bytetrack.yaml")[0]
        detections = sv.Detections.from_yolov8(results)

        if results.boxes.id is not None:
            detections.tracker_id = results.boxes.id.cpu().numpy().astype(int)
            detections.conf = results.boxes.conf.cpu().numpy().astype(float)
            detections.xyxy = results.boxes.xyxy.cpu().numpy().astype(int)
            
            # print(detections.tracker_id)
            # print(detections.conf)
            # print(detections.xyxy)
        else:
            detections.tracker_id = np.array([])
            detections.conf = np.array([])
            detections.xyxy = np.array([])
 
        new_box=detections.xyxy
        new_box = new_box.astype("int").tolist()
        new_ids = detections.tracker_id.astype("int").tolist()
        new_confs = detections.conf.astype("float").tolist()    



        print("count",count)

        output = {
                  'frame_index':input_data['frame_index'],
                  'time_stamp':input_data['time_stamp'],
                  'detections':new_box,
                  'demo_run':input_data['demo_run'],
                  'ids':new_ids,
                  'confs':new_confs
                  }
        
        print(output)
        return output

except for the polygon , how to have multiple lines and update the counts?

Additional

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 23 (1 by maintainers)

Most upvoted comments

Closing the issue.

@uzumakinaruto19 As for your in-zone time counter. Here is a sketch of the python logic that you will need.

# dictionary that stores information when given detection starts to be in the zone
in_zone_state: Dict[int, int] = {}

# loop over frames
for frame_index, frame in ...:

    # trigger your zone with detections
    in_zone = polygon_zone.trigger(detections)
    # filter detections to get only those in the zone
    detections_in_zone = detections[in_zone]
    
    # tracker ids that were in the zone in the current frame
    curr_in_zone = set(detections_in_zone.tracker_id)
    # tracker ids that were in the zone in the previous frame
    prev_in_zone = set(in_zone_state.keys())
    # tracker ids that just entered the zone
    new = curr_in_zone.difference(prev_in_zone)
    # tracker ids that just left the zone
    old = prev_in_zone.difference(curr_in_zone)

    # adding new tracker ids to in_zone_state with current frame_index
    for tracker_id in new:
        in_zone_state[tracker_id] = frame_index

    # removing old tracker ids from in_zone_state and calculating how long it was in zone
    for tracker_id in old:
        in_zone_frame_count = frame_index - in_zone_state[tracker_id]
        in_zone_time = in_zone_frame_count * 1 / VIDEO_FPS
        del in_zone_state[tracker_id]

Maybe you put the line in the wrong position. The logic is that if all the bounding boxes cross the line, the count will increase. In your case, you should either turn the camera to a higher position or detect the shoes and count if those shoes cross the line or you could take a look at #107 with the @maddust issue by choose the point at bottom center of the bounding box for counting.

This actually worked in my case with @maddust suggestion, thanks a ton !! @SkalskiP and @sceddd

when using the polygon zone I’m getting this error, it’s running for some seconds and throwing this error

result[:, [0, 2]] = result[:, [0, 2]].clip(0, width)
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

And is it possible to get how much time an object spends in that zone alone?

Thanks in advance

Maybe you put the line in the wrong position. The logic is that if all the bounding boxes cross the line, the count will increase. In your case, you should either turn the camera to a higher position or detect the shoes and count if those shoes cross the line or you could take a look at #107 with the @maddust issue by choose the point at bottom center of the bounding box for counting.

Hi, @uzumakinaruto19 👋🏻

I’m not sure you can use YOLOv8 ByteTrack this way. Here is a snippet of code I used in the past, and it worked. Important note supervision API may differ a bit. It is pretty old code, but the YOLOv8 tracking part worked 100%.

import cv2

from ultralytics import YOLO
import supervision as sv
import numpy as np


LINE_START = sv.Point(320, 0)
LINE_END = sv.Point(320, 480)


def main():
    line_counter = sv.LineZone(start=LINE_START, end=LINE_END)
    line_annotator = sv.LineZoneAnnotator(thickness=2, text_thickness=1, text_scale=0.5)
    box_annotator = sv.BoxAnnotator(
        thickness=2,
        text_thickness=1,
        text_scale=0.5
    )

    model = YOLO("yolov8l.pt")
    for result in model.track(source=0, show=True, stream=True, agnostic_nms=True):
        
        frame = result.orig_img
        detections = sv.Detections.from_yolov8(result)

        if result.boxes.id is not None:
            detections.tracker_id = result.boxes.id.cpu().numpy().astype(int)
        
        detections = detections[(detections.class_id != 60) & (detections.class_id != 0)]

        labels = [
            f"{tracker_id} {model.model.names[class_id]} {confidence:0.2f}"
            for _, confidence, class_id, tracker_id
            in detections
        ]

        frame = box_annotator.annotate(
            scene=frame, 
            detections=detections,
            labels=labels
        )

        line_counter.trigger(detections=detections)
        line_annotator.annotate(frame=frame, line_counter=line_counter)

        cv2.imshow("yolov8", frame)

        if (cv2.waitKey(30) == 27):
            break


if __name__ == "__main__":
    main()

@uzumakinaruto19 did you use trigger() yet? I don’t see it in your code.