Ultralytics YOLO27: Join the waitlist.
Get Started

Object Counting using Ultralytics YOLO26#

What is Object Counting?#

Open Object Counting In Colab

Object counting with Ultralytics YOLO26 involves identifying and counting specific objects in videos and camera streams. Because YOLO26 runs deep learning detection and tracking in real time, it suits counting scenarios such as crowd and occupancy analysis and surveillance.



Watch: How to Perform Real-Time Object Counting with Ultralytics YOLO26 🚀

Advantages of Object Counting#

  • Resource Optimization: Object counting facilitates efficient resource management by providing accurate counts, optimizing resource allocation in applications like inventory management.
  • Enhanced Security: Object counting enhances security and surveillance by accurately tracking and counting entities, aiding in proactive threat detection.
  • Informed Decision-Making: Object counting offers valuable insights for decision-making, optimizing processes in retail, traffic management, and various other domains.

Real-World Applications#

LogisticsAquaculture
Conveyor Belt Packets Counting Using Ultralytics YOLO26Fish Counting in Sea using Ultralytics YOLO26
Conveyor Belt Packets Counting Using Ultralytics YOLO26Fish Counting in Sea using Ultralytics YOLO26

Count Objects with YOLO26#

Define a counting region — two points for a line or three or more for a polygon — and pass it to the ObjectCounter solution. The counter tracks each object across frames and tallies IN/OUT counts when tracked objects cross the line or pass through the region, returning an annotated frame you can write to an output video.

Object Counting using Ultralytics YOLO
# Run a counting example
yolo solutions count show=True

# Pass a source video
yolo solutions count source="path/to/video.mp4"

# Pass region coordinates
yolo solutions count region="[(20, 400), (1080, 400), (1080, 360), (20, 360)]"

The region argument accepts either two points (for a line) or a polygon with three or more points. Define the coordinates in the order they should be connected so the counter knows exactly where entries and exits occur.

ObjectCounter Arguments#

Here's a table with the ObjectCounter arguments:

ArgumentTypeDefaultDescription
modelstrNonePath to an Ultralytics YOLO model file.
show_inboolTrueFlag to control whether to display the in counts on the video stream.
show_outboolTrueFlag to control whether to display the out counts on the video stream.
regionlist or dictNonePoints defining the region of interest, either a list of (x, y) tuples or a dictionary mapping region names to point lists for multiple regions (RegionCounter only). When None, solutions that require a region fall back to a predefined default.
line_widthint2Line thickness for the boxes, keypoints and counts the solution draws.
verboseboolTrueEnables the solution's per-frame log of input shape, class counts and processing speed. The tracking call itself is always silent.

The ObjectCounter solution allows the use of several track arguments:

ArgumentTypeDefaultDescription
trackerstr'tracktrack.yaml'Specifies the tracking algorithm to use. Built-in options: botsort.yaml, bytetrack.yaml, ocsort.yaml, deepocsort.yaml, fasttrack.yaml, tracktrack.yaml.
conffloat0.25Sets the confidence threshold for detections; lower values allow more objects to be tracked but may include false positives.
ioufloat0.7Sets the Intersection over Union (IoU) threshold for filtering overlapping detections.
classeslistNoneFilters results by class index. For example, classes=[0, 2, 3] only tracks the specified classes.
devicestrNoneSpecifies the device for inference (e.g., cpu, cuda:0 or 0). Allows users to select between CPU, a specific GPU, or other compute devices for model execution.
imgszint or tuple640Target inference image size: an integer for a square or a (height, width) pair. Shapes are adjusted to the model stride.
max_detint300Maximum number of detections kept per frame before tracking, limiting the objects a solution processes in dense scenes.
quantizeint or strNoneInference precision: 16 (FP16) or 32/unset (FP32) for PyTorch and TorchScript models off CPU; other formats use the precision their artifact and runtime select. Replaces the deprecated half arg.

Additionally, the visualization arguments listed below are supported:

ArgumentTypeDefaultDescription
showboolFalseIf True, displays the annotated images or videos in a window. Useful for immediate visual feedback during development or testing.
show_confboolTrueDisplays the confidence score for each detection alongside the label. Gives insight into the model's certainty for each detection.
show_labelsboolTrueDisplays labels for each detection in the visual output. Provides immediate understanding of detected objects.

