Skip to content

Latest commit

ย 

History

History
193 lines (142 loc) ยท 9.51 KB

README.md

File metadata and controls

193 lines (142 loc) ยท 9.51 KB

๐Ÿ“บ ๋™์˜์ƒ ๋ณด๊ธฐ ๐ŸŽฌ

๐Ÿ”— ๋ธ”๋กœ๊ทธ ํ”„๋กœ์ ํŠธ ๋งํฌ ๐ŸŒ

ciga

Cigarette Detection yolo

README - YOLOv8 ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ๊ฐ์ฒด ํƒ์ง€ ๋ฐ ์•Œ๋ฆผ ์‹œ์Šคํ…œ


1. ๊ฐœ์š”

์ด ํ”„๋กœ์ ํŠธ๋Š” YOLOv8 (You Only Look Once version 8) ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ํŠน์ • ๊ฐ์ฒด (์˜ˆ: ๋‹ด๋ฐฐ)๊ฐ€ ํƒ์ง€๋˜์—ˆ์„ ๋•Œ ์•Œ๋ฆผ ์†Œ๋ฆฌ๋ฅผ ์šธ๋ฆฌ๋„๋ก ๊ตฌํ˜„ํ•œ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ OpenCV, Ultralytics YOLO, ๊ทธ๋ฆฌ๊ณ  pygame ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์›น์บ ์—์„œ ์‹ค์‹œ๊ฐ„ ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์„ ์บก์ฒ˜ํ•˜๊ณ , ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ํƒ์ง€๋œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์‹œ๊ฐ์  ํ‘œ์‹œ ๋ฐ ์†Œ๋ฆฌ ์•Œ๋ฆผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ด ์‹œ์Šคํ…œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค:

  • YOLOv8 ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•œ ๊ฐ์ฒด ํƒ์ง€
  • ์›น์บ  ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ์˜์ƒ ์ž…๋ ฅ
  • ์•Œ๋ฆผ ์†Œ๋ฆฌ: ํŠน์ • ๊ฐ์ฒด(์˜ˆ: ๋‹ด๋ฐฐ)๊ฐ€ ํƒ์ง€๋˜๋ฉด ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒ
  • ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ: ์•Œ๋ฆผ ์†Œ๋ฆฌ์™€ ๊ฐ์ฒด ํƒ์ง€ ์ฒ˜๋ฆฌ ๋ถ„๋ฆฌ

2. ์ฃผ์š” ๊ธฐ๋Šฅ

  1. YOLOv8 ๋ชจ๋ธ๋กœ ์‹ค์‹œ๊ฐ„ ๊ฐ์ฒด ํƒ์ง€:

    • ์›น์บ ์—์„œ ์ž…๋ ฅ๋œ ์˜์ƒ์„ YOLOv8 ๋ชจ๋ธ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ํƒ์ง€ํ•ฉ๋‹ˆ๋‹ค.
    • ํƒ์ง€๋œ ๊ฐ์ฒด๋Š” Bounding Box์™€ ํ•จ๊ป˜ ํ™”๋ฉด์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  2. ์•Œ๋ฆผ ์†Œ๋ฆฌ:

    • ํŠน์ • ๊ฐ์ฒด(์˜ˆ: ๋‹ด๋ฐฐ)๊ฐ€ ํƒ์ง€๋˜๋ฉด ์•Œ๋ฆผ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•ฉ๋‹ˆ๋‹ค.
    • ์†Œ๋ฆฌ๋Š” pygame ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ์ƒ๋˜๋ฉฐ, ์†Œ๋ฆฌ๊ฐ€ ๋ฐ˜๋ณต๋˜์ง€ ์•Š๋„๋ก ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  3. ์Šค๋ ˆ๋“œ๋ฅผ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ ์†Œ๋ฆฌ ์žฌ์ƒ:

    • ์†Œ๋ฆฌ ์žฌ์ƒ์€ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋˜์–ด, ๊ฐ์ฒด ํƒ์ง€์™€ ๋™์‹œ์— ์†Œ๋ฆฌ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ์žฌ์ƒ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.
  4. ์‹ค์‹œ๊ฐ„ ์›น์บ  ์ŠคํŠธ๋ฆฌ๋ฐ:

    • OpenCV๋ฅผ ์ด์šฉํ•˜์—ฌ ์›น์บ ์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์˜์ƒ์„ ์บก์ฒ˜ํ•˜๊ณ , ์ด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

