tarugaru commited on
Commit
361ce22
·
verified ·
1 Parent(s): 6d41fdf

Add second model

Browse files
Files changed (1) hide show
  1. app.py +41 -14
app.py CHANGED
@@ -10,8 +10,12 @@ from PIL import Image
10
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
11
  MODEL_PATH = os.path.join(BASE_DIR, "artifacts", "best_model.pt")
12
  LABELS_PATH = os.path.join(BASE_DIR, "data", "style_labels.json")
 
 
 
13
 
14
- class ArtStyleClassifier(nn.Module):
 
15
  def __init__(self, num_classes):
16
  super().__init__()
17
  self.backbone = timm.create_model("efficientnet_b0", pretrained=False, num_classes=0)
@@ -27,13 +31,18 @@ class ArtStyleClassifier(nn.Module):
27
  features = self.backbone(x)
28
  return self.classifier(features)
29
 
30
- with open(LABELS_PATH, "r") as f:
31
- style_to_idx = json.load(f)
32
- idx_to_style = {int(i): s for s, i in style_to_idx.items()}
 
33
 
34
- model = ArtStyleClassifier(num_classes=len(style_to_idx))
35
- model.load_state_dict(torch.load(MODEL_PATH, map_location=torch.device("cpu")))
36
- model.eval()
 
 
 
 
37
 
38
  transform = transforms.Compose([
39
  transforms.Resize((224, 224)),
@@ -41,11 +50,19 @@ transform = transforms.Compose([
41
  transforms.Normalize(mean=[0.485, 0.456, 0.406],
42
  std=[0.229, 0.224, 0.225]),
43
  ])
44
- def predict(image):
 
 
 
 
 
 
45
  if image is None:
46
  return "<p>No image provided.</p>"
 
47
  pil_image = Image.fromarray(image).convert("RGB")
48
  tensor = transform(pil_image).unsqueeze(0)
 
49
  with torch.no_grad():
50
  outputs = model(tensor)
51
  probs = torch.softmax(outputs, dim=1)[0]
@@ -53,14 +70,15 @@ def predict(image):
53
 
54
  medals = ["🥇", "🥈", "🥉"]
55
  colors = ["#4f46e5", "#7c3aed", "#a855f7"]
56
- html = "<div style='font-family:sans-serif;padding:10px'>"
 
57
  for i, (p, idx) in enumerate(zip(top_probs, top_idxs)):
58
- style = idx_to_style[idx.item()]
59
  pct = float(p.item()) * 100
60
  html += f"""
61
  <div style='margin-bottom:16px'>
62
  <div style='display:flex;justify-content:space-between;margin-bottom:4px'>
63
- <span style='font-weight:600'>{medals[i]} {style}</span>
64
  <span style='color:#666'>{pct:.1f}%</span>
65
  </div>
66
  <div style='background:#e5e7eb;border-radius:999px;height:12px'>
@@ -70,12 +88,21 @@ def predict(image):
70
  html += "</div>"
71
  return html
72
 
 
 
 
 
 
 
73
  demo = gr.Interface(
74
  fn=predict,
75
  inputs=gr.Image(label="Upload your artwork"),
76
- outputs=gr.HTML(label="Art Style Predictions"),
77
- title="Art Style Classifier",
78
- description="Upload a photo of your artwork to identify which art style it most resembles.",
 
 
 
79
  )
80
 
81
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
10
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
11
  MODEL_PATH = os.path.join(BASE_DIR, "artifacts", "best_model.pt")
12
  LABELS_PATH = os.path.join(BASE_DIR, "data", "style_labels.json")
13
+ # second model
14
+ ARTIST_MODEL_PATH = os.path.join(BASE_DIR, "artifacts", "best_artist_model.pt")
15
+ ARTIST_LABELS_PATH = os.path.join(BASE_DIR, "data", "artist_labels.json")
16
 
17
+ # define the model architecture (same as training) to load the weights correctly, num_classes will be altered when loading
18
+ class ArtClassifier(nn.Module):
19
  def __init__(self, num_classes):
20
  super().__init__()
21
  self.backbone = timm.create_model("efficientnet_b0", pretrained=False, num_classes=0)
 
31
  features = self.backbone(x)
32
  return self.classifier(features)
33
 
34
+ # helper function to load model and labels, returns model and idx_to_label dict
35
+ def load_model(model_path, labels_path):
36
+ with open(labels_path, "r") as f:
37
+ label_to_idx = json.load(f)
38
 
39
+ idx_to_label = {int(i): label for label, i in label_to_idx.items()}
40
+
41
+ model = ArtClassifier(num_classes=len(label_to_idx))
42
+ model.load_state_dict(torch.load(model_path, map_location=torch.device("cpu")))
43
+ model.eval()
44
+
45
+ return model, idx_to_label
46
 
47
  transform = transforms.Compose([
48
  transforms.Resize((224, 224)),
 
50
  transforms.Normalize(mean=[0.485, 0.456, 0.406],
51
  std=[0.229, 0.224, 0.225]),
52
  ])
53
+
54
+ # call the helper function to load both models and their corresponding idx_to_label mappings
55
+ style_model, idx_to_style = load_model(MODEL_PATH, LABELS_PATH)
56
+ artist_model, idx_to_artist = load_model(ARTIST_MODEL_PATH, ARTIST_LABELS_PATH)
57
+
58
+
59
+ def make_prediction_html(model, idx_to_label, image, title):
60
  if image is None:
61
  return "<p>No image provided.</p>"
62
+
63
  pil_image = Image.fromarray(image).convert("RGB")
64
  tensor = transform(pil_image).unsqueeze(0)
65
+
66
  with torch.no_grad():
67
  outputs = model(tensor)
68
  probs = torch.softmax(outputs, dim=1)[0]
 
70
 
71
  medals = ["🥇", "🥈", "🥉"]
72
  colors = ["#4f46e5", "#7c3aed", "#a855f7"]
73
+ html = f"<div style='font-family:sans-serif;padding:10px'><h3>{title}</h3>"
74
+
75
  for i, (p, idx) in enumerate(zip(top_probs, top_idxs)):
76
+ label = idx_to_label[idx.item()] # rename variable to fit broad use case (style or artist)
77
  pct = float(p.item()) * 100
78
  html += f"""
79
  <div style='margin-bottom:16px'>
80
  <div style='display:flex;justify-content:space-between;margin-bottom:4px'>
81
+ <span style='font-weight:600'>{medals[i]} {label}</span>
82
  <span style='color:#666'>{pct:.1f}%</span>
83
  </div>
84
  <div style='background:#e5e7eb;border-radius:999px;height:12px'>
 
88
  html += "</div>"
89
  return html
90
 
91
+ def predict(image):
92
+ style_html = make_prediction_html(style_model, idx_to_style, image, "Art Style Predictions")
93
+ artist_html = make_prediction_html(artist_model, idx_to_artist, image, "Artist Predictions")
94
+
95
+ return style_html, artist_html
96
+
97
  demo = gr.Interface(
98
  fn=predict,
99
  inputs=gr.Image(label="Upload your artwork"),
100
+ outputs=[
101
+ gr.HTML(label="Art Style Predictions"),
102
+ gr.HTML(label="Artist Predictions")
103
+ ],
104
+ title="Art Style + Artist Classifier",
105
+ description="Upload a photo of your artwork to identify which art style and artist's work it most resembles.",
106
  )
107
 
108
  demo.launch(server_name="0.0.0.0", server_port=7860)