Skip to content
/ SSEOP Public

Skin-tone & Style Evaluation - Optimal Palette

Notifications You must be signed in to change notification settings

on22y/SSEOP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

33 Commits
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

SSEOP : Skin-tone & Style Evaluation - Optimal Palette

์ด ๋ชจ๋ธ์€ ์‚ฌ์šฉ์ž์˜ ์…€์นด ์ด๋ฏธ์ง€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํผ์Šค๋„ ์ปฌ๋Ÿฌ (๊ณ„์ ˆํ†ค) ๋ถ„๋ฅ˜์™€ ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํŒŒ์ดํ”„๋ผ์ธ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. OpenCV์™€ Mediapipe๋ฅผ ํ™œ์šฉํ•ด ์–ผ๊ตด๊ณผ ํ”ผ๋ถ€ ์˜์—ญ์„ ์ถ”์ถœํ•˜๊ณ , ์ฐธ์กฐ์šฉ ์ข…์ด(ํ™”์ดํŠธ ๋ฐธ๋Ÿฐ์Šค) ์ด๋ฏธ์ง€๋ฅผ ์ด์šฉํ•ด ํ”ผ๋ถ€์ƒ‰์„ ๋ณด์ •ํ•œ ๋’ค, ๊ณ„์ ˆ๋ณ„ ์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ์™€ ๋น„๊ตํ•˜์—ฌ ํผ์Šค๋„ ํ†ค์„ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ GrabCut์„ ํ†ตํ•ด ์˜๋ฅ˜ ๋งˆ์Šคํฌ๋ฅผ ์ถ”์ถœํ•˜๊ณ , K-Means ๊ธฐ๋ฐ˜ ์ƒ‰์ƒ ํด๋Ÿฌ์Šคํ„ฐ๋ง์œผ๋กœ ์˜๋ฅ˜์˜ ๋Œ€ํ‘œ ์ƒ‰์ƒ๊ณผ ๋น„์œจ์„ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค. FastAPI๋ฅผ ์ด์šฉํ•œ ๊ฐ„๋‹จํ•œ ์›น API๋„ ํ•จ๊ป˜ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.


๋ชฉ์ฐจ

  1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ
  2. ์„ค์น˜ ๋ฐ ์š”๊ตฌ ์‚ฌํ•ญ
  3. ์‚ฌ์šฉ ๋ฐฉ๋ฒ•
  4. ๋ชจ๋“ˆ ์„ค๋ช…
  5. ์˜์กด์„ฑ
  6. ์ฐธ๊ณ 

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

/
โ”œโ”€โ”€ main.py
โ”œโ”€โ”€ analysis.py
โ”œโ”€โ”€ clothes_personal_color.py
โ”œโ”€โ”€ list.py
โ”œโ”€โ”€ utils.py
โ”œโ”€โ”€ app.py
โ”œโ”€โ”€ requirements.txt         # (์˜ˆ์‹œ) ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ๋ชฉ๋ก
โ””โ”€โ”€ input/
    โ”œโ”€โ”€ reference_paper.jpg  # ์ฐธ์กฐ์šฉ ์ข…์ด ์ด๋ฏธ์ง€ (ํ™”์ดํŠธ ๋ฐธ๋Ÿฐ์Šค)
    โ””โ”€โ”€ selfie.jpg           # ๋ถ„์„ํ•  ์…€์นด ์ด๋ฏธ์ง€
  • main.py
    • ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ
  • analysis.py
    • ํ”ผ๋ถ€์ƒ‰ ๋ณด์ •, ํผ์Šค๋„ ์ปฌ๋Ÿฌ ๋ถ„๋ฅ˜, ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„ ๋“ฑ ํ•ต์‹ฌ โ€œ๋ถ„์„โ€ ๋กœ์ง์ด ๊ตฌํ˜„๋œ ๋ชจ๋“ˆ
  • clothes_personal_color.py
    • ๊ณ„์ ˆ๋ณ„ ์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ์™€ ๋น„๊ตํ•˜์—ฌ ํผ์Šค๋„ ํ†ค์„ ๋ถ„๋ฅ˜ํ•˜๋Š” ํ•จ์ˆ˜๋“ค์ด ์ •์˜๋œ ๋ชจ๋“ˆ
  • list.py
    • ๋ด„ยท์—ฌ๋ฆ„ยท๊ฐ€์„ยท๊ฒจ์šธ๋ณ„ CMYK ์ปฌ๋Ÿฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ , ์ด๋ฅผ RGB ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅ
  • utils.py
    • Mediapipe๋ฅผ ํ™œ์šฉํ•œ ์–ผ๊ตดยทํ”ผ๋ถ€ ๋งˆ์Šคํฌ ์ถ”์ถœ, ์ข…์ด(์ฐธ์กฐ) ์ปจํˆฌ์–ด ๊ฒ€์ถœ, GrabCut ๊ธฐ๋ฐ˜ ์˜๋ฅ˜ ๋งˆ์Šคํฌ ์ถ”์ถœ ๋“ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋“ค
  • app.py
    • FastAPI๋ฅผ ์ด์šฉํ•œ ๊ฐ„๋‹จํ•œ ์›น ์„œ๋น„์Šค ์˜ˆ์ œ. ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ๋ฅผ ๋ฐ›์•„ ํผ์Šค๋„ ํ†ค๊ณผ ์˜๋ฅ˜ ํ†ค ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜

