์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ

[FIRECLIP AI] ๊ฐ„๋‹จํ•œ ํด๋ฆฝ ์˜์ƒ ํ™”์žฌ ํƒ์ง€ ์›น ์„œ๋น„์Šค ์ˆ˜ํ–‰ ๊ณ„ํš์„œ (+์‹ค์ œ ์ง„ํ–‰) - ์ž‘์„ฑ ์ค‘

kaizen_bh 2025. 5. 6. 13:34

 

 

 

์˜ฌํ•ด 3์›”๋ถ€ํ„ฐ 5์›”๊นŒ์ง€ ๋“ฃ๋Š” ICT ์ด๋…ธ๋ฒ ์ด์…˜ ์Šคํ€˜์–ด ์ธ๊ณต์ง€๋Šฅ ๋น„์ „์ปดํ“จํŒ… ๊ณผ์ •์—์„œ ๋งˆ์ง€๋ง‰ 2์ฃผ๊ฐ„ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ์‹œ๊ฐ„์ด ์žˆ๋‹ค

 

์–ด๋–ค๊ฑธ ํ•ด๋ณด๋ฉด ์ข‹์„๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์ด์ „ ์—…๋ฌด์—์„œ ๋งก์•˜๋˜ ํ™”์žฌ ํƒ์ง€๋ฅผ ์›น์— ์˜ฌ๋ ค๋ณด๊ณ  ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ๊ฒฝํ—˜ํ•ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค ์‹ถ์–ด์„œ ์›น์— ์งง์€ ํ™”์žฌ ํด๋ฆฝ ์˜์ƒ์„ ์—…๋กœ๋“œํ•˜๋ฉด ํƒ์ง€ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฐ„๋‹จํ•œ AI๋ฅผ ์–ป์€ ์›น์„ ๋งŒ๋“ค์–ด๋ณด๊ธฐ๋กœ ํ•˜์˜€๋‹ค

์›น, ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ ๋ถ€๋ถ„์€ ์ „ํ˜€ ๋‹ค๋ค„๋ณธ ์ ์ด ์—†์—ˆ๊ธฐ์— ์‚ฝ์งˆ์„ ๋งŽ์ด ํ•˜๊ณ  ์žˆ๋‹ค

 

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด 2๊ฐ€์ง€ ๋ฌธ์„œ๊ฐ€ ๋‚˜์™€์•ผ ํ•œ๋‹ค. ๋ฐ”๋กœ ์ˆ˜ํ–‰ ๊ณ„ํš์„œ (๊ธฐํš์•ˆ) ๋ฐ ๊ฒฐ๊ณผ ๋ณด๊ณ ์„œ

์ด๋ฒˆ ๊ธ€์—์„  ๋จผ์ € ์ „์ฒด์ ์ธ ๊ณ„ํš์„ ๋จผ์ € ์„ธ์›Œ๋ณด๊ณ  ์‹ค์ œ๋กœ ๊ณ„ํš๋Œ€๋กœ ์ง„ํ–‰๋˜์—ˆ๋Š”์ง€, ์ง„ํ–‰ํ•˜๋ฉด์„œ ์–ด๋А ๋ถ€๋ถ„์ด ๋ง‰ํ˜”๊ณ  ์–ด๋–ค ์ด์Šˆ๋“ค์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€, ๊ณ„ํš์„ ์กฐ์ •ํ•˜์—ฌ ์–ด๋””๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ–ˆ๋Š”์ง€ ๋“ฑ ๊ณ„ํš๊ณผ ์‹ค์ œ ์ง„ํ–‰ ๋‚ด์šฉ์„ ๋น„๊ตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค

์ˆ˜์—… ๋‚ด์šฉ ๋ฐ ์ž๋ฃŒ๋“ค์„ ๋ฒ ์ด์Šค๋กœ ํ•˜์—ฌ ๊ธฐ์ค€ ์‚ผ๊ณ  ์›ํ•˜๋Š” ๋ฐฉํ–ฅ์„ฑ์— ๋งž๊ฒŒ ์ปค์Šคํ…€ํ•˜๋Š” ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜์˜€๋‹ค

์ด ๊ณ„ํš์„œ์™€ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋‚จ๊ธด ๊ธฐ๋ก๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ฒฐ๊ณผ ๋ณด๊ณ ์„œ (PPT ํ˜•ํƒœ์˜ ๋ฐœํ‘œ์ž๋ฃŒ or docx ๋ฌธ์„œ) ๋ฅผ ์ •๋ฆฌํ•ด์„œ 2๋ฒˆ์งธ ๊ธ€๋กœ ์˜ฌ๋ฆด ์˜ˆ์ •์ด๋‹ค

 

