์ด ๋ชจ๋ธ์ ์ฌ์ฉ์์ ์ ์นด ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํผ์ค๋ ์ปฌ๋ฌ (๊ณ์ ํค) ๋ถ๋ฅ์ ์๋ฅ ์์ ๋ถ์์ ์ํํ๋ ํ์ดํ๋ผ์ธ์ ์ ๊ณตํฉ๋๋ค. OpenCV์ Mediapipe๋ฅผ ํ์ฉํด ์ผ๊ตด๊ณผ ํผ๋ถ ์์ญ์ ์ถ์ถํ๊ณ , ์ฐธ์กฐ์ฉ ์ข ์ด(ํ์ดํธ ๋ฐธ๋ฐ์ค) ์ด๋ฏธ์ง๋ฅผ ์ด์ฉํด ํผ๋ถ์์ ๋ณด์ ํ ๋ค, ๊ณ์ ๋ณ ์ปฌ๋ฌ ํ๋ ํธ์ ๋น๊ตํ์ฌ ํผ์ค๋ ํค์ ๋ถ๋ฅํฉ๋๋ค. ๋ํ GrabCut์ ํตํด ์๋ฅ ๋ง์คํฌ๋ฅผ ์ถ์ถํ๊ณ , K-Means ๊ธฐ๋ฐ ์์ ํด๋ฌ์คํฐ๋ง์ผ๋ก ์๋ฅ์ ๋ํ ์์๊ณผ ๋น์จ์ ์๊ฐํํฉ๋๋ค. FastAPI๋ฅผ ์ด์ฉํ ๊ฐ๋จํ ์น API๋ ํจ๊ป ํฌํจ๋์ด ์์ต๋๋ค.
/
โโโ 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๋ฅผ ์ด์ฉํ ๊ฐ๋จํ ์น ์๋น์ค ์์ . ์ด๋ฏธ์ง ์ ๋ก๋๋ฅผ ๋ฐ์ ํผ์ค๋ ํค๊ณผ ์๋ฅ ํค ์ ๋ณด๋ฅผ ๋ฐํ
-
GitHub์์ ์ ์ฅ์๋ฅผ ํด๋ก ํฉ๋๋ค.
git clone https://github.com/<์ฌ์ฉ์_์ด๋ฆ>/<์ ์ฅ์_์ด๋ฆ>.git cd <์ ์ฅ์_์ด๋ฆ>
-
Python 3.7 ์ด์(๊ถ์ฅ: 3.8+)์ด ์ค์น๋์ด ์์ด์ผ ํฉ๋๋ค.
-
requirements.txtํ์ผ์ ์ฐธ๊ณ ํ์ฌ ํ์ํ ํจํค์ง๋ฅผ ์ค์นํฉ๋๋ค.pip install -r requirements.txt
์ฃผ์ ์์กด์ฑ ์์
opencv-python(OpenCV)numpymatplotlibscikit-learn(KMeans)mediapipefastapiuvicorn
_requirements.txt_(์์)opencv-python numpy matplotlib scikit-learn mediapipe fastapi uvicorn
-
์ฌ์ฉ์ ์ ์นด ์ด๋ฏธ์ง์ ์ฐธ์กฐ์ฉ ์ข ์ด ์ด๋ฏธ์ง๋ฅผ
input/ํด๋์ ์ค๋นํฉ๋๋ค.- ์์:
input/ โโโ reference_paper.jpg # ์กฐ๋ช ๋ณด์ ์ ์ฌ์ฉํ ์ข ์ด ์ด๋ฏธ์ง โโโ selfie.jpg # ์ดฌ์ํ ์ ์นด ์ด๋ฏธ์ง
- ์์:
-
ํฐ๋ฏธ๋์์
main.py๋ฅผ ์คํํฉ๋๋ค.python main.py
-
ํ๋ก๊ทธ๋จ์ด ์์ฐจ์ ์ผ๋ก ๋ค์ ๋จ๊ณ๋ค์ ์ํํฉ๋๋ค.
- 1๋จ๊ณ: ์ผ๊ตดยทํผ๋ถ ๋ง์คํฌ ์ถ์ถ
utils.get_face_skin_mask()ํจ์๋ฅผ ํตํด Mediapipe Face Mesh๋ก๋ถํฐ ์ผ๊ตด ์ค๊ณฝ์ ์ฐพ๊ณ ํผ๋ถ ์์ญ๋ง ๋ง์คํน - 2๋จ๊ณ: ํผ์ค๋ ์ปฌ๋ฌ ๋ณด์
utils.find_paper_contour_and_mask_refined()๋ก ์ฐธ์กฐ์ฉ ์ข ์ด ์ปจํฌ์ด๋ฅผ ๊ฒ์ถํ์ฌ ์กฐ๋ช ๋ณด์ ์ฉ ๋ง์คํฌ ์์ฑanalysis.estimate_true_skin_color()๋ฅผ ํตํด ์ข ์ด์ ํผ๋ถ ๋ง์คํฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํผ๋ถ์ โ์ง์งโ ์(์กฐ๋ช ๋ณด์ ) ์ถ์
- 3๋จ๊ณ: ํผ์ค๋ ์ปฌ๋ฌ(๊ณ์ ํค) ๋ถ๋ฅ
analysis.classify_personal_color()๋ฅผ ์ด์ฉํด HSL/HV ๊ธฐ์ค์ผ๋ก ๋ดยท์ฌ๋ฆยท๊ฐ์ยท๊ฒจ์ธ ํค ์ค ํ๋๋ฅผ ์ ํ
- 4๋จ๊ณ: ์๋ฅ ๋ง์คํฌ ์ถ์ถ
utils.extract_clothes_mask()(GrabCut)์ผ๋ก ์ ์นด์์ ์๋ฅ ์์ญ ๋ถ๋ฆฌ
- 5๋จ๊ณ: ์๋ฅ ์์ ๋ถ์
analysis.get_dominant_colors_with_elbow_and_ratio()๋ก ์๋ฅ ๋ง์คํฌ ์์ญ์์ KMeans ํด๋ฌ์คํฐ๋ง ์ํanalysis.display_clothes_analysis_with_ratio()๋ก ์๋ฅ ๋ด ์ฃผ์ ์์(ํด๋ฌ์คํฐ)๊ณผ ๋น์จ์ ์๊ฐํ ๋ฐ ์ ์ฅ
- ์ต์ข ๊ฒฐ๊ณผ ์ด๋ฏธ์ง ๋ฐ ๋จ๊ณ๋ณ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฌผ์ ์ง์ ๋ ๊ฒฝ๋ก์ ์ ์ฅํ๊ณ , ์ฝ์์ ๋ฉ์์ง ์ถ๋ ฅ
- 1๋จ๊ณ: ์ผ๊ตดยทํผ๋ถ ๋ง์คํฌ ์ถ์ถ
-
์๋ฃ ํ, ์ ์ฅ๋ ์ด๋ฏธ์ง(์กฐ๋ช ๋ณด์ ์ ยทํ, ํผ๋ถ ๋ง์คํฌ, ์๋ฅ ๋ง์คํฌ, ์๋ฅ ์์ ๋ถ์ ๊ฒฐ๊ณผ ๋ฑ)๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
- ์:
results/skin_corrected.jpeg,results/clothes_mask.png,results/clothes_colors.png๋ฑ
- ์:
-
app.py๋ฅผ ์คํํ๊ธฐ ์ํด์๋uvicorn์ ์ค์นํด์ผ ํฉ๋๋ค. (์:pip install uvicorn) -
์๋ ๋ช ๋ น์ด๋ก FastAPI ์๋ฒ๋ฅผ ๊ตฌ๋ํฉ๋๋ค.
uvicorn app:app --reload --host 0.0.0.0 --port 8000
-
๊ธฐ๋ณธ ์ ๊ณต๋๋ 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) }
- ์์ฒญ (multipart/form-data)
- ์๋ฅ ํค ๋ถ์ (๋น์จ ํฌํจ)
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 } ] }
- ์์ฒญ (multipart/form-data)
- ์๋ฅ ํค ๋ถ๋ฅ (๊ณ์ ํค ๋น๊ต)
POST /clothes-tone- ์์ฒญ
selfie: ์ฌ์ฉ์ ์ ์นด ์ด๋ฏธ์ง
- ์๋ต
{ "tone": "Autumn" # ์๋ฅ์ ๋ํ ์์์ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ ํค ๋ถ๋ฅ }
- ์์ฒญ
- ํผ์ค๋ ์ปฌ๋ฌ ๋ถ์
-
์๋ฒ๊ฐ ์คํ๋ ํ
http://localhost:8000/docs๋ก ์ ์ํ๋ฉด ์๋ ์์ฑ๋ Swagger UI์์ ํ ์คํธ ๊ฐ๋ฅํฉ๋๋ค.
- ํ๋ก์ ํธ์ ์ํธ๋ฆฌ ํฌ์ธํธ (Entry Point) ์ญํ ์ ํฉ๋๋ค.
main()ํจ์ ๋ด์์ ์ ์ฒด ํ์ดํ๋ผ์ธ์ ์์ฐจ์ ์ผ๋ก ํธ์ถํฉ๋๋ค.- ์
๋ ฅ ์ค์ :
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")
- Step 1: ์ผ๊ตดยทํผ๋ถ ๋ง์คํฌ ์์ฑ
skin_mask = get_face_skin_mask(selfie_img_bgr)
- 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)
- Step 3: ํผ์ค๋ ํค ๋ถ๋ฅ
personal_tone = classify_personal_color(true_skin_hsv)
- Step 4: ์๋ฅ ๋ง์คํฌ ์ถ์ถ
clothes_mask = extract_clothes_mask(corrected_selfie_bgr)
- 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 )
- ๊ฐ ๋จ๊ณ๋ณ ์ค๊ฐ ๋ฐ ์ต์ข
๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ
results/ํด๋์ ์ ์ฅ - ์ฝ์ ์ถ๋ ฅ์ผ๋ก ์งํ ์ํฉ ๋ฐ ๊ฒฐ๊ณผ ์ ๋ณด ํ์
- ์
๋ ฅ ์ค์ :
- ํผ๋ถ์ ๋ณด์ & ์ถ์
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: ์กฐ๋ช ๋ณด์ ๋ ํผ๋ถ์ HSVskin_lab_mean: Lab ์์ ๊ณต๊ฐ์์์ ํผ๋ถ ํ๊ท ๊ฐcorrected_selfie_bgr: ์กฐ๋ช ๋ณด์ ๋ ์ ์นด BGR ์ด๋ฏธ์งexc_paper_mask_for_skin: ์ข ์ด ์์ญ์ ์ ์ธํ ํผ๋ถ ๋ง์คํฌrefined_paper_mask: ์ข ์ด ์์ญ ๋ง์คํฌ(์ ์ ๋ฒ์ )
- ์ฃผ์ ํ๋ฆ:
- ์ฐธ์กฐ์ฉ ์ข
์ด ์ปจํฌ์ด ๊ฒ์ถ (
find_paper_contour_and_mask_refined) - ์ข ์ด ์์ญ์ผ๋ก๋ถํฐ ๊ทธ๋ ์ด ์ค์ผ์ผ ๋ณด์ ๊ณ์ ๊ณ์ฐ
- ์
์นด ์ ์ฒด์ ๋ณด์ ๊ณ์ ์ ์ฉ โ
corrected_selfie_bgr - ์ข
์ด ์์ญ ์ ์ธ ํ ํผ๋ถ ์์ญ
H๊ฐ์ ํ๊ท ์ ์ผ๋ก ๊ตฌํด์ ๋ํ ํผ๋ถ์ ์ฐ์ถ
- ์ฐธ์กฐ์ฉ ์ข
์ด ์ปจํฌ์ด ๊ฒ์ถ (
- ํผ์ค๋ ์ปฌ๋ฌ ๋ถ๋ฅ
classify_personal_color(true_skin_hsv)- Hue, Lightness, Saturation ๋ฑ์ ์์ ์งํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ ์ ์๋ ๊ณ์ ๋ณ ๊ธฐ์ค ๊ฐ๊ณผ ๋น๊ตํด
Spring,Summer,Autumn,Winter์ค ํ๋๋ฅผ ์ ํ
- Hue, Lightness, Saturation ๋ฑ์ ์์ ์งํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ ์ ์๋ ๊ณ์ ๋ณ ๊ธฐ์ค ๊ฐ๊ณผ ๋น๊ตํด
- ์๋ฅ ์์ ๋ถ์
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์ ์ด์ฉํด
- ์๋ณธ ์ด๋ฏธ์ง ์์ ์๋ฅ ์์ญ ์ค๊ณฝ ํ์
- ๋ํ ์์ ์นฉ๊ณผ ๋น์จ ๊ทธ๋ํ(ํ์ด ์ฐจํธ)
- Elbow ๊ธฐ๋ฒ ๊ฒฐ๊ณผ ๊ทธ๋ํ
- ๊ฒฐ๊ณผ๋ฌผ์
results/ํด๋์ PNG๋ก ์ ์ฅ
- Matplotlib์ ์ด์ฉํด
- 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)์ ๋ฐํ
- ์ถ์ ํ ํผ๋ถ์ HSV ๊ฐ์ ๋ฐ์ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ณ์ ํ๋ ํธ(ํค) ์ด๋ฆ(
- ํ์ผ ๋ก๋ ์, ๋ฏธ๋ฆฌ
tone_features๋ฅผ ๊ณ์ฐํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ
- ๊ณ์ ๋ณ 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)๋ฑ
- 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)๋ก ๋ฐํ
-
FastAPI ์๋ํฌ์ธํธ ์ ์
POST /personal-color:- Form-data๋ก ์
๋ก๋๋
selfie,reference์ด๋ฏธ์ง ํ์ผ์ ๋ฐ์ estimate_true_skin_color()โclassify_personal_color()์์ผ๋ก ํธ์ถ- JSON ํ์์ผ๋ก ํผ์ค๋ ํค(๊ณ์ ) ๋ฐ ๋ํ HSV, RGB ์ ๋ณด ์๋ต
- Form-data๋ก ์
๋ก๋๋
POST /clothes-color:- Form-data๋ก
selfie์ด๋ฏธ์ง๋ฅผ ๋ฐ์ get_face_skin_mask()โestimate_true_skin_color()(์๋ต ๊ฐ๋ฅ) โextract_clothes_mask()โ ์์ ํด๋ฌ์คํฐ๋ง- JSON์ผ๋ก ์๋ฅ ๋ํ ์์(
rgb)๊ณผ ๋น์จ(ratio)์ ๋ฐํ
- Form-data๋ก
POST /clothes-tone:- Form-data๋ก
selfie์ด๋ฏธ์ง๋ฅผ ๋ฐ์ extract_clothes_mask()โget_dominant_colors_from_mask()โclassify_tone_by_hsv()- ์๋ฅ ํค(๊ณ์ ) ์ด๋ฆ ๋ฐํ
- Form-data๋ก
-
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 -
๊ฒฐ๊ณผ๋ฌผ ์์
skin_mask.png: ์ถ์ถ๋ ํผ๋ถ ์์ญ ๋ง์คํฌ (ํฐ์ = ํผ๋ถ)corrected_selfie.jpg: ํ์ดํธ ๋ฐธ๋ฐ์ค ๋ณด์ ์ด ์ ์ฉ๋ ์ ์นดclothes_mask.png: GrabCut์ผ๋ก ์ถ์ถ๋ ์๋ฅ ์์ญ ๋ง์คํฌclothes_analysis.png: ์๋ฅ ๋ํ ์์ ๋ฐ ๋น์จ ์๊ฐํ (ํ์ด ์ฐจํธ + ์์ ์นฉ)