์„ค์น˜ ๋ฐ ์š”๊ตฌ ์‚ฌํ•ญ

  1. GitHub์—์„œ ์ €์žฅ์†Œ๋ฅผ ํด๋ก ํ•ฉ๋‹ˆ๋‹ค.

    git clone https://github.com/<์‚ฌ์šฉ์ž_์ด๋ฆ„>/<์ €์žฅ์†Œ_์ด๋ฆ„>.git
    cd <์ €์žฅ์†Œ_์ด๋ฆ„>
  2. Python 3.7 ์ด์ƒ(๊ถŒ์žฅ: 3.8+)์ด ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  3. requirements.txt ํŒŒ์ผ์„ ์ฐธ๊ณ ํ•˜์—ฌ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

    pip install -r requirements.txt

    ์ฃผ์š” ์˜์กด์„ฑ ์˜ˆ์‹œ

    • opencv-python (OpenCV)
    • numpy
    • matplotlib
    • scikit-learn (KMeans)
    • mediapipe
    • fastapi
    • uvicorn

    _requirements.txt_ (์˜ˆ์‹œ)

    opencv-python
    numpy
    matplotlib
    scikit-learn
    mediapipe
    fastapi
    uvicorn
    

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ปค๋งจ๋“œ๋ผ์ธ ์‹คํ–‰ (main.py)

  1. ์‚ฌ์šฉ์ž ์…€์นด ์ด๋ฏธ์ง€์™€ ์ฐธ์กฐ์šฉ ์ข…์ด ์ด๋ฏธ์ง€๋ฅผ input/ ํด๋”์— ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.

    • ์˜ˆ์‹œ:
      input/
      โ”œโ”€โ”€ reference_paper.jpg   # ์กฐ๋ช… ๋ณด์ •์— ์‚ฌ์šฉํ•  ์ข…์ด ์ด๋ฏธ์ง€
      โ””โ”€โ”€ selfie.jpg            # ์ดฌ์˜ํ•œ ์…€์นด ์ด๋ฏธ์ง€
      
  2. ํ„ฐ๋ฏธ๋„์—์„œ main.py๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    python main.py
  3. ํ”„๋กœ๊ทธ๋žจ์ด ์ˆœ์ฐจ์ ์œผ๋กœ ๋‹ค์Œ ๋‹จ๊ณ„๋“ค์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    1. 1๋‹จ๊ณ„: ์–ผ๊ตดยทํ”ผ๋ถ€ ๋งˆ์Šคํฌ ์ถ”์ถœ
      utils.get_face_skin_mask() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Mediapipe Face Mesh๋กœ๋ถ€ํ„ฐ ์–ผ๊ตด ์œค๊ณฝ์„ ์ฐพ๊ณ  ํ”ผ๋ถ€ ์˜์—ญ๋งŒ ๋งˆ์Šคํ‚น
    2. 2๋‹จ๊ณ„: ํผ์Šค๋„ ์ปฌ๋Ÿฌ ๋ณด์ •
      • utils.find_paper_contour_and_mask_refined()๋กœ ์ฐธ์กฐ์šฉ ์ข…์ด ์ปจํˆฌ์–ด๋ฅผ ๊ฒ€์ถœํ•˜์—ฌ ์กฐ๋ช… ๋ณด์ •์šฉ ๋งˆ์Šคํฌ ์ƒ์„ฑ
      • analysis.estimate_true_skin_color()๋ฅผ ํ†ตํ•ด ์ข…์ด์™€ ํ”ผ๋ถ€ ๋งˆ์Šคํฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”ผ๋ถ€์˜ โ€œ์ง„์งœโ€ ์ƒ‰(์กฐ๋ช… ๋ณด์ •) ์ถ”์ •
    3. 3๋‹จ๊ณ„: ํผ์Šค๋„ ์ปฌ๋Ÿฌ(๊ณ„์ ˆํ†ค) ๋ถ„๋ฅ˜
      • analysis.classify_personal_color()๋ฅผ ์ด์šฉํ•ด HSL/HV ๊ธฐ์ค€์œผ๋กœ ๋ด„ยท์—ฌ๋ฆ„ยท๊ฐ€์„ยท๊ฒจ์šธ ํ†ค ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒ
    4. 4๋‹จ๊ณ„: ์˜๋ฅ˜ ๋งˆ์Šคํฌ ์ถ”์ถœ
      • utils.extract_clothes_mask() (GrabCut)์œผ๋กœ ์…€์นด์—์„œ ์˜๋ฅ˜ ์˜์—ญ ๋ถ„๋ฆฌ
    5. 5๋‹จ๊ณ„: ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„
      • analysis.get_dominant_colors_with_elbow_and_ratio()๋กœ ์˜๋ฅ˜ ๋งˆ์Šคํฌ ์˜์—ญ์—์„œ KMeans ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ˆ˜ํ–‰
      • analysis.display_clothes_analysis_with_ratio()๋กœ ์˜๋ฅ˜ ๋‚ด ์ฃผ์š” ์ƒ‰์ƒ(ํด๋Ÿฌ์Šคํ„ฐ)๊ณผ ๋น„์œจ์„ ์‹œ๊ฐํ™” ๋ฐ ์ €์žฅ
    6. ์ตœ์ข… ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ ๋‹จ๊ณ„๋ณ„ ์ค‘๊ฐ„ ๊ฒฐ๊ณผ๋ฌผ์„ ์ง€์ •๋œ ๊ฒฝ๋กœ์— ์ €์žฅํ•˜๊ณ , ์ฝ˜์†”์— ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
  4. ์™„๋ฃŒ ํ›„, ์ €์žฅ๋œ ์ด๋ฏธ์ง€(์กฐ๋ช… ๋ณด์ • ์ „ยทํ›„, ํ”ผ๋ถ€ ๋งˆ์Šคํฌ, ์˜๋ฅ˜ ๋งˆ์Šคํฌ, ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„ ๊ฒฐ๊ณผ ๋“ฑ)๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ์˜ˆ: results/skin_corrected.jpeg, results/clothes_mask.png, results/clothes_colors.png ๋“ฑ