์ง€๊ธˆ ์ ์€ ๊ณ„ํš๋“ค์€ ๊ฑฐ์ฐฝํ–ˆ์œผ๋‚˜..(๋‚ด ๊ธฐ์ค€) ๋ง‰์ƒ ํ•ด๋ณด๋‹ˆ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„๋“ค์ด ์ •๋ง ๋งŽ์•˜๋‹ค

 

 

 


 

 

๐Ÿ“Œ ํ”„๋กœ์ ํŠธ๋ช…

FireClip AI: ํด๋ฆฝ ์˜์ƒ ๊ธฐ๋ฐ˜ ํ™”์žฌ ํƒ์ง€ ์›น์„œ๋น„์Šค

 

 

๐ŸŽฏ 1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

ํ•ญ๋ชฉ ๋‚ด์šฉ
๋ชฉํ‘œ ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•œ ์‹ค๋‚ด CCTV ํด๋ฆฝ ์˜์ƒ์—์„œ ์—ฐ๊ธฐ ๋˜๋Š” ๋ถˆ๊ฝƒ์„ ์ž๋™ ํƒ์ง€ํ•˜๊ณ , ํƒ์ง€๋œ ๊ฒฐ๊ณผ(๋ฐ”์šด๋”ฉ๋ฐ•์Šค)๋ฅผ ๊ทธ๋ฆฐ ์˜์ƒ์œผ๋กœ ์›นํŽ˜์ด์ง€์— ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ๋Ÿ‰ ์›น์„œ๋น„์Šค ๊ตฌํ˜„
๊ธฐ์ˆ  ์Šคํƒ GCP, Flask, MongoDB, YOLO, OpenCV

 

 

 


๐Ÿงฑ 2. ๋ฐ์ดํ„ฐ ๊ตฌ์ถ• ๋ฐ ๋ชจ๋ธ ํ•™์Šต 

 

ํ•ญ๋ชฉ ๋‚ด์šฉ
์‚ฌ์šฉ ๋ฐ์ดํ„ฐ ํ˜•์‹ CCTV ํ˜•์‹์˜ ํด๋ฆฝ ์˜์ƒ ๋ฐ ์ด๋ฏธ์ง€
๋ผ๋ฒจ ํ•ญ๋ชฉ ์ˆ˜ ์—ฐ๊ธฐ/๋ถˆ๊ฝƒ 2๊ฐœ ํด๋ž˜์Šค ํฌํ•จ
๊ตฌ์ถ• ์ „๋žต (์ˆ˜์ง‘ ๊ฒฝ๋กœ) โœ… ๊ณต๊ฐœ ํ™”์žฌ/์—ฐ๊ธฐ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์…‹ ํ™œ์šฉ (AIhub, kaggle, Roboflow)
โœ… ํ•„์š”์‹œ ํฌ๋กค๋ง ๋˜๋Š” YouTube ํด๋ฆฝ์œผ๋กœ ๋ณด์™„
โœ… ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๋ฐ YOLO ํฌ๋งท์œผ๋กœ ๋ผ๋ฒจ๋ง

์ˆ˜์ง‘๋Ÿ‰ ์ตœ์†Œ 1000์žฅ ์ด๋ฏธ์ง€ (๋ผ๋ฒจ ํฌํ•จ)
์ด๋ฏธ์ง€ ํ•ด์ƒ๋„ 640×480 ~ 1920×1280 (1280x1080 ์ด์ƒ ๊ถŒ์žฅ)
๋ฐ์ดํ„ฐ๋‹น ํ‰๊ท  ์šฉ๋Ÿ‰ ์•ฝ 500 ~ 1,000KB
๋ผ๋ฒจ๋ง ๋„๊ตฌ Roboflow
๋ชจ๋ธ ์‚ฌ์šฉ ์ „๋žต ๐Ÿ“Œ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์„ ํƒ
โ‘  ์‚ฌ์ „ ํ•™์Šต๋œ YOLOv8 ๋ถˆ๊ฝƒ/์—ฐ๊ธฐ ๋ชจ๋ธ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
โ‘ก ๊ฒฝ๋Ÿ‰ ์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ๋กœ ํŒŒ์ธํŠœ๋‹

 

 

๐Ÿงฑ 2-1. ๋ผ๋ฒจ๋ง ๊ธฐ์ค€ ๋ฐ ํ’ˆ์งˆ ๊ด€๋ฆฌ

