Chạy suy luận trên video
Chạy YOLO26 trên tệp video và camera trực tiếp với bộ nhớ được giới hạn, theo dõi đối tượng để đếm mỗi đối tượng một lần và kiểm tra xem model có theo kịp tốc độ khung hình hay không.
Hầu hết hệ thống thị giác được triển khai đều xử lý video: camera trên băng chuyền, cửa ra vào và đường phố. Video có thêm hai vấn đề mà ảnh đơn không gặp phải. Bộ nhớ: không thể giữ bản ghi dài trong RAM. Danh tính: detector nhìn thấy cùng một người trong 60 khung hình và báo cáo 60 người.
Trong bài học này, bạn sẽ truyền video từng khung hình bằng Predict mode, thêm theo dõi đối tượng để đếm mỗi người một lần, tự viết vòng lặp camera và đo xem model có theo kịp hay không.
Thực hành
Ví dụ minh họa: Dự đoán trên tệp video#
Video dùng cùng Predict mode như ảnh. Đoạn clip 62 khung hình này cho thấy mọi người đi qua một sảnh lớn:
yolo predict model=yolo26n.pt source=https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4video 1/1 (frame 1/62) solutions_ci_demo.mp4: 384x640 22 persons, 27.3ms
...
video 1/1 (frame 62/62) solutions_ci_demo.mp4: 384x640 22 persons, 54.8ms
Results saved to runs/detect/predictframe 1/62: Ultralytics giải mã video và xử lý từng khung hình như một ảnh.22 persons: các detection trong khung hình đó. Những người đi bộ giống nhau được đếm lại trong mọi khung hình.27.3ms...54.8ms: thời gian xử lý mỗi khung hình thay đổi tùy vào các tác vụ khác mà máy đang thực hiện.
Video đã chú thích là runs/detect/predict/solutions_ci_demo.mp4. Model của bạn hoạt động tương tự: thay yolo26n.pt bằng runs/detect/pills_v1/weights/best.pt.
Truyền nguồn dài và trực tiếp#
Với mã xử lý detection, hãy lặp qua một luồng. Mỗi vòng lặp trả về Results của một khung hình, rồi loại bỏ khung hình đó:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
frames, people = 0, 0
for result in model(source, stream=True, classes=[0], verbose=False): # one Results object per frame
frames += 1
people += len(result.boxes)
print(f"{frames} frames, {people / frames:.1f} people per frame")62 frames, 22.2 people per frameCùng vòng lặp này chấp nhận chỉ số webcam (source=0) hoặc URL camera như rtsp://camera.local/stream, và chạy cho đến khi luồng kết thúc hoặc bạn dừng vòng lặp. Thêm vid_stride=2 để xử lý cách mỗi khung hình. Để tạo giao diện web quanh vòng lặp này, hướng dẫn suy luận trực tiếp với Streamlit sẽ đóng gói vòng lặp trong một ứng dụng.
Ví dụ minh họa: Đếm mỗi người một lần#
"22 người mỗi khung hình" không phải con số mọi người cần; điều họ muốn biết là "đã có bao nhiêu người đi qua". Theo dõi nhiều đối tượng liên kết các hộp qua các khung hình, còn Track mode gán cho mỗi đối tượng một ID trong boxes.id:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
seen = set()
for result in model.track(source, stream=True, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False):
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique people tracked")32 unique people trackedis_track là False trên các khung hình trước khi bất kỳ track nào được xác nhận, khi boxes.id là None. Dùng ID để đếm, xác định quỹ đạo hoặc triển khai logic như "đối tượng này đã ở đây được 3 giây".