FastAPI ์›น ์„œ๋น„์Šค (app.py)

  1. app.py๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” uvicorn์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: pip install uvicorn)

  2. ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ FastAPI ์„œ๋ฒ„๋ฅผ ๊ตฌ๋™ํ•ฉ๋‹ˆ๋‹ค.

    uvicorn app:app --reload --host 0.0.0.0 --port 8000
  3. ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” API ์—”๋“œํฌ์ธํŠธ

    • ํผ์Šค๋„ ์ปฌ๋Ÿฌ ๋ถ„์„
      POST /personal-color
      
      • ์š”์ฒญ (multipart/form-data)
        • selfie: ์‚ฌ์šฉ์ž ์…€์นด ์ด๋ฏธ์ง€ (JPEG/PNG)
        • reference: ์กฐ๋ช… ๋ณด์ •์šฉ ์ข…์ด ์ด๋ฏธ์ง€ (JPEG/PNG)
      • ์‘๋‹ต
        {
          "tone": "Spring",              # ์˜ˆ์‹œ: Spring / Summer / Autumn / Winter
          "hsv": { "h": 25.0, "s": 30.5, "v": 60.2 },   # ํ”ผ๋ถ€์˜ ๋Œ€ํ‘œ HSV ๊ฐ’
          "corrected_skin_rgb": [200, 180, 170]        # ์กฐ๋ช… ๋ณด์ • ํ›„ ํ”ผ๋ถ€ ์ƒ‰์ƒ (RGB)
        }
    • ์˜๋ฅ˜ ํ†ค ๋ถ„์„ (๋น„์œจ ํฌํ•จ)
      POST /clothes-color
      
      • ์š”์ฒญ (multipart/form-data)
        • selfie: ์‚ฌ์šฉ์ž ์…€์นด ์ด๋ฏธ์ง€
      • ์‘๋‹ต
        {
          "dominant_colors": [
             { "rgb": [255, 0, 0], "ratio": 0.45 },
             { "rgb": [0, 128, 255], "ratio": 0.30 },
             { "rgb": [50, 50, 50], "ratio": 0.25 }
          ]
        }
    • ์˜๋ฅ˜ ํ†ค ๋ถ„๋ฅ˜ (๊ณ„์ ˆํ†ค ๋น„๊ต)
      POST /clothes-tone
      
      • ์š”์ฒญ
        • selfie: ์‚ฌ์šฉ์ž ์…€์นด ์ด๋ฏธ์ง€
      • ์‘๋‹ต
        {
          "tone": "Autumn"   # ์˜๋ฅ˜์˜ ๋Œ€ํ‘œ ์ƒ‰์ƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์ ˆํ†ค ๋ถ„๋ฅ˜
        }
  4. ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋œ ํ›„ http://localhost:8000/docs๋กœ ์ ‘์†ํ•˜๋ฉด ์ž๋™ ์ƒ์„ฑ๋œ Swagger UI์—์„œ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.