ํ•ญ๋ชฉ  ๊ธฐ์ค€
๋ฐ”์šด๋”ฉ ๋ฐ•์Šค ์ตœ์†Œ ํฌํ•จ ์˜์—ญ, ํด๋ž˜์Šค๋ช… ํฌํ•จ
๋ถ„๋ฅ˜ ๋ผ๋ฒจ ๊ณ ์œ  ํด๋ž˜์Šค ID + ์„ค๋ช…
๊ฒ€์ˆ˜ ์ƒ˜ํ”Œ ๊ฒ€์ˆ˜ 20%
  • ์ €์žฅ ๋ฐ ๊ด€๋ฆฌ
    • ํ˜•์‹: YOLO TXT
    • ์ €์žฅ์†Œ: Google Drive
    • ๊ด€๋ฆฌํˆด: Roboflow
  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ๊ณ„ํš
    • Noise, saturation, hue, hori flip, brightness

 

๐Ÿ’ป ์ผ๋ฐ˜ํ™” ์„ฑ๋Šฅ ๊ฒ€ํ† 

  • ํ•™์Šต๋ฐ์ดํ„ฐ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ํƒ์ง€ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ 20์žฅ ์ด์ƒ์— ๋Œ€ํ•œ ํƒ์ง€๋Šฅ๋ ฅ ํ‰๊ฐ€
  • mAP ์„ฑ๋Šฅ์„ ์‚ฐ์ถœํ•˜์—ฌ 0.7 ์ด์ƒ์ด ๋˜๋„๋ก ํ•™์Šต ๋ฐ์ดํ„ฐ ์กฐ์ •

 

๐Ÿงฑ 2-2. ๋ฐ์ดํ„ฐ ๊ตฌ์ถ• ์ง„ํ–‰

์‚ฌ์šฉ ๋ฐ์ดํ„ฐ Roboflow,  AIํ—ˆ๋ธŒ,  Kaggle
๋ผ๋ฒจ๋ง ํˆด Roboflow

 

์‹ค์ œ CCTV์™€ ์œ ์‚ฌํ•œ 720p (1280 x 720) / 1080p(1920 x 1080 ) ํฌ๊ธฐ๋ฅผ ๊ฐ€์ง„ ์‹ค๋‚ด์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ตฌํ•˜๊ธฐ๋Š” ์‰ฝ์ง€ ์•Š์Œ

  • ํŠนํžˆ CCTV ํ™”์žฌ ์ด๋ฏธ์ง€๋Š” ๋”๋”์šฑ ๊ตฌํ•˜๊ธฐ ์–ด๋ ต๋‹ค (๋ณด์•ˆ ๊ด€๋ จ ์ด์Šˆ ๋“ฑ ๊ณต์œ  ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋‹ค์ˆ˜)
  • Roboflow Kaggle ์—์„œ ๊ตฌํ•œ ์ด๋ฏธ์ง€๋“ค์€ ํ™”์งˆ์ด ๋‚ฎ์€ ์นด๋ฉ”๋ผ๋กœ ์ฐํžŒ ์˜์ƒ๋“ค์„ 640x640 ํฌ๊ธฐ๋กœ ๋ฆฌ์‚ฌ์ด์ฆˆํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„ ์ด๋ฏธ์ง€์˜ ํ€„๋ฆฌํ‹ฐ๊ฐ€ ๋งŽ์ด ๋–จ์–ด์ง
  • AIHub์˜ ๊ฒฝ์šฐ 1920x1080 ํฌ๊ธฐ์˜ ๊ณ ํ™”์งˆ ์ด๋ฏธ์ง€์ด์ง€๋งŒ ์•ผ์™ธ ์ดฌ์˜ ์ด๋ฏธ์ง€

1์ฐจ ๋ฐ์ดํ„ฐ์…‹ 

730์žฅ ๋ผ๋ฒจ๋ง ๋ฐ ์ด๋ฏธ์ง€ ์ฆ๊ฐ• ์ ์šฉ ํ›„ ์ด 1810์žฅ

 

ํด๋ž˜์Šค๋ณ„ ๊ฐ์ฒด ๊ฐœ์ˆ˜

  • fire : 894 ๊ฐœ
  • smoke : 250 ๊ฐœ

Preprocessing

  • Auto-Orient: Applied
  • Resize: Stretch to 640x640

Augmentations

  • Outputs per training example: 3
  • 90° Rotate: Clockwise, Counter-Clockwise, Upside Down
  • Saturation: Between -25% and +25%
  • Brightness: Between -15% and +15%
  • Blur: Up to 2.5px
  • Noise: Up to 0.1% of pixels

๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

  • Train Set : 90%, 1620 ์žฅ
  • Valid Set : 8%, 146์žฅ
  • Test Set : 2%, 44์žฅ

 


 

 

 

2์ฐจ ๋ฐ์ดํ„ฐ์…‹ 

280์žฅ ์ถ”๊ฐ€ ๋ผ๋ฒจ๋ง ๋ฐ ์ด๋ฏธ์ง€ ์ฆ๊ฐ• ์ ์šฉ ํ›„ ์ด 2524์žฅ

 

ํด๋ž˜์Šค๋ณ„ ๊ฐ์ฒด ๊ฐœ์ˆ˜

  • fire : 1,134 ๊ฐœ
  • smoke : 518 ๊ฐœ

Preprocessing

  • Auto-Orient: Applied
  • Resize: Stretch to 640x640

Augmentations

  • Outputs per training example: 3
  • 90° Rotate: Clockwise, Counter-Clockwise, Upside Down
  • Saturation: Between -25% and +25%
  • Brightness: Between -15% and +15%
  • Blur: Up to 2.5px
  • Noise: Up to 0.1% of pixels
  • Shear: ±10° Horizontal, ±10° Vertical

๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

  • Train Set : 91%, 2286 ์žฅ
  • Valid Set : 7%, 187์žฅ
  • Test Set : 2%, 51์žฅ

 

 

๋ฐ์ดํ„ฐ ์ถœ์ฒ˜

 

 

 


 

 

๐Ÿงฑ 2-3. ๋ชจ๋ธ ํ•™์Šต ๊ฒฐ๊ณผ

 

ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ ๋ฐ ๋ชจ๋ธ ํŠœ๋‹

ํ™˜๊ฒฝ : Colab 

 

 

์ผ๋ฐ˜ ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ

from ultralytics import YOLO

# ๋ชจ๋ธ ์ดˆ๊ธฐํ™” (๊ฐ€๋ณ๊ฒŒ ์‹œ์ž‘: yolov8n.pt)
model = YOLO('yolov8n.pt')  # ๋˜๋Š” yolov8s.pt, yolov8m.pt ๋“ฑ

# ํ•™์Šต ์‹œ์ž‘
model.train(
    data='/content/data/data.yaml',
    epochs=50,
    imgsz=640,
    batch=16,
    project='yolov8_fire_detection',
    name='exp',
    exist_ok=True
)

 

  • 1,2์ฐจ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ํ•™์Šต
  • ๋” ๋‹ค์–‘ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์œผ๋กœ ์ž๋™์œผ๋กœ ์ตœ์ ์˜ ์กฐํ•ฉ ์ฐพ๋„๋ก wandb์˜ sweep ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์˜ˆ์ •

 

 

 

 

Wandb Sweep๋กœ ๋ชจ๋ธ ์ž๋™ ํŠœ๋‹

!pip install -U ultralytics
!wandb login <api key>
!yolo settings wandb=True

import wandb
from wandb.integration.ultralytics import add_wandb_callback
from ultralytics import YOLO

# ํ”„๋กœ์ ํŠธ๋ช… ์ง€์ • (์ž๋™ ์ƒ์„ฑ๋„ ๊ฐ€๋Šฅ)
wandb.init(project="fire_clip_project", job_type='training')
  • wandb ์—ฐ๊ฒฐ ๋ฐ sweep ์„ค์ •

 

sweep_config = {
    'method': 'random',
    'metric': {'goal': 'maximize', 'name': 'metrics/mAP50-95(B)'},
    'parameters': {
        'batch_size': {'values': [16, 32, 64]},
        'learning_rate': {
            'distribution': 'uniform',
            'min':0.0001,
            'max':0.001
            }
    }
}
  • ํŠœ๋‹ํ•  ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์ง€์ •
  • mAP50-95๊ฐ€ ์ตœ๋Œ€ํ™”๋˜๋Š” ๊ฒƒ์„ ๊ธฐ์ค€์œผ๋กœ ์‚ผ์Œ
  • ๋ฐฐ์น˜ ์‚ฌ์ด์ฆˆ์™€ ํ•™์Šต๋ฅ ์„ ์—ฌ๋Ÿฌ ์กฐํ•ฉ๋ณ„๋กœ ํ•™์Šต ์ง„ํ–‰
  • ์ด ์™ธ์—๋„ ๋” ๋งŽ์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
  • sweep config ์„ค์ • ํ›„ ํ•™์Šต ๋Œ๋ฆฌ๋ฉด ์กฐํ•ฉ๋“ค์„ ์ž๋™์œผ๋กœ ํ•™์Šต ๋ฐ wandb์— ์„ฑ๋Šฅ ๋กœ๊น…

 

 

