[Python] Counting objects in YOLO11 defining several lines

Discussão em 'Python' iniciado por Stack, Maio 20, 2025.

  1. Stack

    Stack Membro Participativo

    I'm using an example from Ultralytics (YOLOv11) to count apples on a conveyor belt. It defines a line across the frame and counts how many apples cross that line using the ObjectCounter solution provided by Ultralytics.

    Here is a the original code:

    import cv2

    from ultralytics import solutions

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

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

    # 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="yolo11n.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="botsort.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


    Now I’d like to adapt this code to count cars on a road with two lanes. The idea is to draw two separate lines, one for each lane, and count how many cars cross each line independently.

    At first, I tried creating two separate ObjectCounter instances, each with its own line. However, this approach is very inefficient, since it runs inference separately for each counter, even though both are analyzing the same frame.

    Is there a way to define multiple counting lines in a single ObjectCounter instance?

    I also came across another example on the Ultralytics website using YOLOv11, where they define multiple regions in a dictionary and pass that dictionary to a single instance of the RegionCounter class.

    However, it seems the RegionCounter class only works with polygons and requires four points, so it wouldn’t be suitable for working with lines. If I define a dictionary of lines and pass it to RegionCounter:

    #!pip install ultralytics

    import ultralytics
    import cv2
    from ultralytics import solutions

    ultralytics.checks()

    cap = cv2.VideoCapture("trafficCam.mp4")
    #cap = cv2.VideoCapture("traffic_cam_short.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))

    # Video writer
    video_writer = cv2.VideoWriter("counting.avi",
    cv2.VideoWriter_fourcc(*"mp4v"),
    fps, (w, h))

    region_lineas = {
    "linea1": [(140, 450), (500, 450)], # diccionario de líneas para contar los coches en cada carril
    "linea2": [(550, 450), (720, 450)],
    }


    print(region_lineas)

    # Initialize region counter object
    counter = solutions.RegionCounter(
    show=True, # display the frame
    region=region_lineas, # pass region points
    model="yolo11s.pt", # model for counting in regions i.e yolo11s.pt
    classes=[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
    tracker="bytetrack.yaml", # Enable tracking
    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

    results = counter(im0) # count the objects

    # Mostrar la imagen en tiempo real
    cv2.imshow("Cuenta de coches por carril", im0)

    # Guardar el vídeo procesado
    video_writer.write(results.plot_im)

    cap.release() # Release the capture
    video_writer.release()
    cv2.destroyAllWindows()


    I get an error:

    ValueError: A linearring requires at least 4 coordinates.


    Passing the dictionary of lines to an ObjectCounter instead of to a RegionCounter also doesn’t work: ObjectCounter expects a single line (as a list of two points) or a polygonal region (at least 3 points), not a dictionary or multiple lines at once.

    My question: Is there a way to define multiple counting lines in a single ObjectCounter instance? If not, what would be the most efficient way to count objects crossing multiple lines in the same frame without repeating inference?

    Continue reading...

Compartilhe esta Página