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

Ultralytics YOLOv8 ๐Ÿš€์„ ์‚ฌ์šฉํ•œ ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง

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



Watch: Ultralytics YOLOv8 | ํ‘ธ์‹œ์—…, ํ’€์—…, ๋ณต๊ทผ ์šด๋™์„ ์ด์šฉํ•œ ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง์˜ ์žฅ์ ์€?

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

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

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง
ํ‘ธ์‹œ์—… ์นด์šดํŒ… ํ’€์—… ์นด์šดํŒ…
ํ‘ธ์‹œ์—… ์นด์šดํŒ… ํ’€์—… ์นด์šดํŒ…

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง ์˜ˆ์‹œ

from ultralytics import YOLO
from ultralytics.solutions import ai_gym
import cv2

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

gym_object = ai_gym.AIGym()  # init AI GYM module
gym_object.set_args(line_thickness=2,
                    view_img=True,
                    pose_type="pushup",
                    kpts_to_check=[6, 8, 10])

frame_count = 0
while cap.isOpened():
    success, im0 = cap.read()
    if not success:
      print("Video frame is empty or video processing has been successfully completed.")
      break
    frame_count += 1
    results = model.track(im0, verbose=False)  # Tracking recommended
    #results = model.predict(im0)  # Prediction also supported
    im0 = gym_object.start_counting(im0, results, frame_count)

cv2.destroyAllWindows()
from ultralytics import YOLO
from ultralytics.solutions import ai_gym
import cv2

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

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

gym_object = ai_gym.AIGym()  # init AI GYM module
gym_object.set_args(line_thickness=2,
                    view_img=True,
                    pose_type="pushup",
                    kpts_to_check=[6, 8, 10])

frame_count = 0
while cap.isOpened():
    success, im0 = cap.read()
    if not success:
      print("Video frame is empty or video processing has been successfully completed.")
      break
    frame_count += 1
    results = model.track(im0, verbose=False)  # Tracking recommended
    #results = model.predict(im0)  # Prediction also supported
    im0 = gym_object.start_counting(im0, results, frame_count)
    video_writer.write(im0)

cv2.destroyAllWindows()
video_writer.release()
์ง€์›

"ํ‘ธ์‹œ์—…", "ํ’€์—…" ๋ฐ "๋ณต๊ทผ ์šด๋™" ์ง€์›

ํ‚คํฌ์ธํŠธ ๋งต

ํ‚คํฌ์ธํŠธ ์ฃผ๋ฌธ Ultralytics YOLOv8  ํฌ์ฆˆ

์ธ์ˆ˜ set_args

์ด๋ฆ„ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
kpts_to_check list None ํŠน์ • ์šด๋™์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ์„ธ ๊ฐ€์ง€ ํ‚คํฌ์ธํŠธ ์ธ๋ฑ์Šค ๋ชฉ๋ก๊ณผ ํ‚คํฌ์ธํŠธ ๋งต
view_img bool False ์นด์šดํŠธ๊ฐ€ ์žˆ๋Š” ํ”„๋ ˆ์ž„ ํ‘œ์‹œ
line_thickness int 2 ์นด์šดํŠธ ๊ฐ’์˜ ๋‘๊ป˜๋ฅผ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค.
pose_type str pushup ๋ชจ๋‹ˆํ„ฐ๋ง์ด ํ•„์š”ํ•œ ํฌ์ฆˆ, pullup ๊ทธ๋ฆฌ๊ณ  abworkout ๋˜ํ•œ ์ง€์›
pose_up_angle int 145 ํฌ์ฆˆ ์—… ๊ฐ๋„ ๊ฐ’
pose_down_angle int 90 ํฌ์ฆˆ ๋‹ค์šด ๊ฐ๋„ ๊ฐ’

์ธ์ˆ˜ model.predict

์ด๋ฆ„ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
source str 'ultralytics/assets' ์ด๋ฏธ์ง€ ๋˜๋Š” ๋น„๋””์˜ค์˜ ์†Œ์Šค ๋””๋ ‰ํ† ๋ฆฌ
conf float 0.25 ํƒ์ง€๋ฅผ ์œ„ํ•œ ๊ฐ์ฒด ์‹ ๋ขฐ ์ž„๊ณ„๊ฐ’
iou float 0.7 NMS์— ๋Œ€ํ•œ ๊ต์ฐจ์  ์˜ค๋ฒ„ ์œ ๋‹ˆ์˜จ(IoU) ์ž„๊ณ„๊ฐ’
imgsz int or tuple 640 ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋ฅผ ์Šค์นผ๋ผ ๋˜๋Š” (h, w) ๋ชฉ๋ก(์˜ˆ: (640, 480))์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
half bool False ๋ฐ˜์ •๋ฐ€๋„ ์‚ฌ์šฉ(FP16)
device None or str None ์‹คํ–‰ํ•  ๋””๋ฐ”์ด์Šค(์˜ˆ: CUDA ๋””๋ฐ”์ด์Šค=0/1/2/3 ๋˜๋Š” ๋””๋ฐ”์ด์Šค=CPU)
max_det int 300 ์ด๋ฏธ์ง€๋‹น ์ตœ๋Œ€ ํƒ์ง€ ํšŸ์ˆ˜
vid_stride bool False ๋น„๋””์˜ค ํ”„๋ ˆ์ž„ ์†๋„ ๋ณดํญ
stream_buffer bool False ๋ชจ๋“  ์ŠคํŠธ๋ฆฌ๋ฐ ํ”„๋ ˆ์ž„์„ ๋ฒ„ํผ๋งํ•˜๊ฑฐ๋‚˜(True) ๊ฐ€์žฅ ์ตœ๊ทผ ํ”„๋ ˆ์ž„์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค(False).
visualize bool False ๋ชจ๋ธ ๊ธฐ๋Šฅ ์‹œ๊ฐํ™”
augment bool False ์˜ˆ์ธก ์†Œ์Šค์— ์ด๋ฏธ์ง€ ์ฆ๊ฐ• ์ ์šฉ
agnostic_nms bool False ํด๋ž˜์Šค์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๋Š” NMS
classes list[int] None ํด๋ž˜์Šค๋ณ„๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: classes=0 ๋˜๋Š” classes=[0,2,3]).
retina_masks bool False ๊ณ ํ•ด์ƒ๋„ ์„ธ๋ถ„ํ™” ๋งˆ์Šคํฌ ์‚ฌ์šฉ
embed list[int] None ์ฃผ์–ด์ง„ ๋ ˆ์ด์–ด์—์„œ ํ”ผ์ฒ˜ ๋ฒกํ„ฐ/์ž„๋ฒ ๋”ฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ธ์ˆ˜ 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 ๊ฐœ์ฒด ์ถ”์  ๊ฒฐ๊ณผ ํ‘œ์‹œ


์ƒ์„ฑ 2023-12-02, ์—…๋ฐ์ดํŠธ 2024-04-18
์ž‘์„ฑ์ž: glenn-jocher (6), RizwanMunawar (1)

๋Œ“๊ธ€