sweep_id = wandb.sweep(sweep=sweep_config, project='fire_clip_project')

def yolo_train():
    with wandb.init() as run:
        config = wandb.config

        # ๋ชจ๋ธ ์ •์˜ ๋ฐ ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ
        model = YOLO('yolov8n.pt')
        add_wandb_callback(model, enable_model_checkpointing=True)
        results = model.train(
            data='/content/data/data.yaml',
            name='exp3',
            plots=True,
            batch=config.batch_size,
            epochs=50,
            imgsz=640,
            cos_lr=True,
            lrf=0.01,
            lr0=config.learning_rate,
            project='yolov8_fire_detection'
        )

        metrics = results.metrics

        wandb.log({
            'epoch': 50,  # ๋˜๋Š” run.step ๋“ฑ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
            'val_loss': results.loss,  # ๋˜๋Š” ๋‹ค๋ฅธ ์ ์ ˆํ•œ loss ์‚ฌ์šฉ
            'metrics/mAP50': metrics.get('metrics/mAP50(B)', None),
            'metrics/mAP50-95': metrics.get('metrics/mAP50-95(B)', None)
        })

 

 

 

 

 

 

 

 

 

์„ฑ๋Šฅ ๋น„๊ต

์„ฑ๋Šฅ์ง€ํ‘œ recall(B) precision(B) mAP50(B) mAP50-95(B)
1์ฐจ         
2์ฐจ         

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

๐Ÿ› ๏ธ 3. ๊ตฌํ˜„ ๋ฒ”์œ„ ๋ฐ ๊ธฐ๋Šฅ ์ •์˜

๋ถ„๋ฅ˜ ๊ธฐ๋Šฅ ์„ค๋ช…
๐ŸŽฅ ์˜์ƒ ์ž…๋ ฅ 10~30์ดˆ ์˜์ƒ ํด๋ฆฝ ์—…๋กœ๋“œ (mp4) ์›น UI์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์—…๋กœ๋“œ
๐Ÿง  ํ™”์žฌ ํƒ์ง€ YOLOv8 ๊ธฐ๋ฐ˜ ์—ฐ๊ธฐ/๋ถˆ๊ฝƒ ํƒ์ง€ Flask API ๋‚ด๋ถ€์—์„œ ํ”„๋ ˆ์ž„ ์ถ”์ถœ ํ›„ ํƒ์ง€ ์ˆ˜ํ–‰
๐Ÿ–ผ๏ธ ๊ฒฐ๊ณผ ํ‘œ์‹œ ํƒ์ง€๋œ ํ”„๋ ˆ์ž„ ์ธ๋„ค์ผ + ์‹œ๊ฐ„์ •๋ณด ํ‘œ์‹œ MongoDB์— ๊ฒฐ๊ณผ ์ €์žฅ, ์›น์—์„œ ๋ชฉ๋ก ์กฐํšŒ
๐Ÿ“ ๊ฒฐ๊ณผ ์ €์žฅ ํƒ์ง€ ์ด๋ฏธ์ง€์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ ์ด๋ฏธ์ง€ ํŒŒ์ผ : GCP Cloud Storag
๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ : MongoDB

 

๐Ÿ› ๏ธ 3-1. ์‚ฌ์šฉ ๊ธฐ์ˆ  ์Šคํƒ

ํŒŒํŠธ ๊ธฐ์ˆ 
์›น ์„œ๋ฒ„ Flask (GCP Cloud Run ๋ฐฐํฌ)
DB MongoDB
ํด๋ผ์ด์–ธํŠธ HTML (+CSS)
์˜์ƒ ์ฒ˜๋ฆฌ OpenCV
ํƒ์ง€ ๋ชจ๋ธ YOLOv8s/n 
์Šคํ† ๋ฆฌ์ง€ GCP Cloud Storage

 

๐Ÿ› ๏ธ 3-2. ์ „์ฒด ๊ตฌ์กฐ

 

FireClip AI ํ”„๋กœ์ ํŠธ ์ตœ์ข… ๊ธฐํš์„œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ, ์›น์„œ๋น„์Šค์˜ ์ „์ฒด ํ๋ฆ„์„ ๊ณ ๋ คํ•œ ๋ฐฑ์—”๋“œ ๋ฐ ์›น ๊ตฌ์กฐ(์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜)

