Philipp Allgeuer commited on
Commit
7ad5fd3
·
1 Parent(s): f0f9d74

Revamp app structure

Browse files
Files changed (4) hide show
  1. app.py +82 -49
  2. app_novic.py +35 -0
  3. novic +1 -1
  4. requirements.txt +6 -0
app.py CHANGED
@@ -4,70 +4,103 @@
4
  # Imports
5
  import os
6
  import glob
7
- import random
8
- import pathlib
9
- import subprocess
10
  from typing import Optional
11
  import PIL.Image
12
  import gradio as gr
 
13
 
14
- # Ensure access to NOVIC code
15
- REPO_ROOT = pathlib.Path(__file__).parent.resolve()
16
- SENTINEL = REPO_ROOT / '.submodules_done'
17
- if not SENTINEL.exists():
18
- print("Initialising git submodules...")
19
- subprocess.run(['git', 'submodule', 'update', '--init', '--recursive'], cwd=REPO_ROOT, check=True)
20
- SENTINEL.touch()
21
 
22
  # Sample images
23
  IMAGE_EXTS = ('jpg', 'jpeg', 'png', 'webp')
24
  SAMPLE_IMAGES = sorted(image_path for image_ext in IMAGE_EXTS for image_path in glob.glob(os.path.join('sample_images', f'*.{image_ext}')))
25
 
26
- # Classify image
27
- def classify_image(image: Optional[PIL.Image.Image]) -> dict[str, float]:
28
-
29
- if image is None:
30
  return {}
31
-
32
- labels = ('thing', 'item', 'stuff', 'object', 'entity')
33
- probs = [random.random() for _ in labels]
34
- prob_sum = sum(probs)
35
- return {label: prob / prob_sum for label, prob in zip(labels, probs)}
36
 
37
  # Gradio UI
