Skip to content

Line Zone

LineZone

This class is responsible for counting the number of objects that cross a predefined line.

Warning

LineZone utilizes the tracker_id. Read here to learn how to plug tracking into your inference pipeline.

Attributes:

Name Type Description
in_count int

The number of objects that have crossed the line from outside to inside.

out_count int

The number of objects that have crossed the line from inside to outside.

Source code in supervision/detection/line_counter.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class LineZone:
    """
    This class is responsible for counting the number of objects that cross a
    predefined line.

    !!! warning

        LineZone utilizes the `tracker_id`. Read
        [here](https://supervision.roboflow.com/trackers/) to learn how to plug
        tracking into your inference pipeline.

    Attributes:
        in_count (int): The number of objects that have crossed the line from outside
            to inside.
        out_count (int): The number of objects that have crossed the line from inside
            to outside.
    """

    def __init__(self, start: Point, end: Point):
        """
        Args:
            start (Point): The starting point of the line.
            end (Point): The ending point of the line.
        """
        self.vector = Vector(start=start, end=end)
        self.tracker_state: Dict[str, bool] = {}
        self.in_count: int = 0
        self.out_count: int = 0

    def trigger(self, detections: Detections) -> Tuple[np.ndarray, np.ndarray]:
        """
        Update the `in_count` and `out_count` based on the objects that cross the line.

        Args:
            detections (Detections): A list of detections for which to update the
                counts.

        Returns:
            A tuple of two boolean NumPy arrays. The first array indicates which
                detections have crossed the line from outside to inside. The second
                array indicates which detections have crossed the line from inside to
                outside.
        """
        crossed_in = np.full(len(detections), False)
        crossed_out = np.full(len(detections), False)

        for i, (xyxy, _, confidence, class_id, tracker_id) in enumerate(detections):
            if tracker_id is None:
                continue

            x1, y1, x2, y2 = xyxy
            anchors = [
                Point(x=x1, y=y1),
                Point(x=x1, y=y2),
                Point(x=x2, y=y1),
                Point(x=x2, y=y2),
            ]
            triggers = [self.vector.is_in(point=anchor) for anchor in anchors]

            if len(set(triggers)) == 2:
                continue

            tracker_state = triggers[0]

            if tracker_id not in self.tracker_state:
                self.tracker_state[tracker_id] = tracker_state
                continue

            if self.tracker_state.get(tracker_id) == tracker_state:
                continue

            self.tracker_state[tracker_id] = tracker_state
            if tracker_state:
                self.in_count += 1
                crossed_in[i] = True
            else:
                self.out_count += 1
                crossed_out[i] = True

        return crossed_in, crossed_out

__init__(start, end)

Parameters:

Name Type Description Default
start Point

The starting point of the line.

required
end Point

The ending point of the line.

required
Source code in supervision/detection/line_counter.py
29
30
31
32
33
34
35
36
37
38
def __init__(self, start: Point, end: Point):
    """
    Args:
        start (Point): The starting point of the line.
        end (Point): The ending point of the line.
    """
    self.vector = Vector(start=start, end=end)
    self.tracker_state: Dict[str, bool] = {}
    self.in_count: int = 0
    self.out_count: int = 0

trigger(detections)

Update the in_count and out_count based on the objects that cross the line.

Parameters:

Name Type Description Default
detections Detections

A list of detections for which to update the counts.

required

Returns:

Type Description
Tuple[ndarray, ndarray]

A tuple of two boolean NumPy arrays. The first array indicates which detections have crossed the line from outside to inside. The second array indicates which detections have crossed the line from inside to outside.

Source code in supervision/detection/line_counter.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
def trigger(self, detections: Detections) -> Tuple[np.ndarray, np.ndarray]:
    """
    Update the `in_count` and `out_count` based on the objects that cross the line.

    Args:
        detections (Detections): A list of detections for which to update the
            counts.

    Returns:
        A tuple of two boolean NumPy arrays. The first array indicates which
            detections have crossed the line from outside to inside. The second
            array indicates which detections have crossed the line from inside to
            outside.
    """
    crossed_in = np.full(len(detections), False)
    crossed_out = np.full(len(detections), False)

    for i, (xyxy, _, confidence, class_id, tracker_id) in enumerate(detections):
        if tracker_id is None:
            continue

        x1, y1, x2, y2 = xyxy
        anchors = [
            Point(x=x1, y=y1),
            Point(x=x1, y=y2),
            Point(x=x2, y=y1),
            Point(x=x2, y=y2),
        ]
        triggers = [self.vector.is_in(point=anchor) for anchor in anchors]

        if len(set(triggers)) == 2:
            continue

        tracker_state = triggers[0]

        if tracker_id not in self.tracker_state:
            self.tracker_state[tracker_id] = tracker_state
            continue

        if self.tracker_state.get(tracker_id) == tracker_state:
            continue

        self.tracker_state[tracker_id] = tracker_state
        if tracker_state:
            self.in_count += 1
            crossed_in[i] = True
        else:
            self.out_count += 1
            crossed_out[i] = True

    return crossed_in, crossed_out