์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

Ultralytics YOLOv8 ๐Ÿš€๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐœ์ฒด ์ˆ˜ ๊ณ„์‚ฐ

์˜ค๋ธŒ์ ํŠธ ์นด์šดํŒ…์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๊ฐ์ฒด ์นด์šดํŒ… Ultralytics YOLOv8 ๋Š” ๋™์˜์ƒ ๋ฐ ์นด๋ฉ”๋ผ ์ŠคํŠธ๋ฆผ์—์„œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๊ณ  ์นด์šดํŒ…ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. YOLOv8 ๋Š” ์ตœ์ฒจ๋‹จ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๋”ฅ๋Ÿฌ๋‹ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๊ตฐ์ค‘ ๋ถ„์„ ๋ฐ ๊ฐ์‹œ์™€ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํšจ์œจ์ ์ด๊ณ  ์ •ํ™•ํ•œ ๊ฐ์ฒด ์นด์šดํŒ…์„ ์ œ๊ณตํ•˜๋Š” ์‹ค์‹œ๊ฐ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํƒ์›”ํ•œ ์„ฑ๋Šฅ์„ ๋ฐœํœ˜ํ•ฉ๋‹ˆ๋‹ค.


Watch: ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ์ฒด ์ˆ˜ ๊ณ„์‚ฐ Ultralytics YOLOv8

Watch: Class-wise Object Counting using Ultralytics YOLOv8

์˜ค๋ธŒ์ ํŠธ ์นด์šดํŒ…์˜ ์žฅ์ ์€?

  • ๋ฆฌ์†Œ์Šค ์ตœ์ ํ™”: ๊ฐœ์ฒด ์นด์šดํŒ…์€ ์ •ํ™•ํ•œ ๊ฐœ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žฌ๊ณ  ๊ด€๋ฆฌ์™€ ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฆฌ์†Œ์Šค ํ• ๋‹น์„ ์ตœ์ ํ™”ํ•˜์—ฌ ํšจ์œจ์ ์ธ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณด์•ˆ ๊ฐ•ํ™”: ๊ฐœ์ฒด ์นด์šดํŒ…์€ ๊ฐœ์ฒด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ถ”์ ํ•˜๊ณ  ๊ณ„์‚ฐํ•˜์—ฌ ์‚ฌ์ „ ์œ„ํ˜‘ ํƒ์ง€๋ฅผ ์ง€์›ํ•จ์œผ๋กœ์จ ๋ณด์•ˆ๊ณผ ๊ฐ์‹œ๋ฅผ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ •๋ณด์— ๊ธฐ๋ฐ˜ํ•œ ์˜์‚ฌ ๊ฒฐ์ •: ๊ฐ์ฒด ์นด์šดํŒ…์€ ์˜์‚ฌ ๊ฒฐ์ •, ์†Œ๋งค์—…, ๊ตํ†ต ๊ด€๋ฆฌ ๋ฐ ๊ธฐํƒ€ ๋‹ค์–‘ํ•œ ์˜์—ญ์˜ ํ”„๋กœ์„ธ์Šค ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๊ท€์ค‘ํ•œ ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

๋ฌผ๋ฅ˜ ์–‘์‹์—…
์ปจ๋ฒ ์ด์–ด ๋ฒจํŠธ ํŒจํ‚ท ๊ณ„์ˆ˜ ์‚ฌ์šฉ Ultralytics YOLOv8 ๋ฐ”๋‹ค์—์„œ ๋ฌผ๊ณ ๊ธฐ ์ˆ˜ ์„ธ๊ธฐ Ultralytics YOLOv8
์ปจ๋ฒ ์ด์–ด ๋ฒจํŠธ ํŒจํ‚ท ๊ณ„์ˆ˜ ์‚ฌ์šฉ Ultralytics YOLOv8 ๋ฐ”๋‹ค์—์„œ ๋ฌผ๊ณ ๊ธฐ ์ˆ˜ ์„ธ๊ธฐ Ultralytics YOLOv8

YOLOv8 ์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐœ์ฒด ์ˆ˜ ๊ณ„์‚ฐ

import cv2

from ultralytics import YOLO, solutions

model = YOLO("yolov8n.pt")
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)]

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