| Bộ theo dõi | Tốc độ | Độ bền vững |
|---|---|---|
bytetrack.yaml | Nhanh hơn, đơn giản hơn | Mất ID thường xuyên hơn khi đối tượng biến mất trong thời gian ngắn |
botsort.yaml | Chậm hơn | Giữ ID tốt hơn khi camera di chuyển (bù chuyển động; ReID theo ngoại hình là tùy chọn thông qua with_reid) |
Nếu không chỉ định tracker, Ultralytics dùng tracktrack.yaml, mặc định hiện tại; Track mode cũng tích hợp ocsort.yaml, deepocsort.yaml và fasttrack.yaml. Cách chọn và tinh chỉnh bộ theo dõi, cũng như xây dựng đếm đối tượng, bản đồ nhiệt và ước tính tốc độ dựa trên các bộ theo dõi đó, được trình bày trong hướng dẫn Theo dõi đối tượng với ByteTrack, BoT-SORT và TrackTrack.
Ví dụ minh họa: Vòng lặp camera của riêng bạn#
Các ứng dụng thực tế thường tự đọc khung hình — để thay đổi kích thước, cắt, gắn dấu thời gian hoặc chia sẻ camera với mã khác — rồi truyền từng khung hình cho model. Khi đó, persist=True giữ cho bộ theo dõi hoạt động giữa các lần gọi:
import cv2
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
cap = cv2.VideoCapture("solutions_ci_demo.mp4") # saved locally by the commands above; or 0, or an rtsp:// URL
seen = set()
while cap.isOpened():
ok, frame = cap.read()
if not ok:
break
result = model.track(frame, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False)[0]
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
cap.release()
print(f"{len(seen)} unique people, highest ID {max(seen)}")32 unique people, highest ID 67Vẫn là 32 người như track.py. Lưu ý ID lớn nhất là 67, không phải 32: bộ theo dõi cũng cấp ID cho các track tạm thời không bao giờ được xác nhận, nên ID có khoảng trống.
Theo kịp nguồn#
Camera 30 FPS cung cấp một khung hình sau mỗi 33 ms; tốc độ thực tế của bạn bị giới hạn bởi khâu chậm nhất trong giải mã, suy luận và ghi dữ liệu. Trên CPU máy tính xách tay của chúng tôi, yolo26n mất từ 26 đến 46 ms cho mỗi khung hình 384×640 qua các lần chạy, tùy thuộc vào những tác vụ khác máy đang thực hiện: chạm hoặc vượt ngân sách, không có dư địa. Nếu hệ thống của bạn không theo kịp, hãy điều chỉnh theo thứ tự sau:
| Điều chỉnh | Tác động |
|---|---|
Model nhỏ hơn (n thay cho s) | Thường nhanh hơn 2–3 lần |
Giảm imgsz (480 thay vì 640) | Ít pixel hơn, ít tính toán hơn; đối tượng nhỏ bị ảnh hưởng trước tiên |
vid_stride=2 | Giảm một nửa khối lượng xử lý; phù hợp với cảnh chuyển động chậm |
| GPU hoặc bản export đã tối ưu | Cải thiện lớn nhất — engine TensorRT trên NVIDIA hoặc INT8; xem bài học tiếp theo |
Bài Suy luận nhiều luồng trình bày cách xử lý nhiều camera cùng lúc và cơ chế đa luồng đi kèm.
Tránh những lỗi này#
Triệu chứng: bộ nhớ tăng dần cho đến khi tiến trình bị dừng khi xử lý bản ghi dài, hoặc lời gọi camera trực tiếp không bao giờ trả về. Nguyên nhân: nếu không có tham số này, lời gọi Python thu thập một object Results cho mỗi frame trước khi trả về. Cách khắc phục: truyền stream=True và lặp qua generator — generator không làm gì cho đến khi bạn lặp qua nó.
Triệu chứng: trong cv2_loop.py mà không có persist=True, số lượng giảm còn 27 và ID cao nhất cũng là 27: ID khởi động lại ở mỗi frame, nên số lượng "duy nhất" thực ra chỉ là số lượng ở frame đông nhất. Cách khắc phục: truyền persist=True mỗi khi gọi track một lần cho mỗi frame.
Triệu chứng: đếm được 67 người dù thực tế có 32 người. Nguyên nhân: ID có khoảng trống do các track chưa được xác nhận. Cách khắc phục: đếm kích thước của tập ID, như trong track.py.
Tracker mặc định có thể thay đổi giữa các bản phát hành. Hãy truyền tracker="bytetrack.yaml" (hoặc tracker bạn chọn) để số lượng luôn có thể so sánh giữa các phiên bản.
Hiển thị lời giải
import sys
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
seen, times = set(), []
for result in model.track(sys.argv[1], stream=True, persist=True, tracker="bytetrack.yaml", verbose=False):
times.append(result.speed["inference"])
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique objects, {sum(times) / len(times):.1f} ms inference per frame")Chạy bằng python track_any.py your_video.mp4.
32 unique objects, 30.5 ms inference per frame (26-46 ms across runs on a laptop CPU)
Source is 30 FPS -> 33 ms budget: fits only on a quiet machine, with no headroom
First lever: export to OpenVINO or ONNX for this CPU, then vid_stride=2 if still short