File size: 3,706 Bytes
b1fe7e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""Gradio ์›น ๋ฐ๋ชจ: Food-101 101๊ฐœ ์Œ์‹ ํด๋ž˜์Šค ๋ถ„๋ฅ˜๊ธฐ.

์ด ํŒŒ์ผ์€ Hugging Face Spaces์—์„œ ์ž๋™ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค (app_file: app.py).

์ž‘๋™ ๋ฐฉ์‹:
    1) ๊ธฐ๋ณธ๊ฐ’: ํ—ˆ๋ธŒ์˜ 'nateraw/food' ๊ณต๊ฐœ ๋ชจ๋ธ ์‚ฌ์šฉ
       (Pretrained ResNet + Food-101 fine-tuning์œผ๋กœ ~90% ์ •ํ™•๋„)
    2) ์ง์ ‘ ํ•™์Šตํ•œ MyResNet์ด ์žˆ๋‹ค๋ฉด ์•„๋ž˜ USE_CUSTOM_RESNET=True๋กœ ๋ณ€๊ฒฝ
"""
import torch
import torch.nn.functional as F
import gradio as gr


# ============================================================
# ์„ค์ •
# ============================================================
USE_CUSTOM_RESNET = False                 # True: ์ž์ฒด MyResNet ์‚ฌ์šฉ
MODEL_ID = "nateraw/food"                 # ๋˜๋Š” "your-username/my-resnet18-food101"


# ============================================================
# ๋ชจ๋ธ ๋กœ๋”ฉ
# ============================================================
print(f"๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘: {MODEL_ID}")

if USE_CUSTOM_RESNET:
    # ์ž์ฒด ํ•™์Šตํ•œ MyResNet ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
    from configuration_myresnet import MyResNetConfig
    from modeling_myresnet import MyResNetForImageClassification
    from torchvision.transforms import Compose, Resize, ToTensor, Normalize

    model = MyResNetForImageClassification.from_pretrained(MODEL_ID)
    _transform = Compose([
        Resize((224, 224)),
        ToTensor(),
        Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])

    def preprocess(image):
        return _transform(image.convert("RGB")).unsqueeze(0)

else:
    # ๊ณต๊ฐœ ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (AutoImageProcessor๊ฐ€ ์ „์ฒ˜๋ฆฌ ์ž๋™ ์ฒ˜๋ฆฌ)
    from transformers import AutoImageProcessor, AutoModelForImageClassification

    processor = AutoImageProcessor.from_pretrained(MODEL_ID)
    model = AutoModelForImageClassification.from_pretrained(MODEL_ID)

    def preprocess(image):
        inputs = processor(images=image.convert("RGB"), return_tensors="pt")
        return inputs["pixel_values"]


model.eval()
device = "cuda" if torch.cuda.is_available() else "cpu"
model = model.to(device)
id2label = model.config.id2label

print(f"๋””๋ฐ”์ด์Šค: {device}")
print(f"ํด๋ž˜์Šค ์ˆ˜: {len(id2label)}")


# ============================================================
# ์˜ˆ์ธก ํ•จ์ˆ˜
# ============================================================
def classify(image):
    """์ด๋ฏธ์ง€๋ฅผ Top-5 ์Œ์‹ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค."""
    if image is None:
        return {}

    pixel_values = preprocess(image).to(device)

    with torch.no_grad():
        logits = model(pixel_values=pixel_values).logits
    probs = F.softmax(logits, dim=-1)[0].cpu()

    top5_probs, top5_idx = torch.topk(probs, k=5)

    return {
        id2label[idx.item()].replace("_", " ").title(): float(prob)
        for prob, idx in zip(top5_probs, top5_idx)
    }


# ============================================================
# Gradio UI
# ============================================================
TITLE = "๐Ÿฝ๏ธ Food Image Classifier"

DESCRIPTION = """
์Œ์‹ ์‚ฌ์ง„์„ ์—…๋กœ๋“œํ•˜๋ฉด **Food-101** ๋ฐ์ดํ„ฐ์…‹์˜ 101๊ฐœ ์Œ์‹ ์ค‘ ๊ฐ€์žฅ ์œ ์‚ฌํ•œ ๊ฒƒ์„ ์ฐพ์•„ **Top-5** ๊ฒฐ๊ณผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

**์ง€์› ์Œ์‹ ์˜ˆ์‹œ:** ๐Ÿ• Pizza ยท ๐Ÿฃ Sushi ยท ๐Ÿ” Hamburger ยท ๐Ÿฅฉ Steak ยท ๐Ÿฅž Pancakes ยท ๐Ÿœ Ramen ยท ๐Ÿฆ Ice Cream ยท ๐Ÿฅ˜ Bibimbap ยท ๐ŸŒฎ Tacos ยท ๐ŸฅŸ Gyoza ยท ...

**๋ชจ๋ธ:** ResNet-18 (Pretrained on ImageNet, Fine-tuned on Food-101)
"""

demo = gr.Interface(
    fn=classify,
    inputs=gr.Image(type="pil", label="์Œ์‹ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ"),
    outputs=gr.Label(num_top_classes=5, label="์˜ˆ์ธก ๊ฒฐ๊ณผ"),
    title=TITLE,
    description=DESCRIPTION,
    flagging_mode="never",
)


if __name__ == "__main__":
    demo.launch()