๋ชจ๋“ˆ ์„ค๋ช…

main.py

  • ํ”„๋กœ์ ํŠธ์˜ ์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ (Entry Point) ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • main() ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    1. ์ž…๋ ฅ ์„ค์ •:
      base_dir = "."  
      INPUT_SELFIE_PATH = os.path.join(base_dir, "input/selfie.jpg")  
      INPUT_REFERENCE_PATH = os.path.join(base_dir, "input/reference_paper.jpg")  
    2. Step 1: ์–ผ๊ตดยทํ”ผ๋ถ€ ๋งˆ์Šคํฌ ์ƒ์„ฑ
      skin_mask = get_face_skin_mask(selfie_img_bgr)
    3. Step 2: ํผ์Šค๋„ ์ปฌ๋Ÿฌ ๋ณด์ •
      (
        true_skin_hsv,
        skin_lab_mean,
        corrected_selfie_bgr,
        exc_paper_mask_for_skin,
        refined_paper_mask
      ) = estimate_true_skin_color(selfie_img_bgr, skin_mask, INPUT_REFERENCE_PATH)
    4. Step 3: ํผ์Šค๋„ ํ†ค ๋ถ„๋ฅ˜
      personal_tone = classify_personal_color(true_skin_hsv)
    5. Step 4: ์˜๋ฅ˜ ๋งˆ์Šคํฌ ์ถ”์ถœ
      clothes_mask = extract_clothes_mask(corrected_selfie_bgr)
    6. Step 5: ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„
      dominant_colors, wcss_values = get_dominant_colors_with_elbow_and_ratio(
          corrected_selfie_bgr, clothes_mask
      )
      display_clothes_analysis_with_ratio(
          corrected_selfie_bgr, clothes_mask, dominant_colors, wcss_values
      )
    7. ๊ฐ ๋‹จ๊ณ„๋ณ„ ์ค‘๊ฐ„ ๋ฐ ์ตœ์ข… ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ results/ ํด๋”์— ์ €์žฅ
    8. ์ฝ˜์†” ์ถœ๋ ฅ์œผ๋กœ ์ง„ํ–‰ ์ƒํ™ฉ ๋ฐ ๊ฒฐ๊ณผ ์ •๋ณด ํ‘œ์‹œ