GCP + Flask + MongoDB + YOLO ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™

 

 

 

 

์‚ฌ์šฉ์ž(๋ธŒ๋ผ์šฐ์ €)
      โ”‚
      โ–ผ
[Frontend] (HTML+CSS)
  - ์˜์ƒ ์—…๋กœ๋“œ
  - ํƒ์ง€ ๊ฒฐ๊ณผ ํ™•์ธ
      โ”‚
      โ–ผ
[Flask Backend API Server] (GCP Cloud Run)
  - ์š”์ฒญ ์ฒ˜๋ฆฌ (REST API)
  - YOLOv8 ์ถ”๋ก  ์—ฐ๋™
  - Cloud Storage & MongoDB ์—ฐ๋™
      โ”‚
      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
      โ–ผ                โ–ผ                โ–ผ
[YOLOv8 Inference]   [GCS]           [MongoDB]
(๋กœ์ปฌ or Cloud)    (์˜์ƒ ์ €์žฅ)    (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ)

๐Ÿ”™ ๋ฐฑ์—”๋“œ ๊ตฌ์กฐ (Flask)

๐Ÿ”น ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

๊ธฐ๋Šฅ ์„ค๋ช…
/upload ์˜์ƒ/์ด๋ฏธ์ง€ ์—…๋กœ๋“œ API
/detect YOLO ์ถ”๋ก  ์š”์ฒญ API (์—…๋กœ๋“œ ํ›„ ๋‚ด๋ถ€ ํ˜ธ์ถœ or ์‚ฌ์šฉ์ž ์š”์ฒญ)
/results/<id> ํƒ์ง€ ๊ฒฐ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์กฐํšŒ
/list ์—…๋กœ๋“œํ•œ ์ด๋ ฅ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ API

 

๐Ÿ”น ์ฃผ์š” ์ฒ˜๋ฆฌ ํ๋ฆ„

  1. ์‚ฌ์šฉ์ž๊ฐ€ ์˜์ƒ ์—…๋กœ๋“œ (POST /upload)
  2. Flask ์„œ๋ฒ„์—์„œ GCS์— ์˜์ƒ ์ €์žฅ
  3. ์ €์žฅ๋œ ์˜์ƒ ๊ฒฝ๋กœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ YOLO ์ถ”๋ก  ์‹คํ–‰
  4. ์ถ”๋ก  ๊ฒฐ๊ณผ(ํ”„๋ ˆ์ž„ + ๋ฐ•์Šค ์ขŒํ‘œ + ํด๋ž˜์Šค)๋ฅผ ์ด๋ฏธ์ง€/์ธ๋„ค์ผ๋กœ ์ €์žฅ
  5. MongoDB์— ํ•ด๋‹น ์˜์ƒ/๊ฒฐ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ธฐ๋ก (ํŒŒ์ผ ๊ฒฝ๋กœ, ํƒ์ง€๊ฒฐ๊ณผ ๋“ฑ)
  6. ํ”„๋ก ํŠธ์—์„œ /list, /results/<id>๋ฅผ ํ†ตํ•ด ๊ฒฐ๊ณผ ์กฐํšŒ

 

 


 

๐ŸŒ ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์กฐ (HTML + CSS)

 

๐Ÿ”น ํŽ˜์ด์ง€ ๊ตฌ์„ฑ

ํŽ˜์ด์ง€ ๊ธฐ๋Šฅ
/upload.html ์˜์ƒ ์—…๋กœ๋“œ UI, ์—…๋กœ๋“œ ์ง„ํ–‰ ์ƒํƒœ
/results.html ํƒ์ง€ ๊ฒฐ๊ณผ ์ธ๋„ค์ผ ๋ฆฌ์ŠคํŠธ
/details.html?id=... ์„ ํƒ๋œ ๊ฒฐ๊ณผ ์ƒ์„ธ ๋ณด๊ธฐ (ํƒ์ง€๋œ ์ด๋ฏธ์ง€, ๊ฒฐ๊ณผ ํ…์ŠคํŠธ ๋“ฑ)

 

๐Ÿ”น ์—ฐ๋™ API

  • POST /upload: ์˜์ƒ ์—…๋กœ๋“œ
  • GET /list: ๊ฒฐ๊ณผ ๋ชฉ๋ก ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
  • GET /results/<id>: ๊ฒฐ๊ณผ ์ƒ์„ธ ์กฐํšŒ

 


 

โ˜๏ธ ํด๋ผ์šฐ๋“œ ๊ตฌ์„ฑ (GCP ๊ธฐ๋ฐ˜)