3. ๋™์ž‘ ์›๋ฆฌ

์ด ์‹œ์Šคํ…œ์€ ๋‘ ์ฃผ์š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ‘ํ–‰ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค: ๊ฐ์ฒด ํƒ์ง€์™€ ์†Œ๋ฆฌ ์žฌ์ƒ. ์ „์ฒด ์‹œ์Šคํ…œ์˜ ๋™์ž‘ ํ๋ฆ„์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. YOLOv8 ๋ชจ๋ธ ๋กœ๋“œ:

    • ํ•™์Šต๋œ YOLOv8 ๋ชจ๋ธ ํŒŒ์ผ(trained_model.pt)์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ๋ชจ๋ธ์€ ์›น์บ ์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์บก์ฒ˜๋œ ์ด๋ฏธ์ง€์—์„œ ๊ฐ์ฒด๋ฅผ ํƒ์ง€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  2. ์›น์บ  ์˜์ƒ ์บก์ฒ˜:

    • cv2.VideoCapture(0)์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ(Webcam)์—์„œ ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    • ๊ฐ ํ”„๋ ˆ์ž„์„ YOLOv8 ๋ชจ๋ธ์— ์ „๋‹ฌํ•˜์—ฌ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ฐ์ฒด ํƒ์ง€ ๋ฐ ์•Œ๋ฆผ ์†Œ๋ฆฌ ์žฌ์ƒ:

    • YOLOv8 ๋ชจ๋ธ์€ ๊ฐ์ฒด๋ฅผ ํƒ์ง€ํ•˜์—ฌ Bounding Box๋ฅผ ์ด๋ฏธ์ง€์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.
    • ํƒ์ง€๋œ ๊ฐ์ฒด๊ฐ€ 'cigarette'๋ผ๋ฉด ์•Œ๋ฆผ ์†Œ๋ฆฌ(alert_sound.mp3)๊ฐ€ ์žฌ์ƒ๋ฉ๋‹ˆ๋‹ค.
    • ์†Œ๋ฆฌ๋Š” pygame.mixer.music์„ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ์ƒ๋˜๋ฉฐ, ์†Œ๋ฆฌ ์žฌ์ƒ ์—ฌ๋ถ€๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  4. ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ ์ถœ๋ ฅ:

    • ๊ฐ์ฒด ํƒ์ง€ ๊ฒฐ๊ณผ(ํƒ์ง€๋œ ํด๋ž˜์Šค ๋ฐ ํ•ด๋‹น ์œ„์น˜)๋Š” Bounding Box ํ˜•ํƒœ๋กœ ์‹ค์‹œ๊ฐ„ ๋น„๋””์˜ค์— ์˜ค๋ฒ„๋ ˆ์ด๋ฉ๋‹ˆ๋‹ค.
    • ํƒ์ง€๋œ ๊ฐ์ฒด๊ฐ€ ์—†๋‹ค๋ฉด, ํƒ์ง€๋˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ๋น„๋””์˜ค๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

4. ์ฝ”๋“œ ๋ถ„์„

4.1. ๋ชจ๋ธ ๋กœ๋“œ ๋ฐ ์›น์บ  ์„ค์ •
# YOLOv8 ๋ชจ๋ธ ๋กœ๋“œ (ํ•™์Šตํ•œ ๋ชจ๋ธ ํŒŒ์ผ ๊ฒฝ๋กœ)
model = YOLO('trained_model.pt')

# ์›น์บ  ์—ด๊ธฐ (๊ธฐ๋ณธ ์นด๋ฉ”๋ผ 0๋ฒˆ ์‚ฌ์šฉ)
cap = cv2.VideoCapture(0)
  • YOLO('trained_model.pt'): YOLOv8 ๋ชจ๋ธ์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ์ž์‹ ์ด ํ•™์Šตํ•œ ๊ฐ์ฒด ์ธ์‹ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • cv2.VideoCapture(0): OpenCV๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ์›น์บ ์—์„œ ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์„ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค.