analysis.py

  • ํ”ผ๋ถ€์ƒ‰ ๋ณด์ • & ์ถ”์ •
    • estimate_true_skin_color(selfie_img_bgr, extracted_face_skin_mask, reference_img_path)
      • selfie_img_bgr: ์›๋ณธ BGR ์…€์นด ์ด๋ฏธ์ง€
      • extracted_face_skin_mask: Mediapipe๋กœ ์ถ”์ถœํ•œ ํ”ผ๋ถ€ ์˜์—ญ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋งˆ์Šคํฌ
      • reference_img_path: ์กฐ๋ช… ๋ณด์ •์šฉ ์ข…์ด ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
      • ๋ฆฌํ„ด:
        • true_skin_hsv: ์กฐ๋ช… ๋ณด์ •๋œ ํ”ผ๋ถ€์˜ HSV
        • skin_lab_mean: Lab ์ƒ‰์ƒ ๊ณต๊ฐ„์—์„œ์˜ ํ”ผ๋ถ€ ํ‰๊ท ๊ฐ’
        • corrected_selfie_bgr: ์กฐ๋ช… ๋ณด์ •๋œ ์…€์นด BGR ์ด๋ฏธ์ง€
        • exc_paper_mask_for_skin: ์ข…์ด ์˜์—ญ์„ ์ œ์™ธํ•œ ํ”ผ๋ถ€ ๋งˆ์Šคํฌ
        • refined_paper_mask: ์ข…์ด ์˜์—ญ ๋งˆ์Šคํฌ(์ •์ œ ๋ฒ„์ „)
      • ์ฃผ์š” ํ๋ฆ„:
        1. ์ฐธ์กฐ์šฉ ์ข…์ด ์ปจํˆฌ์–ด ๊ฒ€์ถœ (find_paper_contour_and_mask_refined)
        2. ์ข…์ด ์˜์—ญ์œผ๋กœ๋ถ€ํ„ฐ ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ ๋ณด์ • ๊ณ„์ˆ˜ ๊ณ„์‚ฐ
        3. ์…€์นด ์ „์ฒด์— ๋ณด์ • ๊ณ„์ˆ˜ ์ ์šฉ โ†’ corrected_selfie_bgr
        4. ์ข…์ด ์˜์—ญ ์ œ์™ธ ํ›„ ํ”ผ๋ถ€ ์˜์—ญ H ๊ฐ’์„ ํ‰๊ท ์ ์œผ๋กœ ๊ตฌํ•ด์„œ ๋Œ€ํ‘œ ํ”ผ๋ถ€์ƒ‰ ์‚ฐ์ถœ
  • ํผ์Šค๋„ ์ปฌ๋Ÿฌ ๋ถ„๋ฅ˜
    • classify_personal_color(true_skin_hsv)
      • Hue, Lightness, Saturation ๋“ฑ์˜ ์ƒ‰์ƒ ์ง€ํ‘œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์ „ ์ •์˜๋œ ๊ณ„์ ˆ๋ณ„ ๊ธฐ์ค€ ๊ฐ’๊ณผ ๋น„๊ตํ•ด Spring, Summer, Autumn, Winter ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒ
  • ์˜๋ฅ˜ ์ƒ‰์ƒ ๋ถ„์„
    • get_dominant_colors_from_mask(image_bgr, mask, k)
      • ๋งˆ์Šคํฌ ์˜์—ญ ๋‚ด ํ”ฝ์…€ ์ƒ‰์ƒ๊ฐ’์„ ์ถ”์ถœํ•˜์—ฌ KMeans ํด๋Ÿฌ์Šคํ„ฐ๋ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ๊ฐ ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ค‘์‹ฌ(๋Œ€ํ‘œ ์ƒ‰์ƒ)๊ณผ ํ”ฝ์…€ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜
    • get_dominant_colors_with_elbow_and_ratio(image_bgr, mask)
      • k ๊ฐ’์„ Elbow ๊ธฐ๋ฒ•์œผ๋กœ ์ž๋™ ์„ ์ • ํ›„ ํด๋Ÿฌ์Šคํ„ฐ๋ง
      • ํด๋Ÿฌ์Šคํ„ฐ๋ณ„ ๋Œ€ํ‘œ ์ƒ‰์ƒ(HSV ๋˜๋Š” RGB)๊ณผ ๋น„์œจ ๊ณ„์‚ฐ
    • display_clothes_analysis_with_ratio(image_bgr, mask, dominant_colors, wcss_values)
      • Matplotlib์„ ์ด์šฉํ•ด
        1. ์›๋ณธ ์ด๋ฏธ์ง€ ์œ„์— ์˜๋ฅ˜ ์˜์—ญ ์œค๊ณฝ ํ‘œ์‹œ
        2. ๋Œ€ํ‘œ ์ƒ‰์ƒ ์นฉ๊ณผ ๋น„์œจ ๊ทธ๋ž˜ํ”„(ํŒŒ์ด ์ฐจํŠธ)
        3. Elbow ๊ธฐ๋ฒ• ๊ฒฐ๊ณผ ๊ทธ๋ž˜ํ”„
      • ๊ฒฐ๊ณผ๋ฌผ์„ results/ ํด๋”์— PNG๋กœ ์ €์žฅ