๊ตฌ์„ฑ ์š”์†Œ ์—ญํ• 
Cloud Run Flask ๋ฐฑ์—”๋“œ ๋ฐฐํฌ์šฉ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰
Cloud Storage ์›๋ณธ ์˜์ƒ ๋ฐ ์ธ๋„ค์ผ ์ด๋ฏธ์ง€ ์ €์žฅ
MongoDB Atlas ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ (์˜์ƒ ID, ์‹œ๊ฐ„, ํƒ์ง€ ํด๋ž˜์Šค ๋“ฑ)
YOLOv8 ๋ชจ๋ธ ์ถ”๋ก ์€ Cloud Run ๋‚ด๋ถ€ or ๋ถ„๋ฆฌ๋œ ์ธ์Šคํ„ด์Šค์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅ (๋ฆฌ์†Œ์Šค ๊ณ ๋ ค)

 

 


 

โœ… ์ถ”์ฒœ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ (Flask ๊ธฐ์ค€)

fireclip-backend/
โ”œโ”€โ”€ app.py
โ”œโ”€โ”€ routes/
โ”‚   โ”œโ”€โ”€ upload.py
โ”‚   โ”œโ”€โ”€ detect.py
โ”‚   โ””โ”€โ”€ results.py
โ”œโ”€โ”€ services/
โ”‚   โ”œโ”€โ”€ storage.py       # GCS ์ €์žฅ ๊ด€๋ จ
โ”‚   โ”œโ”€โ”€ inference.py     # YOLO ์ถ”๋ก  ํ˜ธ์ถœ
โ”‚   โ””โ”€โ”€ database.py      # MongoDB ์ฒ˜๋ฆฌ
โ”œโ”€โ”€ static/              # ์ธ๋„ค์ผ ๋“ฑ ์ •์  ํŒŒ์ผ
โ”œโ”€โ”€ templates/           # ํ”„๋ก ํŠธ HTML
โ”œโ”€โ”€ requirements.txt
โ””โ”€โ”€ Dockerfile

 

 


 

๐Ÿงฉ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ˆœ์„œ ์ œ์•ˆ

  1. ๊ธฐ๋ณธ Flask ๋ผ์šฐํ„ฐ ๋ฐ API ๊ตฌ์กฐ ์„ธํŒ…
  2. ์˜์ƒ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ + GCS ์ €์žฅ ์—ฐ๋™
  3. YOLO ์ถ”๋ก  ์Šคํฌ๋ฆฝํŠธ ํ…Œ์ŠคํŠธ ๋ฐ Flask ์—ฐ๋™
  4. ๊ฒฐ๊ณผ ์ธ๋„ค์ผ ์ƒ์„ฑ ๋ฐ MongoDB ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ €์žฅ
  5. /list, /results/<id> API ๊ตฌํ˜„
  6. ํ”„๋ก ํŠธ UI ์—ฐ๊ฒฐ

 


 

๐Ÿ—“๏ธ 4. ๊ฐœ๋ฐœ ์ผ์ •

2025.04.25 ~ 2025.05.09

