Skip to content

Reference for ultralytics/solutions/object_counter.py

Note

This file is available at https://github.com/ultralytics/ultralytics/blob/main/ultralytics/solutions/object_counter.py. If you spot a problem please help fix it by contributing a Pull Request 🛠️. Thank you 🙏!


ultralytics.solutions.object_counter.ObjectCounter

ObjectCounter(**kwargs)

Bases: BaseSolution

A class to manage the counting of objects in a real-time video stream based on their tracks.

Source code in ultralytics/solutions/object_counter.py
def __init__(self, **kwargs):
    """Initialization function for Count class, a child class of BaseSolution class, can be used for counting the
    objects.
    """
    super().__init__(**kwargs)

    self.in_count = 0  # Counter for objects moving inward
    self.out_count = 0  # Counter for objects moving outward
    self.counted_ids = []  # List of IDs of objects that have been counted
    self.classwise_counts = {}  # Dictionary for counts, categorized by object class
    self.region_initialized = False  # Bool variable for region initialization

    self.show_in = self.CFG["show_in"]
    self.show_out = self.CFG["show_out"]

count

count(im0)

Processes input data (frames or object tracks) and updates counts.

Parameters:

Name Type Description Default
im0 ndarray

The input image that will be used for processing

required

Returns im0 (ndarray): The processed image for more usage

Source code in ultralytics/solutions/object_counter.py
def count(self, im0):
    """
    Processes input data (frames or object tracks) and updates counts.

    Args:
        im0 (ndarray): The input image that will be used for processing
    Returns
        im0 (ndarray): The processed image for more usage
    """
    if not self.region_initialized:
        self.initialize_region()
        self.region_initialized = True

    self.annotator = Annotator(im0, line_width=self.line_width)  # Initialize annotator
    self.extract_tracks(im0)  # Extract tracks

    self.annotator.draw_region(
        reg_pts=self.region, color=(104, 0, 123), thickness=self.line_width * 2
    )  # Draw region

    # Iterate over bounding boxes, track ids and classes index
    for box, track_id, cls in zip(self.boxes, self.track_ids, self.clss):
        # Draw bounding box and counting region
        self.annotator.box_label(box, label=self.names[cls], color=colors(track_id, True))
        self.store_tracking_history(track_id, box)  # Store track history
        self.store_classwise_counts(cls)  # store classwise counts in dict

        # Draw tracks of objects
        self.annotator.draw_centroid_and_tracks(
            self.track_line, color=colors(int(track_id), True), track_thickness=self.line_width
        )

        # store previous position of track for object counting
        prev_position = self.track_history[track_id][-2] if len(self.track_history[track_id]) > 1 else None
        self.count_objects(self.track_line, box, track_id, prev_position, cls)  # Perform object counting

    self.display_counts(im0)  # Display the counts on the frame
    self.display_output(im0)  # display output with base class function

    return im0  # return output image for more usage

count_objects

count_objects(track_line, box, track_id, prev_position, cls)

Helper function to count objects within a polygonal region.

Parameters:

Name Type Description Default
track_line dict

last 30 frame track record

required
box list

Bounding box data for specific track in current frame

required
track_id int

track ID of the object

required
prev_position tuple

last frame position coordinates of the track

required
cls int

Class index for classwise count updates

required
Source code in ultralytics/solutions/object_counter.py
def count_objects(self, track_line, box, track_id, prev_position, cls):
    """
    Helper function to count objects within a polygonal region.

    Args:
        track_line (dict): last 30 frame track record
        box (list): Bounding box data for specific track in current frame
        track_id (int): track ID of the object
        prev_position (tuple): last frame position coordinates of the track
        cls (int): Class index for classwise count updates
    """
    if prev_position is None or track_id in self.counted_ids:
        return

    centroid = self.r_s.centroid
    dx = (box[0] - prev_position[0]) * (centroid.x - prev_position[0])
    dy = (box[1] - prev_position[1]) * (centroid.y - prev_position[1])

    if len(self.region) >= 3 and self.r_s.contains(Point(track_line[-1])):
        self.counted_ids.append(track_id)
        # For polygon region
        if dx > 0:
            self.in_count += 1
            self.classwise_counts[self.names[cls]]["IN"] += 1
        else:
            self.out_count += 1
            self.classwise_counts[self.names[cls]]["OUT"] += 1

    elif len(self.region) < 3 and LineString([prev_position, box[:2]]).intersects(self.l_s):
        self.counted_ids.append(track_id)
        # For linear region
        if dx > 0 and dy > 0:
            self.in_count += 1
            self.classwise_counts[self.names[cls]]["IN"] += 1
        else:
            self.out_count += 1
            self.classwise_counts[self.names[cls]]["OUT"] += 1

display_counts

display_counts(im0)

Helper function to display object counts on the frame.

Parameters:

Name Type Description Default
im0 ndarray

The input image or frame

required
Source code in ultralytics/solutions/object_counter.py
def display_counts(self, im0):
    """
    Helper function to display object counts on the frame.

    Args:
        im0 (ndarray): The input image or frame
    """
    labels_dict = {
        str.capitalize(key): f"{'IN ' + str(value['IN']) if self.show_in else ''} "
        f"{'OUT ' + str(value['OUT']) if self.show_out else ''}".strip()
        for key, value in self.classwise_counts.items()
        if value["IN"] != 0 or value["OUT"] != 0
    }

    if labels_dict:
        self.annotator.display_analytics(im0, labels_dict, (104, 31, 17), (255, 255, 255), 10)

store_classwise_counts

store_classwise_counts(cls)

Initialize class-wise counts if not already present.

Parameters:

Name Type Description Default
cls int

Class index for classwise count updates

required
Source code in ultralytics/solutions/object_counter.py
def store_classwise_counts(self, cls):
    """
    Initialize class-wise counts if not already present.

    Args:
        cls (int): Class index for classwise count updates
    """
    if self.names[cls] not in self.classwise_counts:
        self.classwise_counts[self.names[cls]] = {"IN": 0, "OUT": 0}




📅 Created 10 months ago ✏️ Updated 1 month ago