# Init Object Counter
counter = solutions.ObjectCounter(
    view_img=True,
    reg_pts=region_points,
    classes_names=model.names,
    draw_tracks=True,
    line_thickness=2,
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    tracks = model.track(im0, persist=True, show=False)

    im0 = counter.start_counting(im0, tracks)
    video_writer.write(im0)

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

from ultralytics import YOLO, solutions

model = YOLO("yolov8n.pt")
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 as a polygon with 5 points
region_points = [(20, 400), (1080, 404), (1080, 360), (20, 360), (20, 400)]

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

# Init Object Counter
counter = solutions.ObjectCounter(
    view_img=True,
    reg_pts=region_points,
    classes_names=model.names,
    draw_tracks=True,
    line_thickness=2,
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    tracks = model.track(im0, persist=True, show=False)

    im0 = counter.start_counting(im0, tracks)
    video_writer.write(im0)

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

from ultralytics import YOLO, solutions

model = YOLO("yolov8n.pt")
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 line points
line_points = [(20, 400), (1080, 400)]

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

# Init Object Counter
counter = solutions.ObjectCounter(
    view_img=True,
    reg_pts=line_points,
    classes_names=model.names,
    draw_tracks=True,
    line_thickness=2,
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    tracks = model.track(im0, persist=True, show=False)

    im0 = counter.start_counting(im0, tracks)
    video_writer.write(im0)

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

from ultralytics import YOLO, solutions

model = YOLO("yolov8n.pt")
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))

line_points = [(20, 400), (1080, 400)]  # line or region points
classes_to_count = [0, 2]  # person and car classes for count

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

# Init Object Counter
counter = solutions.ObjectCounter(
    view_img=True,
    reg_pts=line_points,
    classes_names=model.names,
    draw_tracks=True,
    line_thickness=2,
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    tracks = model.track(im0, persist=True, show=False, classes=classes_to_count)

    im0 = counter.start_counting(im0, tracks)
    video_writer.write(im0)

cap.release()
video_writer.release()
cv2.destroyAllWindows()
์ง€์—ญ ์ด๋™ ๊ฐ€๋Šฅ

ํ”„๋ ˆ์ž„์˜ ๊ฐ€์žฅ์ž๋ฆฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์˜์—ญ์„ ์›ํ•˜๋Š” ๊ณณ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ์ˆ˜ ObjectCounter

๋‹ค์Œ์€ ํ‘œ์ž…๋‹ˆ๋‹ค. ObjectCounter ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

์ด๋ฆ„ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
classes_names dict None ํด๋ž˜์Šค ์ด๋ฆ„ ์‚ฌ์ „.
reg_pts list [(20, 400), (1260, 400)] ๊ณ„์‚ฐ ์˜์—ญ์„ ์ •์˜ํ•˜๋Š” ํฌ์ธํŠธ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค.
count_reg_color tuple (255, 0, 255) ์นด์šดํŒ… ์˜์—ญ์˜ RGB ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
count_txt_color tuple (0, 0, 0) ์นด์šดํŠธ ํ…์ŠคํŠธ์˜ RGB ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
count_bg_color tuple (255, 255, 255) ์นด์šดํŠธ ํ…์ŠคํŠธ ๋ฐฐ๊ฒฝ์˜ RGB ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
line_thickness int 2 ๊ฒฝ๊ณ„ ์ƒ์ž์˜ ์„  ๋‘๊ป˜์ž…๋‹ˆ๋‹ค.
track_thickness int 2 ํŠธ๋ž™ ์„ ์˜ ๋‘๊ป˜์ž…๋‹ˆ๋‹ค.
view_img bool False ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ ํ‘œ์‹œ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๋Š” ํ”Œ๋ž˜๊ทธ์ž…๋‹ˆ๋‹ค.
view_in_counts bool True ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์— ์ธ ์นด์šดํŠธ๋ฅผ ํ‘œ์‹œํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๋Š” ํ”Œ๋ž˜๊ทธ์ž…๋‹ˆ๋‹ค.
view_out_counts bool True ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์— ์•„์›ƒ ์นด์šดํŠธ๋ฅผ ํ‘œ์‹œํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๋Š” ํ”Œ๋ž˜๊ทธ์ž…๋‹ˆ๋‹ค.
draw_tracks bool False ํ”Œ๋ž˜๊ทธ - ๊ฐœ์ฒด ํŠธ๋ž™์„ ๊ทธ๋ฆด์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
track_color tuple None ํŠธ๋ž™์˜ RGB ์ƒ‰์ƒ.
region_thickness int 5 ๊ฐ์ฒด ๊ณ„์‚ฐ ์˜์—ญ์˜ ๋‘๊ป˜์ž…๋‹ˆ๋‹ค.
line_dist_thresh int 15 ๋ผ์ธ ์นด์šดํ„ฐ์˜ ์œ ํด๋ฆฌ๋“œ ๊ฑฐ๋ฆฌ ์ž„๊ณ„๊ฐ’์ž…๋‹ˆ๋‹ค.
cls_txtdisplay_gap int 50 ๊ฐ ํด๋ž˜์Šค ์ˆ˜ ์‚ฌ์ด์˜ ๊ฐ„๊ฒฉ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ธ์ˆ˜ model.track

์ด๋ฆ„ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
source im0 None ์ด๋ฏธ์ง€ ๋˜๋Š” ๋น„๋””์˜ค์˜ ์†Œ์Šค ๋””๋ ‰ํ† ๋ฆฌ
persist bool False ํ”„๋ ˆ์ž„ ๊ฐ„ ํŠธ๋ž™ ์ง€์†
tracker str botsort.yaml ์ถ”์  ๋ฐฉ๋ฒ• '๋ฐ”์ดํŠธํŠธ๋ž™' ๋˜๋Š” '๋ด‡์†ŒํŠธ'
conf float 0.3 ์‹ ๋ขฐ ์ž„๊ณ„๊ฐ’
iou float 0.5 IOU ์ž„๊ณ„๊ฐ’
classes list None ํด๋ž˜์Šค๋ณ„๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: classes=0 ๋˜๋Š” classes=[0,2,3]).
verbose bool True ๊ฐœ์ฒด ์ถ”์  ๊ฒฐ๊ณผ ํ‘œ์‹œ


Created 2023-12-02, Updated 2024-06-10
Authors: glenn-jocher (14), IvorZhu331 (1), RizwanMunawar (6), AyushExel (1)

๋Œ“๊ธ€