์ผ์ • ํ•ด์•ผ ํ•  ์ผ (To-Do) ์„ค๋ช…
4/25 (๊ธˆ) โœ… ํ”„๋กœ์ ํŠธ ๊ธฐํš ํ™•์ • ๋ฐ ๊ธฐ์ˆ ์Šคํƒ ์ •๋ฆฌ ์ฃผ์ œ, ๋ฌธ์ œ ์ •์˜, ์†”๋ฃจ์…˜ ํ๋ฆ„ ์ •๋ฆฌ ๋ฐ ์‚ฌ์šฉ ์Šคํƒ ํ™•์ •
4/26 (ํ† ) ๐Ÿ“‚ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ ํฌ๋กค๋ง ์ฝ”๋“œ ์ •๋ฆฌ ์—ฐ๊ธฐ/๋ถˆ๊ฝƒ ๊ณต๊ฐœ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ YOLO์šฉ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์ •๋ฆฌ
4/28~29 (์›”ํ™”) ๐Ÿงช YOLO ํ•™์Šต์šฉ ๋ฐ์ดํ„ฐ ํฌ๋งทํŒ… ๋ฐ ๋ชจ๋ธ ํ•™์Šต
precision/recall ๋“ฑ ์ง€ํ‘œ ํ™•์ธํ•˜๊ณ  ๋ชจ๋ธ ํŠœ๋‹
๐ŸŽฏ ๋ชจ๋ธ ์„ฑ๋Šฅ ๊ฐœ์„  ๋ฐ ๊ฒฐ๊ณผ ํ™•์ธ
YOLOv8์šฉ ํ•™์Šต ๋ฐ์ดํ„ฐ ๋ผ๋ฒจ๋ง ๋ฐ ๋ชจ๋ธ ํ•™์Šต
4/30~ 5/1 (์ˆ˜๋ชฉ) ๐Ÿงฑ Flask ์„œ๋ฒ„ ๊ธฐ๋ณธ ๊ตฌ์กฐ ์„ค๊ณ„ ๊ธฐ๋ณธ ๋ผ์šฐํŒ…, ์š”์ฒญ ๊ตฌ์กฐ, API ์ŠคํŽ™ ์„ค๊ณ„ ๋“ฑ
5/2 (๊ธˆ) ๐Ÿ“ค ์˜์ƒ ์—…๋กœ๋“œ → ํƒ์ง€ ์—ฐ๋™ ๊ตฌํ˜„ ์—…๋กœ๋“œ๋œ ์˜์ƒ์„ ํ”„๋ ˆ์ž„ ๋ถ„ํ• ํ•˜๊ณ  YOLO๋กœ ํƒ์ง€ ์ˆ˜ํ–‰
5/3 (ํ† ) ๐Ÿ–ผ๏ธ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ํด๋ผ์ด์–ธํŠธ ๋ Œ๋”๋ง ๊ตฌํ˜„ ํƒ์ง€๋œ ์ด๋ฏธ์ง€(ํ”„๋ ˆ์ž„) ์›น์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„
5/4 (์ผ) ๐Ÿ’พ MongoDB ์—ฐ๋™ ๋ฐ ํƒ์ง€ ๊ฒฐ๊ณผ ์ €์žฅ ์—…๋กœ๋“œ ์ •๋ณด ๋ฐ ํƒ์ง€ ๊ฒฐ๊ณผ DB์— ์ €์žฅํ•˜๋Š” ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ
5/5 (์›”) โ˜๏ธ GCP Cloud Storage ์—ฐ๋™ ๋ฐ ์˜์ƒ ์ €์žฅ ์˜์ƒ ํŒŒ์ผ์„ Cloud Storage์— ์ €์žฅํ•˜๊ณ  ๊ฒฝ๋กœ๋ฅผ DB์™€ ์—ฐ๊ฒฐ
5/6 (ํ™”) ๐Ÿงช ์ „์ฒด ์—ฐ๋™ ํ…Œ์ŠคํŠธ ๋ฐ ์˜ค๋ฅ˜ ์ˆ˜์ • end-to-end ํ…Œ์ŠคํŠธ ๋ฐ ์˜ค๋ฅ˜, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ง„ํ–‰
5/7 (์ˆ˜) ๐Ÿงผ UX ๊ฐœ์„  ๋ฐ ๋ณด์™„ ์ž‘์—… ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ์—…๋กœ๋“œ/๊ฒฐ๊ณผ ํ™•์ธ ํ๋ฆ„ ์ •๋น„
5/8 (๋ชฉ) ๐Ÿ“ ๋ฐœํ‘œ์ž๋ฃŒ ์ดˆ์•ˆ ์ž‘์„ฑ ๋ฐ ์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ ์ œ์ž‘ ์‹œ์Šคํ…œ ๊ตฌ์กฐ ์‹œ๊ฐํ™”, ๊ธฐ์ˆ  ์š”์•ฝ ํฌํ•จ
5/9 (๊ธˆ) โœ… ์ตœ์ข… ๋ฐœํ‘œ ๋ฐ ํ”„๋กœ์ ํŠธ ๋งˆ๋ฌด๋ฆฌ ๋ฐœํ‘œ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ์ •๋ฆฌ ๋ฐ ์ตœ์ข… ์ •๋ˆ

 

 

 


 

๐Ÿ“ 5. ์‚ฐ์ถœ๋ฌผ ๋ชฉ๋ก

  • Flask ๊ธฐ๋ฐ˜ ์„œ๋ฒ„ ์ฝ”๋“œ
  • YOLOv8 ํƒ์ง€ ์Šคํฌ๋ฆฝํŠธ (์ปค์Šคํ…€ or ๊ธฐ์กด)
  • MongoDB ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ ๋ฐ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ
  • ํƒ์ง€ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ƒ˜ํ”Œ
  • ๋ฐœํ‘œ์šฉ ์Šฌ๋ผ์ด๋“œ ๋ฐ ์‹œ์—ฐ ์˜์ƒ