38
- demo = gr.Interface(
39
- fn=classify_image,
40
- inputs=gr.Image(
41
- height=400,
42
- image_mode='RGB',
43
- type='pil',
44
- label='Input image',
45
- show_label=True,
46
- interactive=True,
47
- show_fullscreen_button=True,
48
- ),
49
- outputs=gr.Label(
50
- num_top_classes=3,
51
- label='Predicted label',
52
- show_label=True,
53
- show_heading=True,
54
- ),
55
- examples=SAMPLE_IMAGES,
56
- examples_per_page=20,
57
- live=True,
58
- title="🖼️ NOVIC: Unconstrained Open Vocabulary Image Classification",
59
- description="*Select* an image from the examples shown below **OR** *Upload* an image file from your computer **OR** *Capture* an image using an attached camera **OR** *Copy-paste* an image from your clipboard. The label predictions on the right will update automatically!",
60
- article=None,
61
  theme=None,
62
- flagging_mode='never',
63
  analytics_enabled=True,
64
- api_name='classify',
65
- allow_duplication=False,
66
- clear_btn=gr.Button(value='Clear', variant='secondary'),
67
- show_progress='full',
68
  fill_width=False,
69
- deep_link=True,
70
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  # Run demo
73
  if __name__ == '__main__':
 
4
  # Imports
5
  import os
6
  import glob
 
 
 
7
  from typing import Optional
8
  import PIL.Image
9
  import gradio as gr
10
+ import app_novic
11
 
12
+ # Model checkpoints
13
+ MODEL_CHECKPOINTS = {
14
+ 'NOVIC SigLIP B/16 FT2': os.path.join('ovod_20240610_105233', 'ovod_chunk0899_20240612_005748.train'),
15
+ 'NOVIC SigLIP SO/14 FT2': os.path.join('ovod_20240626_001447', 'ovod_chunk0899_20240627_112729.train'),
16
+ 'NOVIC DFN-5B H/14-378 FT2': os.path.join('ovod_20240620_162925', 'ovod_chunk0899_20240621_202727.train'),
17
+ 'NOVIC DFN-5B H/14-378 FT0': os.path.join('ovod_20240628_142131', 'ovod_chunk0433_20240630_235415.train'),
18
+ }
19
 
20
  # Sample images
21
  IMAGE_EXTS = ('jpg', 'jpeg', 'png', 'webp')
22
  SAMPLE_IMAGES = sorted(image_path for image_ext in IMAGE_EXTS for image_path in glob.glob(os.path.join('sample_images', f'*.{image_ext}')))
23
 
24
+ # Classify an image
25
+ def classify_image(image: Optional[PIL.Image.Image], model: Optional[str]) -> dict[str, float]:
26
+ if image is None or model is None:
 
27
  return {}
28
+ checkpoint = os.path.join('checkpoints', MODEL_CHECKPOINTS[model])
29
+ return app_novic.classify_image(image=image, checkpoint=checkpoint)
 
 
 
30
 
31
  # Gradio UI
32
+ with gr.Blocks(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  theme=None,
 
34
  analytics_enabled=True,
35
+ title="🖼️ NOVIC Demo",
 
 
 
36
  fill_width=False,
37
+ ) as demo:
38
+
39
+ gr.HTML("<h1 style='text-align: center; margin-bottom: 1rem'>🖼️ NOVIC: Unconstrained Open Vocabulary Image Classification</h1><div style='text-align: center'><i>Select</i> an example image below <b>OR</b> <i>Upload</i> an image file <b>OR</b> <i>Capture</i> a camera image <b>OR</b> <i>Copy-paste</i> an image from your clipboard ⇒ The label predictions on the right will update automatically!<br>Note that CPU inference is naturally <i>much</i> slower than GPU inference.</div>")
40
+
41
+ with gr.Row(equal_height=True):
42
+
43
+ with gr.Column(scale=1):
44
+ input_model = gr.Dropdown(
45
+ choices=list(MODEL_CHECKPOINTS),
46
+ value='NOVIC DFN-5B H/14-378 FT0',
47
+ type='value',
48
+ multiselect=False,
49
+ allow_custom_value=False,
50
+ filterable=False,
51
+ label='NOVIC model',
52
+ show_label=True,
53
+ interactive=True,
54
+ )
55
+ input_image = gr.Image(
56
+ height=400,
57
+ image_mode='RGB',
58
+ type='pil',
59
+ label='Input image',
60
+ show_label=True,
61
+ interactive=True,
62
+ show_fullscreen_button=True,
63
+ )
64
+
65
+ with gr.Column(scale=1):
66
+ output_label = gr.Label(
67
+ num_top_classes=3,
68
+ label='Predicted label',
69
+ show_label=True,
70
+ scale=1,
71
+ show_heading=True,
72
+ )
73
+
74
+ with gr.Row(equal_height=True):
75
+ gr.ClearButton(
76
+ components=[input_image],
77
+ value='Clear input image',
78
+ variant='secondary',
79
+ size='lg',
80
+ scale=1,
81
+ )
82
+ gr.DeepLinkButton(
83
+ variant='secondary',
84
+ size='lg',
85
+ scale=1,
86
+ )
87
+
88
+ gr.Examples(
89
+ examples=SAMPLE_IMAGES,
90
+ inputs=input_image,
91
+ cache_examples=False,
92
+ examples_per_page=100,
93
+ label='Example images',
94
+ )
95
+
96
+ gr.on(
97
+ triggers=[input_image.change, input_model.change],
98
+ fn=classify_image,
99
+ inputs=[input_image, input_model], # noqa
100
+ outputs=output_label,
101
+ api_name='classify',
102
+ show_progress='full',
103
+ )
104
 
105
  # Run demo
106
  if __name__ == '__main__':
app_novic.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NOVIC interface
2
+
3
+ # Imports
4
+ import sys
5
+ import random # TODO: TEMP
6
+ import pathlib
7
+ import subprocess
8
+ import PIL.Image
9
+ # TODO: Then start coding infer.py (ANY additional import has to be clarified with novic_spaces/requirements.txt (pip install -r requirements.txt) and novic/requirements-infer.txt
10
+
11
+ # Ensure access to NOVIC code
12
+ REPO_ROOT = pathlib.Path(__file__).parent.resolve()
13
+ NOVIC_DIR = REPO_ROOT / 'novic'
14
+ NOVIC_TEST = NOVIC_DIR / '__init__.py'
15
+ if not NOVIC_TEST.exists():
16
+ print("Initialising git submodules as NOVIC code was not found yet...")
17
+ subprocess.run(['git', 'submodule', 'update', '--init', '--recursive'], cwd=REPO_ROOT, check=True)
18
+ if not NOVIC_TEST.exists():
19
+ raise RuntimeError("Failed to find NOVIC code")
20
+ if str(NOVIC_DIR) not in sys.path:
21
+ sys.path.insert(0, str(NOVIC_DIR))
22
+
23
+ # NOVIC imports
24
+ import infer # TODO: TEMP
25
+ print(infer) # TODO: TEMP
26
+
27
+ # Classify an image
28
+ def classify_image(image: PIL.Image.Image, checkpoint: str) -> dict[str, float]:
29
+ # TODO: TEMP
30
+ print(image, checkpoint)
31
+ labels = ('thing', 'item', 'stuff', 'object', 'entity')
32
+ probs = [random.random() for _ in labels]
33
+ prob_sum = sum(probs)
34
+ return {label: prob / prob_sum for label, prob in zip(labels, probs)}
35
+ # EOF
novic CHANGED
@@ -1 +1 @@
1
- Subproject commit bd292d4b22db87fd04b213e8b4184b5d6fbfdc41
 
1
+ Subproject commit 553f618ae2cbea281ff2926a526e1cfa23e20086
requirements.txt CHANGED
@@ -1 +1,7 @@
 
 
 
1
  pillow
 
 
 
 
1
+ # python>=3.10
2
+ numpy
3
+ open_clip_torch==2.23
4
  pillow
5
+ torch
6
+ tqdm
7
+ unidecode