simplify codebase
Browse files- app.py +87 -7
- core.py +0 -74
- interactivity.py +0 -49
app.py
CHANGED
|
@@ -1,14 +1,94 @@
|
|
| 1 |
-
|
|
|
|
| 2 |
import argparse
|
| 3 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
if __name__ == "__main__":
|
| 6 |
BACKEND_OPTIONS = ["gradio", "qt", "mpl"]
|
| 7 |
parser = argparse.ArgumentParser()
|
| 8 |
parser.add_argument("-b", "--backend", type=str,
|
| 9 |
choices=BACKEND_OPTIONS, default=BACKEND_OPTIONS[0])
|
| 10 |
-
args = parser.parse_args()
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
|
|
|
| 1 |
+
|
| 2 |
+
import numpy as np
|
| 3 |
import argparse
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from interactive_pipe import (
|
| 6 |
+
interactive_pipeline, interactive, Curve, SingleCurve
|
| 7 |
+
)
|
| 8 |
+
from transformers import pipeline
|
| 9 |
+
|
| 10 |
+
# -------------------
|
| 11 |
+
# Processing blocks
|
| 12 |
+
# -------------------
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
@interactive(
|
| 16 |
+
radius=(0.005, [0., 0.01]),
|
| 17 |
+
isotropy=(0.5, [0., 1.]),
|
| 18 |
+
)
|
| 19 |
+
def gen_color(
|
| 20 |
+
radius: int = 0, # discrete slider (int)
|
| 21 |
+
isotropy: float = 0., # continuous slider (float)
|
| 22 |
+
):
|
| 23 |
+
out = np.zeros((256, 256, 3)) # Initial background set to black
|
| 24 |
+
out[:, :, 1] = 0.5
|
| 25 |
+
x, y = np.meshgrid(np.linspace(-1, 1, 256), np.linspace(-1, 1, 256))
|
| 26 |
+
# ball positions and colors: [(cx, cy), [R, G, B]]
|
| 27 |
+
balls = [
|
| 28 |
+
((0, 0), [0.8, 0.8, 0.8]), # Cue ball (white)
|
| 29 |
+
((0.0, -0.6), [1, 1, 0]),
|
| 30 |
+
((-0.15, -0.85), [1, 0, 0]),
|
| 31 |
+
((0.0, -0.85), [0, 1, 0]),
|
| 32 |
+
((0.15, -0.85), [1, 0, 0]),
|
| 33 |
+
((-0.075, -0.725), [1, 1, 0]),
|
| 34 |
+
((0.075, -0.725), [1, 0, 0]),
|
| 35 |
+
]
|
| 36 |
+
if isotropy <= 0.5:
|
| 37 |
+
# 0.5 -> 1
|
| 38 |
+
x_scale, y_scale = isotropy, 1
|
| 39 |
+
else:
|
| 40 |
+
x_scale, y_scale = 1, 1-isotropy
|
| 41 |
+
for (cx, cy), color in balls:
|
| 42 |
+
r = (x_scale * (x - cx) ** 2 + y_scale * (y - cy) ** 2) < radius
|
| 43 |
+
out[r, :] = color # Set the color for each ball based on its position
|
| 44 |
+
|
| 45 |
+
return out
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
@interactive(detect=(True, "Enable classification"))
|
| 49 |
+
def apply_classifier(img, context={}, detect=False):
|
| 50 |
+
result = {}
|
| 51 |
+
if detect:
|
| 52 |
+
if not context.get("clf", None):
|
| 53 |
+
context["clf"] = pipeline("image-classification")
|
| 54 |
+
result = context["clf"](Image.fromarray((img*255).astype(np.uint8)))
|
| 55 |
+
else:
|
| 56 |
+
result = [{"score": 0., "label": "No classification"}]*5
|
| 57 |
+
context["result"] = result
|
| 58 |
+
# return result
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def display_result(context={}):
|
| 62 |
+
result_dict = context.get("result", [])
|
| 63 |
+
curves = [
|
| 64 |
+
SingleCurve(
|
| 65 |
+
x=[id, id, id+1, id+1],
|
| 66 |
+
y=[0, r['score'], r['score'], 0],
|
| 67 |
+
label=r["label"], style="-"
|
| 68 |
+
)
|
| 69 |
+
for id, r in enumerate(result_dict)]
|
| 70 |
+
result_curves = Curve(curves, ylim=[0, 1])
|
| 71 |
+
return result_curves
|
| 72 |
+
|
| 73 |
+
# -------------------
|
| 74 |
+
# Pipeline definition
|
| 75 |
+
# -------------------
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def tutorial_pipeline():
|
| 79 |
+
inp = gen_color()
|
| 80 |
+
apply_classifier(inp)
|
| 81 |
+
result_curve = display_result()
|
| 82 |
+
return inp, result_curve
|
| 83 |
+
|
| 84 |
|
| 85 |
if __name__ == "__main__":
|
| 86 |
BACKEND_OPTIONS = ["gradio", "qt", "mpl"]
|
| 87 |
parser = argparse.ArgumentParser()
|
| 88 |
parser.add_argument("-b", "--backend", type=str,
|
| 89 |
choices=BACKEND_OPTIONS, default=BACKEND_OPTIONS[0])
|
| 90 |
+
args = parser.parse_args()
|
| 91 |
+
md_description = "# 🔍 EXAMPLE Interactive-pipe + machine learning \n"
|
| 92 |
+
md_description += "```python\n"+open(__file__, 'r').read()+"```\n"
|
| 93 |
+
interactive_pipeline(gui=args.backend, markdown_description=md_description)(
|
| 94 |
+
tutorial_pipeline)()
|
core.py
DELETED
|
@@ -1,74 +0,0 @@
|
|
| 1 |
-
# "Production code"
|
| 2 |
-
import numpy as np
|
| 3 |
-
from PIL import Image
|
| 4 |
-
from interactive_pipe import interactive_pipeline, interactive, Curve, SingleCurve
|
| 5 |
-
from transformers import pipeline
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
@interactive(
|
| 9 |
-
radius=(0.005, [0., 0.01]),
|
| 10 |
-
isotropy=(0.5, [0., 1.]),
|
| 11 |
-
)
|
| 12 |
-
def gen_color(
|
| 13 |
-
radius: int = 0, # discrete slider (int)
|
| 14 |
-
isotropy: float = 0., # continuous slider (float)
|
| 15 |
-
):
|
| 16 |
-
out = np.zeros((256, 256, 3)) # Initial background set to black
|
| 17 |
-
out[:, :, 1] = 0.5
|
| 18 |
-
x, y = np.meshgrid(np.linspace(-1, 1, 256), np.linspace(-1, 1, 256))
|
| 19 |
-
# ball positions and colors: [(cx, cy), [R, G, B]]
|
| 20 |
-
balls = [
|
| 21 |
-
((0, 0), [0.8, 0.8, 0.8]), # Cue ball (white)
|
| 22 |
-
((0.0, -0.6), [1, 1, 0]),
|
| 23 |
-
((-0.15, -0.85), [1, 0, 0]),
|
| 24 |
-
((0.0, -0.85), [0, 1, 0]),
|
| 25 |
-
((0.15, -0.85), [1, 0, 0]),
|
| 26 |
-
((-0.075, -0.725), [1, 1, 0]),
|
| 27 |
-
((0.075, -0.725), [1, 0, 0]),
|
| 28 |
-
]
|
| 29 |
-
if isotropy <= 0.5:
|
| 30 |
-
# 0.5 -> 1
|
| 31 |
-
x_scale, y_scale = isotropy, 1
|
| 32 |
-
else:
|
| 33 |
-
x_scale, y_scale = 1, 1-isotropy
|
| 34 |
-
for (cx, cy), color in balls:
|
| 35 |
-
r = (x_scale * (x - cx) ** 2 + y_scale * (y - cy) ** 2) < radius
|
| 36 |
-
out[r, :] = color # Set the color for each ball based on its position
|
| 37 |
-
|
| 38 |
-
return out
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
@interactive(detect=(True, "Enable classification"))
|
| 42 |
-
def apply_classifier(img, context={}, detect=False):
|
| 43 |
-
result = {}
|
| 44 |
-
if detect:
|
| 45 |
-
if not context.get("clf", None):
|
| 46 |
-
context["clf"] = pipeline("image-classification")
|
| 47 |
-
result = context["clf"](Image.fromarray((img*255).astype(np.uint8)))
|
| 48 |
-
else:
|
| 49 |
-
result = [{"score": 0., "label": "No classification"}]*5
|
| 50 |
-
context["result"] = result
|
| 51 |
-
# return result
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
def display_result(context={}):
|
| 55 |
-
result_dict = context.get("result", [])
|
| 56 |
-
curves = [
|
| 57 |
-
SingleCurve(
|
| 58 |
-
x=[id, id, id+1, id+1],
|
| 59 |
-
y=[0, r['score'], r['score'], 0],
|
| 60 |
-
label=r["label"], style="-"
|
| 61 |
-
)
|
| 62 |
-
for id, r in enumerate(result_dict)]
|
| 63 |
-
result_curves = Curve(curves, ylim=[0, 1])
|
| 64 |
-
return result_curves
|
| 65 |
-
# -------------------
|
| 66 |
-
# Pipeline definition
|
| 67 |
-
# -------------------
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
def tutorial_pipeline():
|
| 71 |
-
inp = gen_color()
|
| 72 |
-
apply_classifier(inp)
|
| 73 |
-
result_curve = display_result()
|
| 74 |
-
return inp, result_curve
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interactivity.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
| 1 |
-
from interactive_pipe import interactive_pipeline, interactive
|
| 2 |
-
from core import (gen_color, tutorial_pipeline)
|
| 3 |
-
import argparse
|
| 4 |
-
# --------------------------------------------------------------
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
def add_interactivity() -> None:
|
| 8 |
-
# Depending on the level of control you want,
|
| 9 |
-
# you can add more or less controls to the pipeline
|
| 10 |
-
# interactive(
|
| 11 |
-
# ratio=(0.5, [0., 1.], "Side by Side comparison")
|
| 12 |
-
# )(compare_by_splitting)
|
| 13 |
-
# interactive(
|
| 14 |
-
# bnw=(True, "Black and White")
|
| 15 |
-
# )(change_color)
|
| 16 |
-
# interactive(
|
| 17 |
-
# effect=("flip", ["flip", "mirror", "flip+mirror", "identity"])
|
| 18 |
-
# )(modify_geometry)
|
| 19 |
-
# interactive(
|
| 20 |
-
# frequency=(80, [1, 100]),
|
| 21 |
-
# isotropy=(0.8, [0.1, 1.])
|
| 22 |
-
# )(gen_color)
|
| 23 |
-
pass
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
def run_interactive_pipeline(
|
| 27 |
-
backend: str = "gradio",
|
| 28 |
-
markdown_description: str = "# Tuto"
|
| 29 |
-
) -> None:
|
| 30 |
-
add_interactivity()
|
| 31 |
-
playable_tutorial_pipeline = interactive_pipeline(
|
| 32 |
-
gui=backend,
|
| 33 |
-
cache=True,
|
| 34 |
-
markdown_description=markdown_description,
|
| 35 |
-
context={"initialized_param": 42}
|
| 36 |
-
# context is shared between processing blocks.
|
| 37 |
-
# Initialization allow to pre-load a neural network for example.
|
| 38 |
-
)(tutorial_pipeline)
|
| 39 |
-
playable_tutorial_pipeline()
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
if __name__ == "__main__":
|
| 43 |
-
BACKEND_OPTIONS = ["gradio", "qt"]
|
| 44 |
-
parser = argparse.ArgumentParser()
|
| 45 |
-
parser.add_argument("-b", "--backend", type=str,
|
| 46 |
-
choices=BACKEND_OPTIONS, default=BACKEND_OPTIONS[0])
|
| 47 |
-
args = parser.parse_args()
|
| 48 |
-
run_interactive_pipeline(backend=args.backend,
|
| 49 |
-
markdown_description="# Tutorial")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|