FAQ#

  • To count objects in a video using Ultralytics YOLO26, you can follow these steps:

    1. Import the necessary libraries (cv2, ultralytics).
    2. Define the counting region (e.g., a polygon, line, etc.).
    3. Set up the video capture and initialize the object counter.
    4. Process each frame to track objects and count them within the defined region.

    Here's a simple example for counting in a region:

    import cv2
    
    from ultralytics import solutions
    
    def count_objects_in_region(video_path, output_video_path, model_path):
        """Count objects in a specific region within a video."""
        cap = cv2.VideoCapture(video_path)
        assert cap.isOpened(), "Error reading video file"
        w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
        video_writer = cv2.VideoWriter(output_video_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
    
        region_points = [(20, 400), (1080, 400), (1080, 360), (20, 360)]
        counter = solutions.ObjectCounter(show=True, region=region_points, model=model_path)
    
        while cap.isOpened():
            success, im0 = cap.read()
            if not success:
                print("Video frame is empty or processing is complete.")
                break
            results = counter(im0)
            video_writer.write(results.plot_im)
    
        cap.release()
        video_writer.release()
        cv2.destroyAllWindows()
    
    count_objects_in_region("path/to/video.mp4", "output_video.avi", "yolo26n.pt")

    For more advanced configurations and options, check out the RegionCounter solution for counting objects in multiple regions simultaneously.

  • Using Ultralytics YOLO26 for object counting offers several advantages:

    1. Resource Optimization: It facilitates efficient resource management by providing accurate counts, helping optimize resource allocation in industries like inventory management.
    2. Enhanced Security: It enhances security and surveillance by accurately tracking and counting entities, aiding in proactive threat detection and security systems.
    3. Informed Decision-Making: It offers valuable insights for decision-making, optimizing processes in domains like retail, traffic management, and more.
    4. Real-time Processing: YOLO26's architecture enables real-time inference, making it suitable for live video streams and time-sensitive applications.

    For implementation examples and practical applications, explore the TrackZone solution for tracking objects in specific zones.

  • To count specific classes of objects using Ultralytics YOLO26, you need to specify the classes you are interested in during the tracking phase. Below is a Python example:

    import cv2
    
    from ultralytics import solutions
    
    def count_specific_classes(video_path, output_video_path, model_path, classes_to_count):
        """Count specific classes of objects in a video."""
        cap = cv2.VideoCapture(video_path)
        assert cap.isOpened(), "Error reading video file"
        w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
        video_writer = cv2.VideoWriter(output_video_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
    
        line_points = [(20, 400), (1080, 400)]
        counter = solutions.ObjectCounter(show=True, region=line_points, model=model_path, classes=classes_to_count)
    
        while cap.isOpened():
            success, im0 = cap.read()
            if not success:
                print("Video frame is empty or processing is complete.")
                break
            results = counter(im0)
            video_writer.write(results.plot_im)
    
        cap.release()
        video_writer.release()
        cv2.destroyAllWindows()
    
    count_specific_classes("path/to/video.mp4", "output_specific_classes.avi", "yolo26n.pt", [0, 2])

    In this example, classes_to_count=[0, 2] means it counts objects of class 0 and 2 (e.g., person and car in the COCO dataset). You can find more information about class indices in the COCO dataset documentation.

  • Ultralytics YOLO26 provides several advantages over other object detection models like Faster R-CNN, SSD, and previous YOLO versions:

    1. Speed and Efficiency: YOLO26 runs in real time, making it well suited to applications requiring high-speed inference, such as surveillance and autonomous driving.
    2. Accuracy: It provides high detection and tracking accuracy, reducing false positives and improving overall system reliability.
    3. Ease of Integration: YOLO26 exports to many deployment formats for servers, mobile, and edge devices.
    4. Flexibility: Supports detection, segmentation, and OBB models with track mode on top, and configurable models to meet specific use-case requirements.

    Check out Ultralytics YOLO26 Documentation for a deeper dive into its features and performance comparisons.

  • Yes. Ultralytics YOLO26 is well suited to crowd analysis and traffic management because it detects, tracks, and counts objects in real time in dynamic environments. Example use cases include:

    • Crowd Analysis: Monitor and manage large gatherings, ensuring safety and optimizing crowd flow with region-based counting.
    • Traffic Management: Track and count vehicles, analyze traffic patterns, and manage congestion in real time with speed estimation.
    • Retail Analytics: Analyze customer movement patterns and product interactions to optimize store layouts and improve customer experience.
    • Industrial Automation: Count products on conveyor belts and monitor production lines for quality control and efficiency improvements.

Comments879

Ask a question, share your results, or help someone else.

  1. RizwanMunawarRizwanMunawarGitHub

    🎉 Big News Alert! 🚀 Ultralytics Solutions CLI is here from ultralytics>=8.3.28! Now, you can easily harness the power of advanced YOLO solutions straight from the command line. Simplify your workflow, and streamline object detection, tracking, counting, and more—all with just a few commands! Get ready to experience a whole new level of efficiency! 💥

    CLI Usage Overview

    yolo SOLUTIONS SOLUTION_NAME ARGS
    • SOLUTIONS is a mandatory keyword.
    • SOLUTION_NAME (optional): Choose from ['count', 'heatmap', 'queue', 'speed', 'workout', 'analytics'].
    • ARGS (optional): Use custom arg=value pairs, like show_in=True, to customize settings.

    Examples

    yolo solutions count show=True  # For object counting
    
    yolo solutions source="path/to/video/file.mp4"  # Specify a video file path

    Start exploring now and let Ultralytics Solutions CLI power up your projects!

    5
    1. faheem-khaskhelifaheem-khaskheliGitHub

      i have created a line, at 15 degree angle, if a person come down it should count as in, and if a person goes up it count as out.

      • down = in
      • up = out but model does not work like this, model count direction is reversed.

      how can i solve this?

    2. Glenn JocherGlenn JocherUltralytics

      @faheem-khaskheli to resolve the direction issue, ensure the line's orientation is correctly defined in your code. You might need to adjust the logic that determines the direction based on the line's angle. If the model's counting direction is reversed, check the implementation of the ObjectCounter and verify the region or line points are set correctly.

    3. faheem-khaskhelifaheem-khaskheliGitHub

      @glenn-jocher is there any way i can use ultralytics solution for this problem? i have checked the code and it is only checking dx > 0 for in else out.

    4. Glenn JocherGlenn JocherUltralytics

      @faheem-khaskheli to address the reversed counting direction, adjust the logic in your code to correctly interpret the angle of the line. Ensure that the conditions for dx > 0 and dx < 0 align with the intended "in" and "out" directions based on your line's orientation.

  2. BoaruzhanchikBoaruzhanchikGitHub

    Hi,how can I use object counting with 3 lines and 3 different counters ?
    line_points = [(197,164), (486,164)]

    Line pedestrian

    line_pedestrian_1 = [(234,244),(131,218)] line_pedestrian_2 = [(490,245),(534,231)] line_pedestrian_3 = [(112,189),(154,177)] counter = object_counter.ObjectCounter() counter.set_args(view_img=False, reg_pts=line_points, classes_names=model.names, draw_tracks=False, region_thickness = 1) my code ex: im0 = counter.start_counting(frame, results) counter.extract_and_process_tracks(results) counter.in_counts counter.out_counts print(f'In counts:{counter.in_counts}') print(f'Out counts:{counter.out_counts}')

    2
    1. Glenn JocherGlenn JocherUltralytics(edited)

      Hey there! 👋 For multiple lines with separate counts, create one ObjectCounter per line and pass each frame to every counter. Each counter keeps its own in/out counts:

      from ultralytics import solutions
      
      line_pedestrian_1 = [(234, 244), (131, 218)]
      line_pedestrian_2 = [(490, 245), (534, 231)]
      line_pedestrian_3 = [(112, 189), (154, 177)]
      
      counters = [
          solutions.ObjectCounter(region=line, model='yolo26n.pt')
          for line in (line_pedestrian_1, line_pedestrian_2, line_pedestrian_3)
      ]
      
      # For each frame:
      for i, counter in enumerate(counters, 1):
          results = counter(frame)
          print(f'Counter {i} - In: {results.in_count}, Out: {results.out_count}')

      This way, each ObjectCounter will track objects crossing its respective line. Hope this helps! If you have further questions, feel free to ask. Happy coding! 😊

      1
    2. BoaruzhanchikBoaruzhanchikGitHub

      Thank you for your reply! There was a problem with counting the number of custom classes, the docstring says "classes_names (dict): Classes names", I'm trying to use class_cars = { 2.0 : 'car', 5 : 'bus', 7: 'truck' } counter3.set_args(classes_names=class_cars, reg_pts=line_pedestrian_3,region_thickness = 2) but an error occurs Traceback (most recent call last): File "/home/iosif/Documents/Dev/yolo_model/yolov8_train/yolov8_tracking_car_number/tracking_5.py", line 93, in im0 = counter3.start_counting(frame, results) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 259, in start_counting self.extract_and_process_tracks(tracks) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 172, in extract_and_process_tracks self.annotator.box_label(box, label=f"{track_id}:{self.names[cls]}", color=colors(int(cls), True)) KeyError: 0.0 When trying to get a class by index, the following error occurs Traceback (most recent call last): File "/home/iosif/Documents/Dev/yolo_model/yolov8_train/yolov8_tracking_car_number/tracking_5.py", line 87, in im0 = counter1.start_counting(frame, results) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 259, in start_counting self.extract_and_process_tracks(tracks) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 172, in extract_and_process_tracks self.annotator.box_label(box, label=f"{track_id}:{self.names[cls]}", color=colors(int(cls), True)) TypeError: string indices must be integers Question: How can I select the class that I want to count?

    3. Glenn JocherGlenn JocherUltralytics(edited)

      Hi there! 👋 In current versions ObjectCounter no longer takes classes_names or set_args(); class names come from the model, so that KeyError can't occur. To count only specific classes, pass their indices with classes:

      from ultralytics import solutions
      
      counter3 = solutions.ObjectCounter(region=line_pedestrian_3, model='yolo26n.pt', classes=[2, 5, 7], line_width=2)
      results = counter3(im0)
      print(results.classwise_count)  # e.g. {'car': {'IN': 1, 'OUT': 0}}

      This should resolve the errors you're seeing. Let me know if you need any more help! 😊

    4. BoaruzhanchikBoaruzhanchikGitHub

      This will work to limit the total number of detectable classes, but it does not solve the problem of counting in separate areas of a single class (2 areas to count only cars and buses and 2 areas for pedestrians). An example from the code (Now I will describe why it happens) I specified a limited list of classes for tracking and when cls =17 is detected in tracking, the program crashes because this class is not specified in counter.set_args. How can I get around this limitation so that I can specify different classes for counting different areas (as I said in the example 2 only for cars, 2 only for people).

      class_list_common = [0,2,5,7,17]
       all_dict_dict = { 0 : 'person', 2: 'car', 5: 'bus',7: 'truck'}
      counter1.set_args(classes_names=all_dict_dict,reg_pts=line_pedestrian_1,region_thickness = 2,line_dist_thresh=8,draw_tracks=True)
      results = model.track(frame,classes=class_list_common)

      Traceback (most recent call last): File "/home/iosif/Documents/Dev/yolo_model/yolov8_train/yolov8_tracking_car_number/tracking_5.py", line 140, in im0 = counter1.start_counting(frame, results) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 259, in start_counting self.extract_and_process_tracks(tracks) File "/home/iosif/.local/lib/python3.10/site-packages/ultralytics/solutions/object_counter.py", line 172, in extract_and_process_tracks self.annotator.box_label(box, label=f"{track_id}:{self.names[cls]}", color=colors(int(cls), True)) KeyError: 17.0

    5. Glenn JocherGlenn JocherUltralytics(edited)

      Hey there! 👋 To count different classes in separate areas, create multiple ObjectCounter instances, each with its own region and classes list. Class names come from the model automatically, and classwise_count gives the counts per class:

      from ultralytics import solutions
      
      counter_cars_buses = solutions.ObjectCounter(model='yolo26n.pt', region=line_cars_buses, classes=[2, 5])
      counter_pedestrians = solutions.ObjectCounter(model='yolo26n.pt', region=line_pedestrians, classes=[0])
      
      # For each frame:
      im0 = counter_cars_buses(frame).plot_im
      im0 = counter_pedestrians(frame).plot_im

      This way, each counter will only count the classes it's set up for. Happy counting! 😊

    6. syariffortasksyariffortaskGitHub

      hello there, how about if i want my line just for in count not for out count for example i have line_pedestrian_1 = [(0,244),(131,244)] ,if all people touch this line count in will increment, because what I know so far is that the line is divided into 2 parts, one for counting in and one for counting out

    7. Glenn JocherGlenn JocherUltralytics(edited)

      Hi there! 👋 ObjectCounter reports in_count and out_count separately for a line, based on the direction in which tracked objects cross it. If you only need one direction, read just that value and ignore the other:

      from ultralytics import solutions
      
      counter = solutions.ObjectCounter(region=line_pedestrian_1, model='yolo26n.pt')
      results = counter(frame)
      print(results.in_count)  # only objects crossing in the 'in' direction

      Happy coding! 😊

    8. Glenn JocherGlenn JocherUltralytics(edited)

      Hello! Sure, I'd be happy to provide an example for setting up object counting with Ultralytics YOLO. Let's suppose you want to count cars crossing a line. Here's how you could set this up:

      import cv2
      
      from ultralytics import solutions
      
      # Open video file
      cap = cv2.VideoCapture('path/to/your/video.mp4')
      assert cap.isOpened(), 'Error loading video'
      
      # Define the line points for counting
      line_points = [(20, 400), (1080, 400)]  # Adjust these points to fit your line
      
      # Initialize Object Counter; classes=[2] counts only cars in the COCO classes
      counter = solutions.ObjectCounter(model='yolo26n.pt', region=line_points, classes=[2])
      
      # Process video and start counting
      while cap.isOpened():
          ret, frame = cap.read()
          if not ret:
              break  # End of video
      
          # Perform tracking and counting
          results = counter(frame)
      
          # Optionally view the frame with counts
          cv2.imshow('Object Counting', results.plot_im)
          if cv2.waitKey(1) & 0xFF == 27:  # press 'ESC' to exit
              break
      
      # Release resources
      cap.release()
      cv2.destroyAllWindows()

      💡 Important:

      • Adjust line_points to position your counting line in the video frame.
      • Use classes with the model's class indices to count only specific object types.

      Objects crossing the line in one direction increase results.in_count and in the opposite direction results.out_count. For multiple counting areas, create one counter per line or region.

      Hope this helps get you started! Let me know if there's anything else you'd like to explore. 😄

    9. Glenn JocherGlenn JocherUltralytics(edited)

      @syariffortask hey! If your line is not appearing on the frame, there could be a couple of things to check. Make sure show=True is set when initializing your ObjectCounter (or display results.plot_im yourself), and verify that the region points are correctly defined and fall within the frame's dimensions. Here's a quick example:

      from ultralytics import solutions
      
      counter = solutions.ObjectCounter(
          show=True,
          region=[(20, 400), (1080, 400)],  # Make sure these points are within your frame's dimensions
          model='yolo26n.pt',
      )

      Make sure your setup matches your video frame size, and adjust region as necessary. This adjustment should help you visualize the counting line directly on your frames! 😊 Let me know if this does the trick!

    10. syariffortasksyariffortaskGitHub

      glenn tell me how you can do that? are you update class ObjectCounter logic in new version ultralytics?

    11. Glenn JocherGlenn JocherUltralytics(edited)

      Hey! 👋 Thanks for reaching out. Yes, we're constantly working on enhancing the ObjectCounter logic. For counting objects crossing a specific line, here's a quick example based on your requirement:

      import cv2
      
      from ultralytics import solutions
      
      # Set up your video source
      cap = cv2.VideoCapture('path/to/video.mp4')
      
      # Initialize Object Counter for your line
      line_pedestrian_1 = [(0, 244), (131, 244)]  # Define as per your need
      counter = solutions.ObjectCounter(show=True, region=line_pedestrian_1, model='yolo26n.pt', classes=[0])
      
      while cap.isOpened():
          ret, im0 = cap.read()
          if not ret:
              break
      
          # Track objects and count crossings of your line
          results = counter(im0)
      
          # Display
          cv2.imshow('Count', results.plot_im)
          if cv2.waitKey(1) == ord('q'):  # press q to quit
              break
      
      cap.release()
      cv2.destroyAllWindows()

      This sets up an object counting system for pedestrians crossing line_pedestrian_1. ObjectCounter reports results.in_count and results.out_count separately based on the direction of crossing, so you can use only the one you need. Keep up with our GitHub releases for the latest features! 🚀 Let me know if there's anything else I can help with.

    12. syariffortasksyariffortaskGitHub

      Thanks for answer my question, But Can ultralytics predict and count two frame/ two vidio source ?

    13. Glenn JocherGlenn JocherUltralytics(edited)

      @syariffortask hey! Thanks for reaching out with your question. 😊 Yes, YOLO can definitely work with two video sources simultaneously, but it would require running two instances of the video processing loop, each in its own thread or process, due to the way the code execution works.

      Here's a simplified example using Python's threading module to process two videos at the same time:

      from threading import Thread
      
      import cv2
      
      from ultralytics import YOLO
      
      
      def process_video(video_path):
          model = YOLO('yolo26n.pt')
          cap = cv2.VideoCapture(video_path)
          assert cap.isOpened(), 'Error reading video file'
      
          while cap.isOpened():
              success, frame = cap.read()
              if not success:
                  break
              results = model.track(frame, persist=True)
      
              # Here you could use a solutions.ObjectCounter per video
              # For example: im0 = counter(frame).plot_im
              # And then save or display im0
      
          cap.release()
      
      
      # Define your video sources
      video_1 = 'path/to/your/first_video.mp4'
      video_2 = 'path/to/your/second_video.mp4'
      
      # Start processing each video in a separate thread
      Thread(target=process_video, args=(video_1,)).start()
      Thread(target=process_video, args=(video_2,)).start()

      Remember, depending on your system, handling two video streams simultaneously can be resource-intensive. Adjust the frame processing rate if necessary to manage system load. Hope that helps! Let me know if you have more questions. 🚀

  3. phoenix-JMphoenix-JMGitHub

    Hello everyone; i used the following code snippet for trained yolov8n-obb model with five classes;

    import cv2

    from ultralytics import solutions

    cap = cv2.VideoCapture("xie_035.mp4") assert cap.isOpened(), "Error reading video file"

    region_points = [(20, 400), (1080, 400)] # line counting

    region_points = [(20, 400), (1080, 400), (1080, 360), (20, 360)] # rectangle region

    region_points = [(20, 400), (1080, 400), (1080, 360), (20, 360), (20, 400)] # polygon region

    Video writer

    w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS)) video_writer = cv2.VideoWriter("object_counting_output.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))

    Initialize object counter object

    counter = solutions.ObjectCounter( show=True, # display the output region=region_points, # pass region points model="D:/TRACKING_COUNTING/yolov8n-obb_ads.pt", # model="yolo11n-obb.pt" for object counting with OBB model. # classes=[0, 2], # count specific classes i.e. person and car with COCO pretrained model. tracker="bytetrack.yaml", # choose trackers i.e "bytetrack.yaml" )

    Process video

    while cap.isOpened(): success, im0 = cap.read()

    if not success:
        print("Video frame is empty or processing is complete.")
        break
    
    results = counter(im0)
    
    # print(results)  # access the output
    
    video_writer.write(results.plot_im)  # write the processed frame.

    cap.release() video_writer.release() cv2.destroyAllWindows() # destroy all opened windows

    however, it generates HBB not OBB, can someone help please.

    1
    1. Glenn JocherGlenn JocherUltralytics(edited)

      @phoenix-JM thanks for reaching out! ObjectCounter handles OBB models natively, so you can pass an OBB model directly (e.g. model="yolo26n-obb.pt") and no special initialization is needed; please make sure you're using the latest Ultralytics version. If you need the raw OBB coordinates for custom plotting, they are available as counter.boxes after the call (or results.obb.xyxyxyxy when running a model directly). For new projects we recommend the YOLO26-OBB models as shown in our Object Counting documentation. Let us know if you need further guidance! 🚀

    2. RizwanMunawarRizwanMunawarGitHub

      @phoenix-JM Hi, thanks for the question. Indeed, visualization for OBB is not supported yet. you can only plot the HBB. I will work on this feature this week. Thanks

    3. phoenix-JMphoenix-JMGitHub

      Thank you for your reply. @glenn-Jocher can you please provide me the code snippet to do so.

    4. phoenix-JMphoenix-JMGitHub

      @RIzwanMunawar Hello ! is there any update regarding object counting and tracking using OBB. ?

  4. SourceOfNootmiteSourceOfNootmiteGitHub

    Hi ultralytics team! Hope you're doing well. My knowledge of computer vision is quite limited, so apologies for dumb questions. Is it possible to train my own model based off yolov11? I attempted to do so by using a roboflow guide and their example colab notebook. I have access to the weights, one of them saying best.pt. Are weights and models completely different. Can i somehow use that and replace:

    model="yolo11n.pt" with my own model.
    # Init ObjectCounter
    counter = solutions.ObjectCounter(
        show=True,  # Display the output
        region=region_points,  # Pass region points
        model="yolo11n.pt",  # model="yolo11n-obb.pt" for object counting using YOLO11 OBB model.
        # classes=[0, 2],  # If you want to count specific classes i.e person and car with COCO pretrained model.
        # show_in=True,  # Display in counts
        # show_out=True,  # Display out counts
        # line_width=2,  # Adjust the line width for bounding boxes and text display
    )
    1
    1. RizwanMunawarRizwanMunawarGitHub

      @SourceOfNootmite Hi! Yes, you can use any supported model for object counting, including YOLOv10, Ultralytics YOLO11, and Ultralytics YOLOv8. You can also use any model we support. If you have a YOLO11 model trained on your dataset, it will work seamlessly with the Object Counting module.

      However, this feature is not currently supported if you're referring to a completely new model architecture. Thanks!

  5. MartinnemoMartinnemoGitHub

    hi guys.

    Thanks for an awesome job with all of ultralytics!

    I'm having a problem where/ how to implement the conf and model.track in the code above ? Can you help ? :)

    1
    1. MartinnemoMartinnemoGitHub

      I mean, i following code, how do i apply the confidence function:

      import cv2

      from ultralytics import solutions

      cap = cv2.VideoCapture("path/to/video/file.mp4") assert cap.isOpened(), "Error reading video file" w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))

      Define region points

      region_points = [(20, 400), (1080, 400)] # For line counting

      region_points = [(20, 400), (1080, 400), (1080, 360), (20, 360)] # For rectangle region counting

      region_points = [(20, 400), (1080, 400), (1080, 360), (20, 360), (20, 400)] # For polygon region counting

      Video writer

      video_writer = cv2.VideoWriter("object_counting_output.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))

      Init Object Counter

      counter = solutions.ObjectCounter( show=True, # Display the output region=region_points, # Pass region points model="yolo11n.pt", # model="yolo11n-obb.pt" for object counting using YOLO11 OBB model. # classes=[0, 2], # If you want to count specific classes i.e person and car with COCO pretrained model. # show_in=True, # Display in counts # show_out=True, # Display out counts # line_width=2, # Adjust the line width for bounding boxes and text display )

      Process video

      while cap.isOpened(): success, im0 = cap.read() if not success: print("Video frame is empty or video processing has been successfully completed.") break im0 = counter.count(im0) video_writer.write(im0)

      cap.release() video_writer.release() cv2.destroyAllWindows()

    2. Glenn JocherGlenn JocherUltralytics(edited)

      To apply the confidence threshold (conf) to filter detections, you can pass it as a parameter when initializing the ObjectCounter. Here's an example:

      counter = solutions.ObjectCounter(
          show=True,
          region=region_points,
          model="yolo26n.pt",
          conf=0.5  # Adjust the confidence threshold as needed
      )

      This will only count objects with a detection confidence score above the specified threshold (0.5 in this case). Let me know if you need further clarification!

  6. gmantovagmantovaGitHub

    What is the minimal code that I can use to have:

    yolo (defining parameters, if any)

    bytetrack (defining parameters, if any)

    get the coordinates of the boxes and id of the object

    then I'll define a geometric condition, let's say behind a line etc

    1
    1. Glenn JocherGlenn JocherUltralytics(edited)

      @g-i-o-r-g-i-o to achieve object tracking and counting with YOLO and ByteTrack, you can use the following minimal code setup. This will allow you to get the coordinates and IDs of detected objects and apply a geometric condition:

      import cv2
      from ultralytics import YOLO
      
      # Initialize model and video capture
      model = YOLO('yolo26n.pt')
      cap = cv2.VideoCapture('path/to/video.mp4')
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              break
      
          # Run detection and tracking
          results = model.track(frame, persist=True, tracker='bytetrack.yaml')
          
          # Process results
          for r in results:
              for box in r.boxes:
                  x1, y1, x2, y2 = box.xyxy[0].tolist()
                  obj_id = int(box.id) if box.id is not None else None
                  # Apply geometric condition here, e.g., check if behind a line
      
          # Display or save results
          cv2.imshow('Frame', frame)
          if cv2.waitKey(1) & 0xFF == ord('q'):
              break
      
      cap.release()
      cv2.destroyAllWindows()

      For more detailed guidance, please visit the object counting guide.

      1
  7. gmantovagmantovaGitHub

    Hi, my results with "count in line" are totally off. It confuses in and out while there is only one direction, I've wasted hours and this is crazy.

    It confuses in and out, and I don't understand why.

    Maybe someone can take a look?

    https://we.tl/t-GvMGmGPcPd

    1
    1. Glenn JocherGlenn JocherUltralytics

      @g-i-o-r-g-i-o i'm sorry to hear about the issues you're facing. Please ensure that the region and line points are correctly defined in your setup. For further guidance, you can refer to our object counting documentation at https://docs.ultralytics.com/guides/object-counting/. If the problem persists, consider checking the model configuration and input parameters.

  8. GenieV19GenieV19GitHub

    I have a question about the total number of objects detected vs the counts displayed. I have set the polygon region to be the entire video area, but my counts 'in' and 'out' do not equal either the number of boxes drawn and manually counted or the ID number displayed against each object, which is around double the number of boxes actually shown. Could you explain why this is and how to obtain a final number of unique objects detected? Thanks!

    1
    1. Paula DerrengerPaula DerrengerUltralytics(edited)

      @GenieV19 hello!

      Thank you for your question and for providing detailed information. It sounds like you're experiencing a discrepancy between the number of detected objects and the counts displayed. Let's address this step-by-step:

      1. Tracking IDs vs. Bounding Boxes: The IDs displayed are unique identifiers assigned to each tracked object. These IDs can appear higher than the number of visible bounding boxes due to objects entering and exiting the frame, or being temporarily occluded and then re-detected. This can lead to new IDs being assigned.

      2. Counting Logic: The 'in' and 'out' counts are based on tracked objects crossing the line or entering the region, and each track ID is counted once. Ensure that your region is set correctly and that the counting logic aligns with your expectations.

      3. Unique Object Counting: To get a final count of unique objects, you can collect the track IDs over the entire video. Here's a simple example:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("path/to/video/file.mp4")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define region points
      region_points = [(20, 400), (1080, 404), (1080, 360), (20, 360)]
      
      
      unique_ids = set()
      
      # Video writer
      video_writer = cv2.VideoWriter("object_counting_output.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=True,
          region=region_points,
          model="yolo26n.pt",
      )
      
      while cap.isOpened():
          success, im0 = cap.read()
          if not success:
              print("Video frame is empty or processing is complete.")
              break
      
          results = counter(im0)
          unique_ids.update(counter.track_ids)  # track IDs in this frame
          video_writer.write(results.plot_im)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      After the loop, print the result:

      print(f"Total unique objects detected: {len(unique_ids)}")
      1. Ensure Latest Versions: Please ensure you are using the latest versions of torch and ultralytics. You can upgrade them using:
        pip install --upgrade torch ultralytics

      If the issue persists, please provide a minimum reproducible example as outlined here. This will help us investigate further.

      Feel free to reach out if you have any more questions! 😊

  9. TanrionTVTanrionTVGitHub

    Hello,

    I would like to use your program to count grey sections. However, I have two problems: - Firstly, when I use the tracker some detections disappear. That's why I can't think of anything to improve it. - and secondly, some tracking identifiers are reallocated to objects that have nothing to do with the initial one. I was thinking of modifying botrack so that it only assigns the same identifiers for 10 frames, for example, but I have no idea how to do this. Do you think this is feasible?

    I have an i9 vPro and a Nvidia A2000.

    Here's the program I use:

    import cv2
    from ultralytics import YOLO, solutions
    
    MODEL_PATH = r'model\best.pt'
    model=YOLO(MODEL_PATH)
    cap = cv2.VideoCapture('test_26_50mm.avi')
    assert cap.isOpened(), "Error reading video file"
    w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
    
    # Define line points
    # Conveyor
    #line_points = [(0, 800), (2000, 800)]
    # Bar line vertical
    line_points = [(2000, 0), (2000, 2500)]
    # Bar line horizontal
    #line_points = [(0,2200), (2500, 2200)]
     
    # Video writer  
    video_writer = cv2.VideoWriter('results\output_bar_counting.avi', cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
    
    # Init Object Counter
    counter = solutions.ObjectCounter(
        view_img=False,
        reg_pts=line_points,
        classes_names=model.names,
        draw_tracks=False,
        track_thickness=2,
        line_thickness=5,
        line_dist_thresh = 200,
        view_out_counts=False
    
    )
    
    while cap.isOpened():
        success, frame = cap.read()
        if not success:
            print("Video frame is empty or video processing has been successfully completed.")
            break
        tracks = model.track(frame, persist=True, show=False, tracker = 'botsort.yaml', conf = 0.6)
    
        frame = counter.start_counting(frame, tracks)
        video_writer.write(frame)
    
    cap.release()
    video_writer.release()
    cv2.destroyAllWindows()

    I would have liked to share some pictures with you, but I couldn't. If you can help me, I would appreciate it.

    1
    1. TanrionTVTanrionTVGitHub

      and do you why the tracking is better when count in line than when count in region ?

    2. Glenn JocherGlenn JocherUltralytics(edited)

      Hello,

      Thank you for reaching out! Let's address your concerns one by one.

      Disappearing Detections

      The issue of disappearing detections can often be attributed to the confidence threshold or the tracking algorithm's parameters. You can experiment with the conf and iou parameters (they can be passed straight to ObjectCounter, which runs the tracker) to see if adjusting these values helps retain more detections. For example, lowering the confidence threshold might help:

      counter = solutions.ObjectCounter(region=line_points, model="best.pt", tracker="botsort.yaml", conf=0.3, iou=0.4)

      Reallocation of Tracking Identifiers

      Reallocation of tracking IDs can indeed be problematic. Modifying the BoT-SORT algorithm to maintain the same identifiers for a fixed number of frames is a feasible approach. However, this requires a deeper dive into the BoT-SORT implementation. You can start by editing the botsort.yaml configuration file to tweak parameters like track_high_thresh and track_low_thresh.

      Editing botsort.yaml

      You can modify the botsort.yaml file to adjust the tracking parameters. Here’s an example of how you might adjust the track_high_thresh to ensure that IDs are not reallocated too frequently:

      # botsort.yaml
      track_high_thresh: 0.6  # Increase this value to make the tracker more confident before reallocating IDs
      track_low_thresh: 0.1   # Lower this value to keep tracks alive longer

      Example Code

      Here’s an updated version of your code with some adjustments:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("test_26_50mm.avi")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define line points
      line_points = [(2000, 0), (2000, 2500)]
      
      # Video writer
      video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=False,
          region=line_points,
          model=r"model/best.pt",
          tracker="botsort.yaml",
          conf=0.3,
          iou=0.4,
          line_width=5,
          show_out=False,
      )
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              print("Video frame is empty or video processing has been successfully completed.")
              break
      
          results = counter(frame)
          video_writer.write(results.plot_im)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      Further Customization

      For more advanced customization, you might need to dive into the BoT-SORT source code. If you're comfortable with Python, you can clone the BoT-SORT repository, make your changes, and then use your modified version with Ultralytics YOLO.

      Additional Resources

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide. This guide provides comprehensive information on setting up and optimizing object counting with Ultralytics YOLO.

      Feel free to reach out if you have any more questions or need further assistance. Happy coding! 😊

    3. TanrionTVTanrionTVGitHub

      Thank you very much for your advice, I had already tried to modify the conf and iou parameters as well as the botsort.yaml file. However, it still doesn't work. I think I'm asking too much of the program, because the gray sections are very close together and the camera only records at 24fps. Thanks anyway! Or do you have other trackers to recommend?

    4. TanrionTVTanrionTVGitHub

      Maybe I could do some tracking in a cropped area, what do you think about that ?

    5. Glenn JocherGlenn JocherUltralytics(edited)

      @TanrionTV hello,

      Thank you for your thoughtful question! Cropping the area for tracking can indeed be a useful strategy, especially when dealing with closely packed objects. By focusing on a smaller region, you can potentially improve the accuracy and consistency of the tracking.

      Here’s how you can implement cropping in your existing code:

      1. Crop the Frame: Before passing the frame to the counter, crop it to the region of interest.
      2. Use Cropped Coordinates: ObjectCounter tracks the image you pass it, so define its line or region in the crop's coordinates and paste the annotated crop back into the full frame if needed.

      Here’s an example of how you might modify your code to include cropping:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("test_26_50mm.avi")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define crop region (x, y, width, height)
      x, y, cw, ch = (500, 500, 1000, 1000)
      
      # Line points are given in cropped-frame coordinates (here a vertical line in the middle of the crop)
      line_points = [(500, 0), (500, 1000)]
      
      # Video writer
      video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=False,
          region=line_points,
          model=r"model/best.pt",
          tracker="botsort.yaml",
          conf=0.3,
          iou=0.4,
          line_width=5,
          show_out=False,
      )
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              print("Video frame is empty or video processing has been successfully completed.")
              break
      
          # Crop, count inside the crop, then paste the annotated crop back into the full frame
          results = counter(frame[y : y + ch, x : x + cw])
          frame[y : y + ch, x : x + cw] = results.plot_im
          video_writer.write(frame)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      Alternative Trackers

      If BoT-SORT is not meeting your needs, you might want to try ByteTrack, which is another robust tracker supported by Ultralytics. You can switch to ByteTrack by changing the tracker parameter:

      counter = solutions.ObjectCounter(region=line_points, model="model/best.pt", tracker="bytetrack.yaml", conf=0.3, iou=0.4)

      Additional Tips

      • Frame Rate: Given that your camera records at 24fps, ensure that your model and tracker can handle this frame rate efficiently. Sometimes, reducing the frame rate can help improve tracking stability.
      • Experiment with Parameters: Continue experimenting with different conf and iou values, as well as tracker-specific parameters in the YAML files.

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide.

      Feel free to reach out if you have any more questions or need further assistance. Happy coding! 😊

    6. TanrionTVTanrionTVGitHub

      thank you ! but i have this error : track.boxes.xyxy[:, [0, 2]] += x ~~~~~~~~~~~~~~~~^^^^^^^^^^^ RuntimeError: Inplace update to inference tensor outside InferenceMode is not allowed.You can make a clone to get a normal tensor before doing inplace update.See https://github.com/pytorch/rfcs/pull/17 for more details.

    7. Glenn JocherGlenn JocherUltralytics(edited)

      Hello,

      Thank you for your detailed feedback and for sharing your code! 😊

      The inplace tensor update error comes from editing the tracked boxes after inference. In current versions you don't need to: ObjectCounter runs the tracker itself, so you pass it the cropped image with the line defined in the crop's coordinates and paste the annotated crop back. Here’s how you can modify your code:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("test_26_50mm.avi")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define crop region (x, y, width, height)
      x, y, cw, ch = (500, 500, 1000, 1000)
      
      # Line points are given in cropped-frame coordinates (here a vertical line in the middle of the crop)
      line_points = [(500, 0), (500, 1000)]
      
      # Video writer
      video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=False,
          region=line_points,
          model=r"model/best.pt",
          tracker="botsort.yaml",
          conf=0.3,
          iou=0.4,
          line_width=5,
          show_out=False,
      )
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              print("Video frame is empty or video processing has been successfully completed.")
              break
      
          # Crop, count inside the crop, then paste the annotated crop back into the full frame
          results = counter(frame[y : y + ch, x : x + cw])
          frame[y : y + ch, x : x + cw] = results.plot_im
          video_writer.write(frame)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      Alternative Trackers

      If BoT-SORT is not meeting your needs, you might want to try ByteTrack, which is another robust tracker supported by Ultralytics. You can switch to ByteTrack by changing the tracker parameter:

      counter = solutions.ObjectCounter(region=line_points, model="model/best.pt", tracker="bytetrack.yaml", conf=0.3, iou=0.4)

      Additional Tips

      • Frame Rate: Given that your camera records at 24fps, ensure that your model and tracker can handle this frame rate efficiently. Sometimes, reducing the frame rate can help improve tracking stability.
      • Experiment with Parameters: Continue experimenting with different conf and iou values, as well as tracker-specific parameters in the YAML files.

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide.

      Feel free to reach out if you have any more questions or need further assistance. Happy coding! 😊

    8. Thomas-CHOCHOYThomas-CHOCHOYGitHub

      Thank you for your help! Your fix gives me this error:

          track.boxes.xyxy = track.boxes.xyxy.clone() # Clone the tensor to avoid the inplace update error
          ^^^^^^^^^^^^^^^^
      AttributeError : the ‘xyxy’ property of the ‘Boxes’ object has no setter

      but I managed to fix it with the following patch:

          # Track the cropped image
          tracks1 = model.track(frame, persist=True, show=False, tracker = ‘bytetrack.yaml’, conf = 0.2,iou=0.4, vid_stride=1, augment=True, retina_masks=False)
      
      
          # Adjust the coordinates to the original image
          tracks = deepcopy(tracks1)
          for track in tracks :
              track.boxes.xyxy[ :, [0, 2]] += x
              track.boxes.xyxy[ :, [1, 3]] += y += y

      However, even when cropping the image, the tracker reallocates the old identifiers to the new objects. I've also tried using bytetrack by adjusting the parameters but the results are even worse. I'm starting to run out of ideas. Is it possible to send you the video (20mo), maybe you'll see it more clearly than I do.

      Thank you very much for your advice!

    9. Glenn JocherGlenn JocherUltralytics(edited)

      Hello,

      Thank you for your detailed explanation and for sharing your code! It's great to see your dedication to solving this issue.

      Regarding your current challenges with tracking and identifier reallocation, it seems like you’ve already tried several approaches, including modifying the conf and iou parameters and experimenting with different trackers. Your idea of cropping the image is a good one, and it’s excellent that you managed to fix the tensor update issue.

      Further Suggestions

      1. Adjusting Tracker Parameters: Since you’ve already tried adjusting the conf and iou parameters, another approach could be to fine-tune other parameters in the botsort.yaml or bytetrack.yaml configuration files. For example, you can try increasing the track_high_thresh and track_low_thresh values to make the tracker more conservative in reassigning IDs.

      2. Using a Different Tracker: If BoT-SORT and ByteTrack are not yielding satisfactory results, you might want to explore other tracking algorithms. While Ultralytics primarily supports BoT-SORT and ByteTrack, you can integrate other trackers with custom code.

      3. Frame Rate and Resolution: Given that your camera records at 24fps, you might want to experiment with reducing the frame rate or resolution to see if it improves tracking stability. Sometimes, processing fewer frames can help the tracker maintain consistent IDs.

      Sharing the Video

      If you’re comfortable sharing the video, it would indeed help in diagnosing the issue more accurately. You can upload the video to a cloud storage service (like Google Drive or Dropbox) and share the link here. This way, we can take a closer look and provide more targeted advice.

      Example Code with Cropping

      In current versions ObjectCounter runs the tracker itself, so you can pass it the cropped image directly with the line defined in the crop's coordinates, with no tensor cloning needed:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("test_26_50mm.avi")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define crop region (x, y, width, height)
      x, y, cw, ch = (500, 500, 1000, 1000)
      
      # Line points are given in cropped-frame coordinates (here a vertical line in the middle of the crop)
      line_points = [(500, 0), (500, 1000)]
      
      # Video writer
      video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=False,
          region=line_points,
          model=r"model/best.pt",
          tracker="botsort.yaml",
          conf=0.3,
          iou=0.4,
          line_width=5,
          show_out=False,
      )
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              print("Video frame is empty or video processing has been successfully completed.")
              break
      
          # Crop, count inside the crop, then paste the annotated crop back into the full frame
          results = counter(frame[y : y + ch, x : x + cw])
          frame[y : y + ch, x : x + cw] = results.plot_im
          video_writer.write(frame)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      Additional Resources

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide.

      Feel free to share the video link or any additional details here, and we’ll do our best to assist you further. Thank you for your patience and persistence!

    10. Glenn JocherGlenn JocherUltralytics(edited)

      Hello,

      Thank you for sharing the details and the GitHub link to your project! I appreciate your efforts in providing a comprehensive example. This will help us better understand the issue and provide more targeted assistance.

      Next Steps

      1. Reproducible Example: Please ensure that the provided code and model are using the latest versions of torch and ultralytics. You can update your packages using:

        pip install --upgrade torch ultralytics
      2. Investigate Tracking Parameters: Since you've already tried adjusting conf and iou parameters, another approach could be to fine-tune other parameters in the botsort.yaml or bytetrack.yaml configuration files. For example, increasing track_high_thresh and track_low_thresh values might help in maintaining consistent IDs.

      3. Cropping Strategy: Cropping the frame to focus on a specific region is a good strategy. Ensure that the counting line is defined in the crop's coordinates. Note that ObjectCounter now runs the tracker itself, so you can pass it the cropped image with the line defined in the crop's coordinates and no tensor cloning is needed. Here’s a refined version of your code:

        import cv2
        
        from ultralytics import solutions
        
        cap = cv2.VideoCapture("test_26_50mm.avi")
        assert cap.isOpened(), "Error reading video file"
        w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
        
        # Define crop region (x, y, width, height)
        x, y, cw, ch = (500, 500, 1000, 1000)
        
        # Line points are given in cropped-frame coordinates (here a vertical line in the middle of the crop)
        line_points = [(500, 0), (500, 1000)]
        
        # Video writer
        video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
        
        # Init Object Counter
        counter = solutions.ObjectCounter(
            show=False,
            region=line_points,
            model=r"model/best.pt",
            tracker="botsort.yaml",
            conf=0.3,
            iou=0.4,
            line_width=5,
            show_out=False,
        )
        
        while cap.isOpened():
            success, frame = cap.read()
            if not success:
                print("Video frame is empty or video processing has been successfully completed.")
                break
        
            # Crop, count inside the crop, then paste the annotated crop back into the full frame
            results = counter(frame[y : y + ch, x : x + cw])
            frame[y : y + ch, x : x + cw] = results.plot_im
            video_writer.write(frame)
        
        cap.release()
        video_writer.release()
        cv2.destroyAllWindows()
      4. Alternative Trackers: If BoT-SORT and ByteTrack are not yielding satisfactory results, you might want to explore other tracking algorithms. While Ultralytics primarily supports BoT-SORT and ByteTrack, you can integrate other trackers with custom code.

      Additional Resources

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide.

      Feel free to share any additional details or updates here, and we’ll do our best to assist you further. Thank you for your patience and persistence! 😊

    11. Thomas-CHOCHOYThomas-CHOCHOYGitHub

      my github is only useful if you look at it. If you had looked at it, you would have seen that I have more programs, between "line counter", "region counter", "cropped counter" and they don't work. What's more, I've posted a video of my project on github, so maybe you'll see it more clearly. On the other hand, if you have any other trackers to suggest, I'd love to hear from you. Personally, I don't know of any others that perform as well. Thank you very much for your help!

    12. Glenn JocherGlenn JocherUltralytics(edited)

      Hello @Tanrion,

      Thank you for sharing your GitHub repository and the video. I appreciate your detailed explanation and the effort you've put into troubleshooting the issue.

      Reviewing Your Code and Video

      I've reviewed the programs in your repository, including the "line counter," "region counter," and "cropped counter." It's clear that you've tried multiple approaches to solve the problem.

      Tracking Identifiers Issue

      Regarding the reallocation of tracking identifiers, this can be a challenging issue with object tracking. Here are a few suggestions to improve the tracking consistency:

      1. Adjust Tracker Parameters:

        • BoT-SORT: You can try increasing the track_high_thresh and track_low_thresh values in the botsort.yaml configuration file to make the tracker more conservative in reassigning IDs.
        • ByteTrack: Similarly, adjust the parameters in the bytetrack.yaml file.
      2. Alternative Trackers: While BoT-SORT and ByteTrack are among the best, you might want to explore other trackers like DeepSORT or FairMOT. These are not natively supported by Ultralytics but can be integrated with some custom coding.

      3. Frame Rate and Resolution: Reducing the frame rate or resolution might help improve tracking stability. Sometimes, processing fewer frames can help the tracker maintain consistent IDs.

      Cropping Strategy

      Your idea of cropping the image is excellent. It helps focus on a specific region, potentially improving tracking accuracy. In current versions ObjectCounter runs the tracker itself, so you can pass it the cropped image with the line defined in the crop's coordinates, with no tensor cloning needed:

      import cv2
      
      from ultralytics import solutions
      
      cap = cv2.VideoCapture("test_26_50mm.avi")
      assert cap.isOpened(), "Error reading video file"
      w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
      
      # Define crop region (x, y, width, height)
      x, y, cw, ch = (500, 500, 1000, 1000)
      
      # Line points are given in cropped-frame coordinates (here a vertical line in the middle of the crop)
      line_points = [(500, 0), (500, 1000)]
      
      # Video writer
      video_writer = cv2.VideoWriter("results/output_bar_counting.avi", cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
      
      # Init Object Counter
      counter = solutions.ObjectCounter(
          show=False,
          region=line_points,
          model=r"model/best.pt",
          tracker="botsort.yaml",
          conf=0.3,
          iou=0.4,
          line_width=5,
          show_out=False,
      )
      
      while cap.isOpened():
          success, frame = cap.read()
          if not success:
              print("Video frame is empty or video processing has been successfully completed.")
              break
      
          # Crop, count inside the crop, then paste the annotated crop back into the full frame
          results = counter(frame[y : y + ch, x : x + cw])
          frame[y : y + ch, x : x + cw] = results.plot_im
          video_writer.write(frame)
      
      cap.release()
      video_writer.release()
      cv2.destroyAllWindows()

      Further Assistance

      If you continue to face issues, please ensure you are using the latest versions of torch and ultralytics. You can update your packages using:

      pip install --upgrade torch ultralytics

      For more detailed guidance on object counting and tracking, you can refer to our Object Counting Guide.

      Feel free to share any additional details or updates here, and we’ll do our best to assist you further. Thank you for your patience and persistence! 😊