Files changed (1) hide show
  1. app.py +40 -17
app.py CHANGED
@@ -1,24 +1,32 @@
1
- import aiohttp
2
  import io
3
  import random
4
  import panel as pn
 
5
 
6
  from PIL import Image
7
 
8
  from transformers import CLIPProcessor, CLIPModel
9
  from typing import List, Tuple
10
 
11
- pn.extension(design='bootstrap', sizing_mode="stretch_width")
 
 
 
 
 
 
 
 
 
12
 
13
  async def random_url(_):
14
- api_url = random.choice([
15
- "https://api.thecatapi.com/v1/images/search",
16
- "https://api.thedogapi.com/v1/images/search"
17
- ])
18
  async with aiohttp.ClientSession() as session:
19
  async with session.get(api_url) as resp:
20
  return (await resp.json())[0]["url"]
21
 
 
22
  @pn.cache
23
  def load_processor_model(
24
  processor_name: str, model_name: str
@@ -54,33 +62,37 @@ async def process_inputs(class_names: List[str], image_url: str):
54
  High level function that takes in the user inputs and returns the
55
  classification results as panel objects.
56
  """
 
57
  if not image_url:
58
- yield '## Provide an image URL'
59
  return
60
- yield '## Fetching image and running model βš™'
 
61
  pil_img = await open_image_url(image_url)
62
- img = pn.pane.Image(pil_img, height=400, align='center')
63
 
64
  class_items = class_names.split(",")
65
  class_likelihoods = get_similarity_scores(class_items, pil_img)
66
 
67
  # build the results column
68
- results = pn.Column("## πŸŽ‰ Here are the results!", img)
69
 
70
  for class_item, class_likelihood in zip(class_items, class_likelihoods):
71
  row_label = pn.widgets.StaticText(
72
- name=class_item.strip(), value=f"{class_likelihood:.2%}", align='center'
73
  )
74
  row_bar = pn.indicators.Progress(
75
  value=int(class_likelihood * 100),
76
  sizing_mode="stretch_width",
77
  bar_color="secondary",
78
  margin=(0, 10),
79
- design=pn.theme.Material
80
  )
81
  results.append(pn.Column(row_label, row_bar))
 
82
  yield results
83
 
 
84
  # create widgets
85
  randomize_url = pn.widgets.Button(name="Randomize URL", align="end")
86
 
@@ -95,25 +107,36 @@ class_names = pn.widgets.TextInput(
95
  )
96
 
97
  input_widgets = pn.Column(
98
- "## 😊 Click randomize or paste a URL to start classifying!",
99
  pn.Row(image_url, randomize_url),
100
  class_names,
101
  )
102
 
103
  # add interactivity
104
- interactive_result = pn.bind(
105
- process_inputs, image_url=image_url, class_names=class_names
 
106
  )
107
 
 
 
 
 
 
 
 
 
108
  # create dashboard
109
  main = pn.WidgetBox(
110
  input_widgets,
111
  interactive_result,
 
112
  )
113
 
 
114
  pn.template.BootstrapTemplate(
115
- title="Panel Image Classification Demo",
116
  main=main,
117
  main_max_width="min(50%, 698px)",
118
  header_background="#F08080",
119
- ).servable(title="Panel Image Classification Demo");
 
 
1
  import io
2
  import random
3
  import panel as pn
4
+ import aiohttp
5
 
6
  from PIL import Image
7
 
8
  from transformers import CLIPProcessor, CLIPModel
9
  from typing import List, Tuple
10
 
11
+ pn.extension(design="bootstrap", sizing_mode="stretch_width")
12
+
13
+ ICON_URLS = {
14
+ "brand-github": "https://github.com/holoviz/panel",
15
+ "brand-twitter": "https://twitter.com/Panel_Org",
16
+ "brand-linkedin": "https://www.linkedin.com/company/panel-org",
17
+ "message-circle": "https://discourse.holoviz.org/",
18
+ "brand-discord": "https://discord.gg/AXRHnJU6sP",
19
+ }
20
+
21
 
22
  async def random_url(_):
23
+ pet = random.choice(["cat", "dog"])
24
+ api_url = f"https://api.the{pet}api.com/v1/images/search"
 
 
25
  async with aiohttp.ClientSession() as session:
26
  async with session.get(api_url) as resp:
27
  return (await resp.json())[0]["url"]
28
 
29
+
30
  @pn.cache
31
  def load_processor_model(
32
  processor_name: str, model_name: str
 
62
  High level function that takes in the user inputs and returns the
63
  classification results as panel objects.
64
  """
65
+ main.disabled = True
66
  if not image_url:
67
+ yield "##### ⚠️ Provide an image URL"
68
  return
69
+
70
+ yield "##### βš™ Fetching image and running model..."
71
  pil_img = await open_image_url(image_url)
72
+ img = pn.pane.Image(pil_img, height=400, align="center")
73
 
74
  class_items = class_names.split(",")
75
  class_likelihoods = get_similarity_scores(class_items, pil_img)
76
 
77
  # build the results column
78
+ results = pn.Column("##### πŸŽ‰ Here are the results!", img)
79
 
80
  for class_item, class_likelihood in zip(class_items, class_likelihoods):
81
  row_label = pn.widgets.StaticText(
82
+ name=class_item.strip(), value=f"{class_likelihood:.2%}", align="center"
83
  )
84
  row_bar = pn.indicators.Progress(
85
  value=int(class_likelihood * 100),
86
  sizing_mode="stretch_width",
87
  bar_color="secondary",
88
  margin=(0, 10),
89
+ design=pn.theme.Material,
90
  )
91
  results.append(pn.Column(row_label, row_bar))
92
+ main.disabled = False
93
  yield results
94
 
95
+
96
  # create widgets
97
  randomize_url = pn.widgets.Button(name="Randomize URL", align="end")
98
 
 
107
  )
108
 
109
  input_widgets = pn.Column(
110
+ "##### 😊 Click randomize or paste a URL to start classifying!",
111
  pn.Row(image_url, randomize_url),
112
  class_names,
113
  )
114
 
115
  # add interactivity
116
+ interactive_result = pn.panel(
117
+ pn.bind(process_inputs, image_url=image_url, class_names=class_names),
118
+ height=600,
119
  )
120
 
121
+ # add footer
122
+ footer_row = pn.Row(pn.Spacer(), align="center")
123
+ for icon, url in ICON_URLS.items():
124
+ href_button = pn.widgets.Button(icon=icon, width=35, height=35)
125
+ href_button.js_on_click(code=f"window.open('{url}')")
126
+ footer_row.append(href_button)
127
+ footer_row.append(pn.Spacer())
128
+
129
  # create dashboard
130
  main = pn.WidgetBox(
131
  input_widgets,
132
  interactive_result,
133
+ footer_row,
134
  )
135
 
136
+ title = "Panel Demo - Image Classification"
137
  pn.template.BootstrapTemplate(
138
+ title=title,
139
  main=main,
140
  main_max_width="min(50%, 698px)",
141
  header_background="#F08080",
142
+ ).servable(title=title)