clothes_personal_color.py

  • CMYK โ†” RGB ๋ณ€ํ™˜
    • cmyk_to_rgb(c, m, y, k)
      • c, m, y, k ๊ฐ’์„ 0โ€“100 ์Šค์ผ€์ผ์—์„œ 0โ€“1๋กœ ์ •๊ทœํ™” ํ›„, RGB๋กœ ๋ณ€ํ™˜
  • ๊ณ„์ ˆ๋ณ„ ์ปฌ๋Ÿฌ ๋ฆฌ์ŠคํŠธ์—์„œ ๋Œ€ํ‘œ ์ƒ‰์ƒ ํŠน์ง• ์ถ”์ถœ
    • extract_tone_features(color_list)
      • list.py์— ์ •์˜๋œ ๊ณ„์ ˆ๋ณ„ CMYK ๋ฆฌ์ŠคํŠธ(spring_list, summer_list ๋“ฑ)๋ฅผ ์ž…๋ ฅ๋ฐ›์•„
      • ๊ฐ ์ƒ‰์ƒ์˜ HSL/HV ํŠน์ง•์„ ๊ณ„์‚ฐํ•˜์—ฌ tone_features ๋”•์…”๋„ˆ๋ฆฌ๋กœ ์ €์žฅ
  • ํผ์Šค๋„ ํ†ค ๋ถ„๋ฅ˜ ํ•จ์ˆ˜
    • classify_tone_by_hsv(skin_hsv, tone_features)
      • ์ถ”์ •ํ•œ ํ”ผ๋ถ€์˜ HSV ๊ฐ’์„ ๋ฐ›์•„ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณ„์ ˆ ํŒ”๋ ˆํŠธ(ํ†ค) ์ด๋ฆ„(Spring, Summer, Autumn, Winter)์„ ๋ฐ˜ํ™˜
  • ํŒŒ์ผ ๋กœ๋“œ ์‹œ, ๋ฏธ๋ฆฌ tone_features๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ

list.py

  • ๊ณ„์ ˆ๋ณ„ CMYK ์ปฌ๋Ÿฌ ์ •๋ณด
    • spring_list, summer_list, autumn_list, winter_list์— ์—ฌ๋Ÿฌ ์ƒ‰์ƒ ํ•ญ๋ชฉ(๋”•์…”๋„ˆ๋ฆฌ) ์ •์˜
      • ์˜ˆ์‹œ:
        spring_list = [
            { "name": "Peach", "c": 0, "m": 52, "y": 32, "k": 0, "season": "spring" },
            ...
        ]
    • ๊ฐ ํ•ญ๋ชฉ์—๋Š” name, c, m, y, k, season ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ฝ”๋“œ ์‹คํ–‰ ์‹œ์— cmyk_to_rgb()๋ฅผ ํ†ตํ•ด RGB ๊ฐ’("rgb")์„ ์ถ”๊ฐ€๋กœ ๊ณ„์‚ฐ
  • ฮ”E(CIELAB) ๊ณ„์‚ฐ (์˜ˆ: ์ƒ‰์ƒ ๊ฐ„ ์œ ์‚ฌ๋„ ์ธก์ •) ์˜ˆ๋น„ ํ•จ์ˆ˜
    • delta_e_distance(rgb1, rgb2) ๋“ฑ

utils.py

  • Face Mesh๋ฅผ ์ด์šฉํ•œ ์–ผ๊ตดยทํ”ผ๋ถ€ ๋งˆ์Šคํฌ
    • get_face_skin_mask(image_bgr)
      • Mediapipe Face Mesh๋กœ ์–ผ๊ตด ์œค๊ณฝ์ (landmarks)์„ ์ฐพ์•„์„œ
      • FACE_OVAL_INDICES์— ์ •์˜๋œ ์–ผ๊ตด ํ…Œ๋‘๋ฆฌ ์ ๋“ค์„ ์—ฐ๊ฒฐํ•ด ๋‹ค๊ฐํ˜• ๋งˆ์Šคํฌ ์ƒ์„ฑ
      • ๋‹ค๊ฐํ˜• ๋‚ด๋ถ€๋ฅผ ์ฑ„์›Œ ํ”ผ๋ถ€ ์˜์—ญ ๋งˆ์Šคํฌ(๋ฐ”์ด๋„ˆ๋ฆฌ) ๋ฐ˜ํ™˜
  • ์ฐธ์กฐ์šฉ ์ข…์ด(ํ™”์ดํŠธ ๋ฐธ๋Ÿฐ์Šค) ๊ฒ€์ถœ
    • find_paper_contour_and_mask_refined(image_bgr)
      • ๊ทธ๋ ˆ์ด์Šค์ผ€์ผ, ๊ฐ€์šฐ์‹œ์•ˆ ๋ธ”๋Ÿฌ, ์œค๊ณฝ์„  ๊ฒ€์ถœ ๋“ฑ์„ ํ†ตํ•ด ์ข…์ด(ํฐ์ƒ‰ ์‚ฌ๊ฐํ˜•) ์ปจํˆฌ์–ด ์ถ”์ถœ
      • ๋ฉด์ /๊ธฐ์šธ๊ธฐ ์กฐ๊ฑด์„ ํ†ตํ•ด ์‚ฌ๊ฐํ˜• ํ•„ํ„ฐ๋ง
      • ์ •์ œ๋œ ์ข…์ด ๋งˆ์Šคํฌ(๋ฐ”์ด๋„ˆ๋ฆฌ) ๋ฐ˜ํ™˜
  • ์˜๋ฅ˜ ๋งˆ์Šคํฌ ์ถ”์ถœ (GrabCut ๊ธฐ๋ฐ˜)
    • extract_clothes_mask(image_bgr)
      • ์ด๋ฏธ์ง€ ์ค‘์•™์„ ๊ธฐ์ค€์œผ๋กœ ์˜๋ฅ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •๋˜๋Š” ์‚ฌ๊ฐํ˜• ์˜์—ญ(rect)์„ ์„ค์ •
      • cv2.grabCut()์„ ์‚ฌ์šฉํ•˜์—ฌ ์ „๊ฒฝ(์˜๋ฅ˜) ์˜์—ญ๋งŒ ๋ถ„๋ฆฌ
      • ์ด์ง„ํ™” ๋งˆ์Šคํฌ(0 ๋˜๋Š” 255)๋กœ ๋ฐ˜ํ™˜

