| """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 |
| MODEL_ID = "nateraw/food" |
|
|
|
|
| |
| |
| |
| print(f"๋ชจ๋ธ ๋ก๋ฉ ์ค: {MODEL_ID}") |
|
|
| if USE_CUSTOM_RESNET: |
| |
| 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: |
| |
| 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) |
| } |
|
|
|
|
| |
| |
| |
| 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() |
|
|