4.2. ์•Œ๋ฆผ ์†Œ๋ฆฌ ์ฒ˜๋ฆฌ
# ์•Œ๋ฆผ ์†Œ๋ฆฌ ํŒŒ์ผ ๊ฒฝ๋กœ (์†Œ๋ฆฌ ํŒŒ์ผ์„ ํ”„๋กœ์ ํŠธ ํด๋”์— ๋„ฃ๊ณ  ์‚ฌ์šฉ)
alert_sound = 'alert_sound.mp3'

# pygame ์ดˆ๊ธฐํ™”
pygame.mixer.init()

# ์†Œ๋ฆฌ ์žฌ์ƒ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜
def play_alert_sound():
    while True:
        pygame.mixer.music.load(alert_sound)
        pygame.mixer.music.play()
        print("์†Œ๋ฆฌ ์žฌ์ƒ๋จ!")  # ์†Œ๋ฆฌ ์žฌ์ƒ ์‹œ ์ถœ๋ ฅ
        time.sleep(1)  # ๋„ˆ๋ฌด ์ž์ฃผ ๋ฐ˜๋ณต๋˜์ง€ ์•Š๋„๋ก ์ž ์‹œ ๋Œ€๊ธฐ

# ์†Œ๋ฆฌ ์žฌ์ƒ์„ ์œ„ํ•œ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
alert_thread = threading.Thread(target=play_alert_sound, daemon=True)
alert_thread.start()
  • pygame.mixer.init(): pygame์˜ ๋ฏน์„œ ๋ชจ๋“ˆ์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ์†Œ๋ฆฌ ํŒŒ์ผ์„ ์žฌ์ƒํ•  ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.
  • play_alert_sound(): ์•Œ๋ฆผ ์†Œ๋ฆฌ๋ฅผ ๋ฌดํ•œ ๋ฐ˜๋ณตํ•˜์—ฌ ์žฌ์ƒํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์†Œ๋ฆฌ๊ฐ€ ์žฌ์ƒ๋  ๋•Œ๋งˆ๋‹ค 1์ดˆ ๊ฐ„๊ฒฉ์„ ๋‘๊ณ  ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค.
  • threading.Thread(target=play_alert_sound, daemon=True): ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ๋ฆฌ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด ํƒ์ง€์™€ ์†Œ๋ฆฌ ์žฌ์ƒ์ด ๋™์‹œ์— ์ด๋ฃจ์–ด์งˆ ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
4.3. ๊ฐ์ฒด ํƒ์ง€ ๋ฐ ์†Œ๋ฆฌ ์•Œ๋ฆผ
# YOLOv8 ๋ชจ๋ธ๋กœ ๊ฐ์ฒด ํƒ์ง€
results = model(frame)

# ๊ฒฐ๊ณผ์—์„œ ํƒ์ง€๋œ ๊ฐ์ฒด ํ™•์ธ
cigarette_detected = False

# results.pred[0]๋Š” YOLO ๋ชจ๋ธ์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ ํƒ์ง€ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค
for result in results[0].boxes:
    class_id = int(result.cls.item())  # ๊ฒฐ๊ณผ ํด๋ž˜์Šค ID ์ถ”์ถœ
    if model.names[class_id] == 'cigarette':  # 'cigarette' ํด๋ž˜์Šค๊ฐ€ ํƒ์ง€๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
        cigarette_detected = True
        break
  • results = model(frame): ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž…๋ ฅ๋œ frame์—์„œ ๊ฐ์ฒด ํƒ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • results[0].boxes: ํƒ์ง€๋œ ๊ฐ์ฒด๋“ค์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๊ฐ ๊ฐ์ฒด๋Š” ํด๋ž˜์Šค ID์™€ ๊ฒฝ๊ณ„ ์ƒ์ž ์ขŒํ‘œ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • if model.names[class_id] == 'cigarette': ํƒ์ง€๋œ ๊ฐ์ฒด๊ฐ€ 'cigarette'์ธ์ง€ ํ™•์ธํ•˜๊ณ , ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๋ฐœ๊ฒฌ๋˜๋ฉด cigarette_detected๋ฅผ True๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