app.py

  • FastAPI ์—”๋“œํฌ์ธํŠธ ์ •์˜

    • POST /personal-color:
      • Form-data๋กœ ์—…๋กœ๋“œ๋œ selfie, reference ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋ฐ›์•„
      • estimate_true_skin_color() โ†’ classify_personal_color() ์ˆœ์œผ๋กœ ํ˜ธ์ถœ
      • JSON ํ˜•์‹์œผ๋กœ ํผ์Šค๋„ ํ†ค(๊ณ„์ ˆ) ๋ฐ ๋Œ€ํ‘œ HSV, RGB ์ •๋ณด ์‘๋‹ต
    • POST /clothes-color:
      • Form-data๋กœ selfie ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›์•„
      • get_face_skin_mask() โ†’ estimate_true_skin_color()(์ƒ๋žต ๊ฐ€๋Šฅ) โ†’ extract_clothes_mask() โ†’ ์ƒ‰์ƒ ํด๋Ÿฌ์Šคํ„ฐ๋ง
      • JSON์œผ๋กœ ์˜๋ฅ˜ ๋Œ€ํ‘œ ์ƒ‰์ƒ(rgb)๊ณผ ๋น„์œจ(ratio)์„ ๋ฐ˜ํ™˜
    • POST /clothes-tone:
      • Form-data๋กœ selfie ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›์•„
      • extract_clothes_mask() โ†’ get_dominant_colors_from_mask() โ†’ classify_tone_by_hsv()
      • ์˜๋ฅ˜ ํ†ค(๊ณ„์ ˆ) ์ด๋ฆ„ ๋ฐ˜ํ™˜
  • CORS ์„ค์ •

    • FastAPI ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ CORSMiddleware๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ชจ๋“  ์ถœ์ฒ˜ ํ—ˆ์šฉ ์„ค์ •

์˜์กด์„ฑ

opencv-python>=4.5
numpy>=1.19
matplotlib>=3.3
scikit-learn>=0.24
mediapipe>=0.8
fastapi>=0.65
uvicorn>=0.13

์ฐธ๊ณ 

  • ํด๋” ๊ตฌ์กฐ ์˜ˆ์‹œ

    โ”œโ”€โ”€ input/
    โ”‚   โ”œโ”€โ”€ selfie.jpg
    โ”‚   โ””โ”€โ”€ reference_paper.jpg
    โ”œโ”€โ”€ results/
    โ”‚   โ”œโ”€โ”€ corrected_selfie.jpg
    โ”‚   โ”œโ”€โ”€ paper_mask.png
    โ”‚   โ”œโ”€โ”€ skin_mask.png
    โ”‚   โ”œโ”€โ”€ clothes_mask.png
    โ”‚   โ””โ”€โ”€ clothes_analysis.png
    โ”œโ”€โ”€ main.py
    โ”œโ”€โ”€ analysis.py
    โ”œโ”€โ”€ clothes_personal_color.py
    โ”œโ”€โ”€ list.py
    โ”œโ”€โ”€ utils.py
    โ”œโ”€โ”€ app.py
    โ””โ”€โ”€ requirements.txt
    
  • ๊ฒฐ๊ณผ๋ฌผ ์˜ˆ์‹œ

    1. skin_mask.png: ์ถ”์ถœ๋œ ํ”ผ๋ถ€ ์˜์—ญ ๋งˆ์Šคํฌ (ํฐ์ƒ‰ = ํ”ผ๋ถ€)
    2. corrected_selfie.jpg: ํ™”์ดํŠธ ๋ฐธ๋Ÿฐ์Šค ๋ณด์ •์ด ์ ์šฉ๋œ ์…€์นด
    3. clothes_mask.png: GrabCut์œผ๋กœ ์ถ”์ถœ๋œ ์˜๋ฅ˜ ์˜์—ญ ๋งˆ์Šคํฌ
    4. clothes_analysis.png: ์˜๋ฅ˜ ๋Œ€ํ‘œ ์ƒ‰์ƒ ๋ฐ ๋น„์œจ ์‹œ๊ฐํ™” (ํŒŒ์ด ์ฐจํŠธ + ์ƒ‰์ƒ ์นฉ)

About

Skin-tone & Style Evaluation - Optimal Palette

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors 3

  •  
  •  
  •