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

๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง Ultralytics YOLOv8

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



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

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

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

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

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

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

import cv2

from ultralytics import YOLO, solutions

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 = solutions.AIGym(
    line_thickness=2,
    view_img=True,
    pose_type="pushup",
    kpts_to_check=[6, 8, 10],
)

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

cv2.destroyAllWindows()
import cv2

from ultralytics import YOLO, solutions

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 = solutions.AIGym(
    line_thickness=2,
    view_img=True,
    pose_type="pushup",
    kpts_to_check=[6, 8, 10],
)

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

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

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

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

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

์ธ์ˆ˜ AIGym

์ด๋ฆ„ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
kpts_to_check list None ํŠน์ • ์šด๋™์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ์„ธ ๊ฐ€์ง€ ํ‚คํฌ์ธํŠธ ์ธ๋ฑ์Šค ๋ชฉ๋ก๊ณผ ํ‚คํฌ์ธํŠธ ์ง€๋„
line_thickness int 2 ๊ทธ๋ ค์ง„ ์„ ์˜ ๋‘๊ป˜์ž…๋‹ˆ๋‹ค.
view_img bool False ํ”Œ๋ž˜๊ทธ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
pose_up_angle float 145.0 '์œ„๋กœ' ํฌ์ฆˆ์— ๋Œ€ํ•œ ๊ฐ๋„ ์ž„๊ณ„๊ฐ’์ž…๋‹ˆ๋‹ค.
pose_down_angle float 90.0 '์•„๋ž˜' ํฌ์ฆˆ์— ๋Œ€ํ•œ ๊ฐ๋„ ์ž„๊ณ„๊ฐ’์ž…๋‹ˆ๋‹ค.
pose_type str pullup ๊ฐ์ง€ํ•  ํฌ์ฆˆ ์œ ํ˜•('pullup', pushup, abworkout, squat).

์ธ์ˆ˜ model.predict

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

์ธ์ˆ˜ model.track

์ธ์ˆ˜ ์œ ํ˜• ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
source str None Specifies the source directory for images or videos. Supports file paths and URLs.
persist bool False Enables persistent tracking of objects between frames, maintaining IDs across video sequences.
tracker str botsort.yaml Specifies the tracking algorithm to use, e.g., bytetrack.yaml ๋˜๋Š” botsort.yaml.
conf float 0.3 Sets the confidence threshold for detections; lower values allow more objects to be tracked but may include false positives.
iou float 0.5 Sets the Intersection over Union (IoU) threshold for filtering overlapping detections.
classes list None Filters results by class index. For example, classes=[0, 2, 3] only tracks the specified classes.
verbose bool True Controls the display of tracking results, providing a visual output of tracked objects.

์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ

Ultralytics YOLOv8 ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด ์šด๋™์„ ์–ด๋–ป๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋‚˜์š”?

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

import cv2

from ultralytics import YOLO, solutions

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 = solutions.AIGym(
    line_thickness=2,
    view_img=True,
    pose_type="pushup",
    kpts_to_check=[6, 8, 10],
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    results = model.track(im0, verbose=False)
    im0 = gym_object.start_counting(im0, results)

cv2.destroyAllWindows()

์ถ”๊ฐ€ ์‚ฌ์šฉ์ž ์ง€์ • ๋ฐ ์„ค์ •์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…์„œ์˜ AIGym ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง์— Ultralytics YOLOv8 ์„ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ์ด์ ์ด ์žˆ๋‚˜์š”?

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง์— Ultralytics YOLOv8 ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

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

YouTube ๋™์˜์ƒ ๋ฐ๋ชจ๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ์ด์ ์ด ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜๋Š” ๋ชจ์Šต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šด๋™ ๊ฐ์ง€ ๋ฐ ์ถ”์ ์— ์žˆ์–ด์„œ Ultralytics YOLOv8 ์€ ์–ผ๋งˆ๋‚˜ ์ •ํ™•ํ•˜๋‚˜์š”?

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

์‚ฌ์šฉ์ž ์ง€์ • ์šด๋™ ๋ฃจํ‹ด์— Ultralytics YOLOv8 ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

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

from ultralytics import solutions

gym_object = solutions.AIGym(
    line_thickness=2,
    view_img=True,
    pose_type="squat",
    kpts_to_check=[6, 8, 10],
)

์ธ์ˆ˜ ์„ค์ •์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ธ์ˆ˜ AIGym ์„น์…˜์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์œ ์—ฐ์„ฑ์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์šด๋™์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ๋ฃจํ‹ด์„ ์‚ฌ์šฉ์ž ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Ultralytics YOLOv8 ์„ ์‚ฌ์šฉํ•˜์—ฌ ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง ์ถœ๋ ฅ์„ ์ €์žฅํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋‚˜์š”?

์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง ์ถœ๋ ฅ์„ ์ €์žฅํ•˜๋ ค๋ฉด ์ฒ˜๋ฆฌ๋œ ํ”„๋ ˆ์ž„์„ ์ €์žฅํ•˜๋Š” ๋น„๋””์˜ค ์ž‘์„ฑ๊ธฐ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

import cv2

from ultralytics import YOLO, solutions

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 = solutions.AIGym(
    line_thickness=2,
    view_img=True,
    pose_type="pushup",
    kpts_to_check=[6, 8, 10],
)

while cap.isOpened():
    success, im0 = cap.read()
    if not success:
        print("Video frame is empty or video processing has been successfully completed.")
        break
    results = model.track(im0, verbose=False)
    im0 = gym_object.start_counting(im0, results)
    video_writer.write(im0)

cv2.destroyAllWindows()
video_writer.release()

์ด ์„ค์ •์€ ๋ชจ๋‹ˆํ„ฐ๋ง๋œ ๋™์˜์ƒ์„ ์ถœ๋ ฅ ํŒŒ์ผ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ถœ๋ ฅ ์ €์žฅ์„ ํ†ตํ•œ ์šด๋™ ๋ชจ๋‹ˆํ„ฐ๋ง ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.


9๊ฐœ์›” ์ „ ์ƒ์„ฑ๋จ โœ๏ธ 3 ์ผ ์ „ ์—…๋ฐ์ดํŠธ ๋จ

๋Œ“๊ธ€