4.4. ์†Œ๋ฆฌ ์žฌ์ƒ ์ œ์–ด
if cigarette_detected:
    print("Cigarette detected!")  # ํƒ์ง€ ์‹œ ์ถœ๋ ฅ
    if not is_playing:  # ์†Œ๋ฆฌ๊ฐ€ ์žฌ์ƒ ์ค‘์ด ์•„๋‹ˆ๋ฉด
        pygame.mixer.music.set_volume(1.0)  # ๋ณผ๋ฅจ์„ ์ตœ๋Œ€๊ฐ’์œผ๋กœ ์„ค์ •
        is_playing = True
else:
    print("No cigarette detected!")  # ํƒ์ง€๋˜์ง€ ์•Š์œผ๋ฉด ์ถœ๋ ฅ
    pygame.mixer.music.set_volume(0.0)  # ๋ณผ๋ฅจ์„ 0์œผ๋กœ ์„ค์ •
    is_playing = False
  • pygame.mixer.music.set_volume(1.0): ๋‹ด๋ฐฐ๊ฐ€ ํƒ์ง€๋œ ๊ฒฝ์šฐ ์•Œ๋ฆผ ์†Œ๋ฆฌ๋ฅผ ์ตœ๋Œ€ ๋ณผ๋ฅจ์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์žฌ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • pygame.mixer.music.set_volume(0.0): ๋‹ด๋ฐฐ๊ฐ€ ํƒ์ง€๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์†Œ๋ฆฌ๋ฅผ ์Œ์†Œ๊ฑฐ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
4.5. ์‹ค์‹œ๊ฐ„ ์›น์บ  ์ถœ๋ ฅ
# ํƒ์ง€๋œ ๊ฒฐ๊ณผ๋ฅผ ์˜์ƒ์— ํ‘œ์‹œ
annotated_frame = results[0].plot()  # ํƒ์ง€๋œ ๊ฐ์ฒด ํ‘œ์‹œ

# ์‹ค์‹œ๊ฐ„ ์›น์บ  ์˜์ƒ ์ถœ๋ ฅ
cv2.imshow('Webcam Feed', annotated_frame)
  • results[0].plot(): ํƒ์ง€๋œ ๊ฐ์ฒด์— ๋Œ€ํ•œ Bounding Box๋ฅผ ๊ทธ๋ ค์„œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • cv2.imshow('Webcam Feed', annotated_frame): ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฒ˜๋ฆฌ๋œ ํ”„๋ ˆ์ž„์„ ํ™”๋ฉด์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

5. ์ข…๋ฃŒ ๋ฐ ๋ฆฌ์†Œ์Šค ํ•ด์ œ

# ์›น์บ  ๋ฐ ์ฐฝ ๋‹ซ๊ธฐ
cap.release()
cv2.destroyAllWindows()
  • cap.release(): ์›น์บ  ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
  • cv2.destroyAllWindows(): OpenCV ์ฐฝ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.

6. ๊ฒฐ๋ก 

์ด ์‹œ์Šคํ…œ์€ YOLOv8 ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ์ฒด๋ฅผ ํƒ์ง€ํ•˜๊ณ , ํŠน์ • ๊ฐ์ฒด๊ฐ€ ํƒ์ง€๋˜๋ฉด ์•Œ๋ฆผ ์†Œ๋ฆฌ๋ฅผ ์žฌ์ƒํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๊ฐ์ฒด ํƒ์ง€ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. pygame๊ณผ threading์„ ํ™œ์šฉํ•˜์—ฌ ์†Œ๋ฆฌ ์žฌ์ƒ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ , OpenCV๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์›น์บ  ์˜์ƒ์— ํƒ์ง€ ๊ฒฐ๊ณผ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. confusion_matrix_normalized confusion_matrix val_batch2_pred val_batch2_labels val_batch1_pred val_batch1_labels val_batch0_pred val_batch0_labels train_batch2 train_batch1 train_batch0 results results.csv R_curve PR_curve P_curve labels_correlogram labels F1_curve