interactive-pipe 0.6.1__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {interactive_pipe-0.6.1/src/interactive_pipe.egg-info → interactive_pipe-0.7.0}/PKG-INFO +39 -26
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/pyproject.toml +3 -1
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/readme.md +37 -26
- interactive_pipe-0.7.0/src/interactive_pipe/graphical/gradio_control.py +95 -0
- interactive_pipe-0.7.0/src/interactive_pipe/graphical/gradio_gui.py +173 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/choose_backend.py +2 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0/src/interactive_pipe.egg-info}/PKG-INFO +39 -26
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/SOURCES.txt +2 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/requires.txt +2 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/LICENSE +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/setup.cfg +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/cache.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/engine.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/filter.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/graph.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/pipeline.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/core/signature.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/curves.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/data.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/image.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/parameters.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/gui.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_control.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_gui.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_window.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/nb_control.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/nb_gui.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/qt_control.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/qt_gui.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/window.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/control.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/keyboard.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/pipeline.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/__init__.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/_private.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/control_abbreviation.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/filter_decorator.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/keyword_args_analyzer.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/pipeline_decorator.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/thirdparty/images_openai_api.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/thirdparty/music_spotify.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/dependency_links.txt +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/top_level.txt +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_cache.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_control_abbreviations.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_controller.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_core.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_curves.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_decorator.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_engine.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_filter.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_headless.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_image.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_parameters.py +0 -0
- {interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/test/test_recorder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: interactive_pipe
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!
|
|
5
5
|
Author-email: Balthazar Neveu <balthazarneveu@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/balthazarneveu/interactive_pipe
|
|
@@ -21,6 +21,7 @@ Requires-Dist: opencv_python_headless>=4.8.1.78
|
|
|
21
21
|
Requires-Dist: pytest>=6.2.5
|
|
22
22
|
Requires-Dist: ipywidgets>=8.0.7
|
|
23
23
|
Requires-Dist: pandas
|
|
24
|
+
Requires-Dist: gradio
|
|
24
25
|
Provides-Extra: qt6
|
|
25
26
|
Requires-Dist: PyQt6>=6.5.2; extra == "qt6"
|
|
26
27
|
Requires-Dist: PyQt6_sip>=13.5.2; extra == "qt6"
|
|
@@ -39,6 +40,7 @@ Requires-Dist: opencv_python_headless>=4.8.1.78; extra == "full"
|
|
|
39
40
|
Requires-Dist: pytest>=6.2.5; extra == "full"
|
|
40
41
|
Requires-Dist: ipywidgets>=8.0.7; extra == "full"
|
|
41
42
|
Requires-Dist: pandas; extra == "full"
|
|
43
|
+
Requires-Dist: gradio; extra == "full"
|
|
42
44
|
|
|
43
45
|
# `interactive_pipe`
|
|
44
46
|
|
|
@@ -93,7 +95,7 @@ pip install -e ".[full]"
|
|
|
93
95
|
|
|
94
96
|
## :scroll: Features
|
|
95
97
|
|
|
96
|
-
**Version 0.
|
|
98
|
+
**Version 0.7.0**
|
|
97
99
|
- Modular multi-image processing filters
|
|
98
100
|
- Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
|
|
99
101
|
- Support in jupyter notebooks
|
|
@@ -101,6 +103,7 @@ pip install -e ".[full]"
|
|
|
101
103
|
- Cache intermediate results in RAM for much faster processing
|
|
102
104
|
- `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
|
|
103
105
|
- Support Curve plots (2D signals)
|
|
106
|
+
- :new: gradio backend (+allows sharing with others)
|
|
104
107
|
|
|
105
108
|
|
|
106
109
|
|
|
@@ -122,7 +125,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
122
125
|
- supported backends
|
|
123
126
|
- :ok: `gui='qt'` pyQt/pySide
|
|
124
127
|
- :ok: `gui='mpl'` matplotlib
|
|
125
|
-
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
128
|
+
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
129
|
+
- :test_tube: `gui='gradio'` gradio wrapping (+use `share_gradio_app=True` to share your app with others)
|
|
126
130
|
- tested platforms
|
|
127
131
|
- :ok: Linux (Ubuntu / KDE Neon)
|
|
128
132
|
- :ok: RapsberryPi
|
|
@@ -130,25 +134,18 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
130
134
|
|
|
131
135
|
|
|
132
136
|
|
|
133
|
-
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
|
|
134
|
-
|:-----: |:-----:|:------:|:----: |
|
|
135
|
-
| Backend name | `qt` | `mpl` | `nb`|
|
|
136
|
-
| Preview |  |  |  |
|
|
137
|
-
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
138
|
-
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
139
|
-
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
140
|
-
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
141
|
-
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
137
|
+
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
|
|
138
|
+
|:-----: |:-----:|:------:|:----: |:----: |
|
|
139
|
+
| Backend name | `qt` | `mpl` | `nb`| `gradio` |
|
|
140
|
+
| Preview |  |  |  | |
|
|
141
|
+
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:|
|
|
142
|
+
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
143
|
+
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
144
|
+
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
145
|
+
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign:|
|
|
142
146
|
|
|
143
147
|
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
#### :test_tube: Experimental features
|
|
147
|
-
- Custom events on specific key press
|
|
148
|
-
- Display the execution graph of the pipeline `G` key
|
|
149
|
-
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
150
|
-
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
151
|
-
|
|
152
149
|
# Tutorials
|
|
153
150
|
|
|
154
151
|
### Learn by examples
|
|
@@ -163,12 +160,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
163
160
|

|
|
164
161
|
|
|
165
162
|
|
|
166
|
-
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
167
|
-
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
168
|
-
|
|
169
|
-
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
170
163
|
|
|
171
|
-

|
|
172
164
|
|
|
173
165
|
|
|
174
166
|
# Tutorials
|
|
@@ -259,7 +251,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
|
|
|
259
251
|
```
|
|
260
252
|
|
|
261
253
|
- Note that you can also create filters which take no inputs and simply "generate" images.
|
|
262
|
-
- The `color_choice` list will be
|
|
254
|
+
- The `color_choice` list will be turned into a nice dropdown menu. Default value here will be red as this is the first element of the list!
|
|
263
255
|
----------
|
|
264
256
|
|
|
265
257
|
:bulb: Can filters communicate together?
|
|
@@ -313,7 +305,8 @@ if __name__ == '__main__':
|
|
|
313
305
|
### History
|
|
314
306
|
- Interactive pipe was initially developped by [Balthazar Neveu](https://github.com/balthazarneveu) as part of the [irdrone project](https://github.com/wisescootering/infrareddrone/tree/master/interactive) based on matplotlib.
|
|
315
307
|
- Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
|
|
316
|
-
-
|
|
308
|
+
- August 2023: rewriting the whole core and supporting several graphical backends!
|
|
309
|
+
- September 2024: Gradio backend
|
|
317
310
|
|
|
318
311
|
|
|
319
312
|
|
|
@@ -333,3 +326,23 @@ if __name__ == '__main__':
|
|
|
333
326
|
- Exploratory backends
|
|
334
327
|
- Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
|
|
335
328
|
- Create a [Kivy](https://kivy.org/) backend
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
### Further examples
|
|
332
|
+
|
|
333
|
+
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
334
|
+
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
335
|
+
|
|
336
|
+
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
337
|
+
|
|
338
|
+

|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
#### :test_tube: Experimental features
|
|
345
|
+
- Custom events on specific key press
|
|
346
|
+
- Display the execution graph of the pipeline `G` key
|
|
347
|
+
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
348
|
+
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "interactive_pipe"
|
|
8
|
-
version = "0.
|
|
8
|
+
version = "0.7.0"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Balthazar Neveu", email="balthazarneveu@gmail.com" },
|
|
11
11
|
]
|
|
@@ -20,6 +20,7 @@ dependencies = [
|
|
|
20
20
|
"pytest>=6.2.5",
|
|
21
21
|
"ipywidgets>=8.0.7",
|
|
22
22
|
"pandas",
|
|
23
|
+
"gradio",
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
description = "Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!"
|
|
@@ -62,4 +63,5 @@ full=[
|
|
|
62
63
|
"pytest>=6.2.5",
|
|
63
64
|
"ipywidgets>=8.0.7",
|
|
64
65
|
"pandas",
|
|
66
|
+
"gradio",
|
|
65
67
|
]
|
|
@@ -51,7 +51,7 @@ pip install -e ".[full]"
|
|
|
51
51
|
|
|
52
52
|
## :scroll: Features
|
|
53
53
|
|
|
54
|
-
**Version 0.
|
|
54
|
+
**Version 0.7.0**
|
|
55
55
|
- Modular multi-image processing filters
|
|
56
56
|
- Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
|
|
57
57
|
- Support in jupyter notebooks
|
|
@@ -59,6 +59,7 @@ pip install -e ".[full]"
|
|
|
59
59
|
- Cache intermediate results in RAM for much faster processing
|
|
60
60
|
- `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
|
|
61
61
|
- Support Curve plots (2D signals)
|
|
62
|
+
- :new: gradio backend (+allows sharing with others)
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
|
|
@@ -80,7 +81,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
80
81
|
- supported backends
|
|
81
82
|
- :ok: `gui='qt'` pyQt/pySide
|
|
82
83
|
- :ok: `gui='mpl'` matplotlib
|
|
83
|
-
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
84
|
+
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
85
|
+
- :test_tube: `gui='gradio'` gradio wrapping (+use `share_gradio_app=True` to share your app with others)
|
|
84
86
|
- tested platforms
|
|
85
87
|
- :ok: Linux (Ubuntu / KDE Neon)
|
|
86
88
|
- :ok: RapsberryPi
|
|
@@ -88,25 +90,18 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
88
90
|
|
|
89
91
|
|
|
90
92
|
|
|
91
|
-
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
|
|
92
|
-
|:-----: |:-----:|:------:|:----: |
|
|
93
|
-
| Backend name | `qt` | `mpl` | `nb`|
|
|
94
|
-
| Preview |  |  |  |
|
|
95
|
-
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
96
|
-
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
97
|
-
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
98
|
-
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
99
|
-
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
93
|
+
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
|
|
94
|
+
|:-----: |:-----:|:------:|:----: |:----: |
|
|
95
|
+
| Backend name | `qt` | `mpl` | `nb`| `gradio` |
|
|
96
|
+
| Preview |  |  |  | |
|
|
97
|
+
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:|
|
|
98
|
+
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
99
|
+
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
100
|
+
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
101
|
+
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign:|
|
|
100
102
|
|
|
101
103
|
|
|
102
104
|
|
|
103
|
-
|
|
104
|
-
#### :test_tube: Experimental features
|
|
105
|
-
- Custom events on specific key press
|
|
106
|
-
- Display the execution graph of the pipeline `G` key
|
|
107
|
-
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
108
|
-
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
109
|
-
|
|
110
105
|
# Tutorials
|
|
111
106
|
|
|
112
107
|
### Learn by examples
|
|
@@ -121,12 +116,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
121
116
|

|
|
122
117
|
|
|
123
118
|
|
|
124
|
-
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
125
|
-
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
126
119
|
|
|
127
|
-
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
128
|
-
|
|
129
|
-

|
|
130
120
|
|
|
131
121
|
|
|
132
122
|
# Tutorials
|
|
@@ -217,7 +207,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
|
|
|
217
207
|
```
|
|
218
208
|
|
|
219
209
|
- Note that you can also create filters which take no inputs and simply "generate" images.
|
|
220
|
-
- The `color_choice` list will be
|
|
210
|
+
- The `color_choice` list will be turned into a nice dropdown menu. Default value here will be red as this is the first element of the list!
|
|
221
211
|
----------
|
|
222
212
|
|
|
223
213
|
:bulb: Can filters communicate together?
|
|
@@ -271,7 +261,8 @@ if __name__ == '__main__':
|
|
|
271
261
|
### History
|
|
272
262
|
- Interactive pipe was initially developped by [Balthazar Neveu](https://github.com/balthazarneveu) as part of the [irdrone project](https://github.com/wisescootering/infrareddrone/tree/master/interactive) based on matplotlib.
|
|
273
263
|
- Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
|
|
274
|
-
-
|
|
264
|
+
- August 2023: rewriting the whole core and supporting several graphical backends!
|
|
265
|
+
- September 2024: Gradio backend
|
|
275
266
|
|
|
276
267
|
|
|
277
268
|
|
|
@@ -290,4 +281,24 @@ if __name__ == '__main__':
|
|
|
290
281
|
- Animations/While loops/Video source (Time slider)
|
|
291
282
|
- Exploratory backends
|
|
292
283
|
- Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
|
|
293
|
-
- Create a [Kivy](https://kivy.org/) backend
|
|
284
|
+
- Create a [Kivy](https://kivy.org/) backend
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
### Further examples
|
|
288
|
+
|
|
289
|
+
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
290
|
+
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
291
|
+
|
|
292
|
+
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
293
|
+
|
|
294
|
+

|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
#### :test_tube: Experimental features
|
|
301
|
+
- Custom events on specific key press
|
|
302
|
+
- Display the execution graph of the pipeline `G` key
|
|
303
|
+
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
304
|
+
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
|
|
2
|
+
from functools import partial
|
|
3
|
+
from interactive_pipe.headless.control import Control
|
|
4
|
+
import logging
|
|
5
|
+
import gradio as gr
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseControl():
|
|
9
|
+
def __init__(self, name, ctrl: Control, update_func):
|
|
10
|
+
super().__init__()
|
|
11
|
+
self.name = name
|
|
12
|
+
self.ctrl = ctrl
|
|
13
|
+
self.update_func = update_func
|
|
14
|
+
self.check_control_type()
|
|
15
|
+
|
|
16
|
+
def create(self):
|
|
17
|
+
raise NotImplementedError(
|
|
18
|
+
"This method should be overridden by subclass")
|
|
19
|
+
|
|
20
|
+
def check_control_type(self):
|
|
21
|
+
raise NotImplementedError(
|
|
22
|
+
"This method should be overridden by subclass to check the right slider control type")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ControlFactory:
|
|
26
|
+
@staticmethod
|
|
27
|
+
def create_control(control: Control, update_func):
|
|
28
|
+
control_type = control._type
|
|
29
|
+
name = control.name
|
|
30
|
+
control_class_map = {
|
|
31
|
+
bool: TickBoxControl,
|
|
32
|
+
int: IntSliderControl,
|
|
33
|
+
float: FloatSliderControl,
|
|
34
|
+
str: DropdownMenuControl
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if control_type not in control_class_map:
|
|
38
|
+
logging.warning(
|
|
39
|
+
f"Unsupported control type: {control_type} for control named {name}")
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
control_class = control_class_map[control_type]
|
|
43
|
+
return control_class(name, control, update_func)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class IntSliderControl(BaseControl):
|
|
47
|
+
def check_control_type(self):
|
|
48
|
+
assert self.ctrl._type == int
|
|
49
|
+
|
|
50
|
+
def create(self) -> gr.Slider:
|
|
51
|
+
self.control_widget = gr.Slider(
|
|
52
|
+
value=self.ctrl.value_default, minimum=self.ctrl.value_range[0], maximum=self.ctrl.value_range[1], label=self.name, step=1)
|
|
53
|
+
return self.control_widget
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class FloatSliderControl(BaseControl):
|
|
57
|
+
def check_control_type(self):
|
|
58
|
+
assert self.ctrl._type == float
|
|
59
|
+
|
|
60
|
+
def create(self) -> gr.Slider:
|
|
61
|
+
self.control_widget = gr.Slider(
|
|
62
|
+
value=self.ctrl.value_default,
|
|
63
|
+
minimum=self.ctrl.value_range[0], maximum=self.ctrl.value_range[1], label=self.name)
|
|
64
|
+
|
|
65
|
+
return self.control_widget
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TickBoxControl(BaseControl):
|
|
69
|
+
def check_control_type(self):
|
|
70
|
+
assert self.ctrl._type == bool
|
|
71
|
+
|
|
72
|
+
def create(self) -> gr.Checkbox:
|
|
73
|
+
self.control_widget = gr.Checkbox(label=self.name, value=self.ctrl.value)
|
|
74
|
+
return self.control_widget
|
|
75
|
+
|
|
76
|
+
def reset(self):
|
|
77
|
+
self.control_widget.update(value=self.ctrl.default_value)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class DropdownMenuControl(BaseControl):
|
|
81
|
+
def check_control_type(self):
|
|
82
|
+
assert self.ctrl._type == str
|
|
83
|
+
if not hasattr(self.ctrl, 'value_range'):
|
|
84
|
+
raise ValueError("Invalid control type")
|
|
85
|
+
|
|
86
|
+
def create(self) -> gr.Dropdown:
|
|
87
|
+
# Create a horizontal layout to hold the dropdown menu
|
|
88
|
+
self.control_widget = gr.Dropdown(label=self.name, choices=self.ctrl.value_range, value=self.ctrl.value)
|
|
89
|
+
return self.control_widget
|
|
90
|
+
|
|
91
|
+
def reset(self):
|
|
92
|
+
index = self.control_widget.findText(self.ctrl.value)
|
|
93
|
+
if index >= 0:
|
|
94
|
+
self.control_widget.setCurrentIndex(index)
|
|
95
|
+
self.control_widget.setCurrentIndex(index)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import gradio as gr
|
|
2
|
+
import numpy as np
|
|
3
|
+
from typing import List
|
|
4
|
+
from interactive_pipe.headless.pipeline import HeadlessPipeline
|
|
5
|
+
from interactive_pipe.graphical.gradio_control import ControlFactory
|
|
6
|
+
from interactive_pipe.graphical.window import InteractivePipeWindow
|
|
7
|
+
from interactive_pipe.graphical.gui import InteractivePipeGUI
|
|
8
|
+
from interactive_pipe.headless.control import Control
|
|
9
|
+
import logging
|
|
10
|
+
PYQTVERSION = None
|
|
11
|
+
MPL_SUPPORT = False
|
|
12
|
+
GRADIO_INTERFACE_MODE = False
|
|
13
|
+
try:
|
|
14
|
+
from interactive_pipe.data_objects.curves import Curve
|
|
15
|
+
import matplotlib.pyplot as plt
|
|
16
|
+
MPL_SUPPORT = True
|
|
17
|
+
except ImportError:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class InteractivePipeGradio(InteractivePipeGUI):
|
|
22
|
+
def init_app(self, **kwargs):
|
|
23
|
+
self.window = MainWindow(controls=self.controls, name=self.name,
|
|
24
|
+
pipeline=self.pipeline, size=self.size, main_gui=self, **kwargs)
|
|
25
|
+
self.pipeline.global_params["__pipeline"] = self.pipeline
|
|
26
|
+
# self.set_default_key_bindings()
|
|
27
|
+
|
|
28
|
+
def run(self) -> list:
|
|
29
|
+
assert self.pipeline._PipelineCore__initialized_inputs, "Did you forget to initialize the pipeline inputs?"
|
|
30
|
+
out_list = self.window.process_inputs_fn(*self.window.default_values)
|
|
31
|
+
out_list_gradio_containers = []
|
|
32
|
+
for idx in range(len(out_list)):
|
|
33
|
+
for idy in range(len(out_list[idx])):
|
|
34
|
+
if isinstance(out_list[idx][idy], np.ndarray):
|
|
35
|
+
out_list_gradio_containers.append(gr.Image())
|
|
36
|
+
elif MPL_SUPPORT and isinstance(out_list[idx][idy], Curve):
|
|
37
|
+
out_list_gradio_containers.append(gr.Plot())
|
|
38
|
+
else:
|
|
39
|
+
raise NotImplementedError(
|
|
40
|
+
f"output type {type(out_list[idx][idy])} not supported")
|
|
41
|
+
self.window.instantiate_gradio_interface(out_list_gradio_containers)
|
|
42
|
+
self.window.refresh()
|
|
43
|
+
self.custom_end()
|
|
44
|
+
return self.pipeline.results
|
|
45
|
+
|
|
46
|
+
def print_message(self, message_list: List[str]):
|
|
47
|
+
print("\n".join(message_list))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MainWindow(InteractivePipeWindow):
|
|
51
|
+
def __init__(self, *args, controls=[], name="", pipeline: HeadlessPipeline = None, size=None, share_gradio_app=False, **kwargs):
|
|
52
|
+
InteractivePipeWindow.__init__(
|
|
53
|
+
self, name=name, pipeline=pipeline, size=size)
|
|
54
|
+
self.init_sliders(controls)
|
|
55
|
+
self.size = size
|
|
56
|
+
self.full_screen_flag = False
|
|
57
|
+
self.pipeline = pipeline
|
|
58
|
+
self.share_gradio_app = share_gradio_app
|
|
59
|
+
# Define the functions that will be called when the input changes for gradio. => gr.Interface(fn=process_fn)
|
|
60
|
+
|
|
61
|
+
def process_outputs_fn(out) -> tuple:
|
|
62
|
+
flat_out = []
|
|
63
|
+
for idx in range(len(out)):
|
|
64
|
+
if isinstance(out[idx], list):
|
|
65
|
+
for idy in range(len(out[idx])):
|
|
66
|
+
if MPL_SUPPORT and isinstance(out[idx][idy], Curve):
|
|
67
|
+
curve = out[idx][idy]
|
|
68
|
+
fig, ax = plt.subplots()
|
|
69
|
+
Curve._plot_curve(curve.data, ax=ax)
|
|
70
|
+
flat_out.append(fig)
|
|
71
|
+
elif isinstance(out[idx][idy], np.ndarray):
|
|
72
|
+
logging.info(f"CONVERTING IMAGE {idx} {idy}")
|
|
73
|
+
flat_out.append(self.convert_image(out[idx][idy]))
|
|
74
|
+
else:
|
|
75
|
+
raise NotImplementedError(
|
|
76
|
+
f"output type {type(out[idx][idy])} not supported")
|
|
77
|
+
else:
|
|
78
|
+
logging.info(f"CONVERTING IMAGE {idx} ")
|
|
79
|
+
flat_out.append(self.convert_image(out[idx]))
|
|
80
|
+
if out is None:
|
|
81
|
+
logging.warning("No output to display")
|
|
82
|
+
return
|
|
83
|
+
return tuple(flat_out)
|
|
84
|
+
|
|
85
|
+
def process_inputs_fn(*args) -> list:
|
|
86
|
+
all_keys = list(self.ctrl.keys())
|
|
87
|
+
for idx in range(len(args)):
|
|
88
|
+
self.ctrl[all_keys[idx]].update(args[idx])
|
|
89
|
+
out = self.pipeline.run()
|
|
90
|
+
return out
|
|
91
|
+
|
|
92
|
+
def run_fn(*args) -> tuple:
|
|
93
|
+
out = process_inputs_fn(*args)
|
|
94
|
+
out_tuple = process_outputs_fn(out)
|
|
95
|
+
return out_tuple
|
|
96
|
+
self.default_values = [self.ctrl[ctrl_key].value for ctrl_key in self.ctrl.keys()]
|
|
97
|
+
self.process_inputs_fn = process_inputs_fn
|
|
98
|
+
self.run_fn = run_fn
|
|
99
|
+
|
|
100
|
+
def instantiate_gradio_interface(self, outputs: List[gr.Blocks]):
|
|
101
|
+
if GRADIO_INTERFACE_MODE:
|
|
102
|
+
# Interface mode, high level wrapper
|
|
103
|
+
# https://www.gradio.app/guides/the-interface-class
|
|
104
|
+
self.io = gr.Interface(
|
|
105
|
+
allow_flagging='never',
|
|
106
|
+
fn=self.run_fn,
|
|
107
|
+
title=self.name,
|
|
108
|
+
inputs=self.widget_list,
|
|
109
|
+
outputs=outputs,
|
|
110
|
+
examples=[self.default_values],
|
|
111
|
+
live=True,
|
|
112
|
+
show_progress="minimal",
|
|
113
|
+
clear_btn=None,
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
# Gradio Blocks mode
|
|
117
|
+
# https://www.gradio.app/guides/blocks-and-event-listeners
|
|
118
|
+
with gr.Blocks() as io:
|
|
119
|
+
with gr.Row():
|
|
120
|
+
for elem in outputs:
|
|
121
|
+
elem.render()
|
|
122
|
+
with gr.Row():
|
|
123
|
+
for elem in self.widget_list:
|
|
124
|
+
with gr.Row():
|
|
125
|
+
elem.render()
|
|
126
|
+
with gr.Row():
|
|
127
|
+
gr.Examples([self.default_values], inputs=self.widget_list)
|
|
128
|
+
io.load(fn=self.run_fn, inputs=self.widget_list, outputs=outputs)
|
|
129
|
+
for idx in range(len(self.widget_list)):
|
|
130
|
+
self.widget_list[idx].change(
|
|
131
|
+
fn=self.run_fn, inputs=self.widget_list,
|
|
132
|
+
outputs=outputs,
|
|
133
|
+
show_progress="minimal"
|
|
134
|
+
)
|
|
135
|
+
self.io = io
|
|
136
|
+
self.io.launch(share=self.share_gradio_app)
|
|
137
|
+
|
|
138
|
+
def init_sliders(self, controls: List[Control]):
|
|
139
|
+
self.ctrl = {}
|
|
140
|
+
self.result_label = {}
|
|
141
|
+
self.name_label = {}
|
|
142
|
+
self.widget_list = []
|
|
143
|
+
control_factory = ControlFactory()
|
|
144
|
+
for ctrl in controls:
|
|
145
|
+
if isinstance(ctrl, Control):
|
|
146
|
+
slider_instance = control_factory.create_control(
|
|
147
|
+
ctrl, None)
|
|
148
|
+
control_widget = slider_instance.create()
|
|
149
|
+
self.widget_list.append(control_widget)
|
|
150
|
+
slider_name = ctrl.name
|
|
151
|
+
self.ctrl[slider_name] = ctrl
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def convert_image(out_im):
|
|
155
|
+
if isinstance(out_im, np.ndarray):
|
|
156
|
+
return (out_im.clip(0., 1.) * 255).astype(np.uint8)
|
|
157
|
+
else:
|
|
158
|
+
return out_im
|
|
159
|
+
|
|
160
|
+
def refresh(self):
|
|
161
|
+
if self.pipeline is not None:
|
|
162
|
+
self.io.launch()
|
|
163
|
+
|
|
164
|
+
def reset_sliders(self):
|
|
165
|
+
# Click on default examples in Gradio
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
def add_image_placeholder(self, row, col):
|
|
169
|
+
ax_placeholder = None
|
|
170
|
+
text_label = None
|
|
171
|
+
image_label = None
|
|
172
|
+
self.image_canvas[row][col] = {
|
|
173
|
+
"image": image_label, "title": text_label, "ax_placeholder": ax_placeholder}
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/choose_backend.py
RENAMED
|
@@ -35,6 +35,8 @@ def get_interactive_pipeline_class(gui="auto"):
|
|
|
35
35
|
from interactive_pipe.graphical.mpl_gui import InteractivePipeMatplotlib as ChosenGui
|
|
36
36
|
elif selected_gui == "nb":
|
|
37
37
|
from interactive_pipe.graphical.nb_gui import InteractivePipeJupyter as ChosenGui
|
|
38
|
+
elif selected_gui == "gradio":
|
|
39
|
+
from interactive_pipe.graphical.gradio_gui import InteractivePipeGradio as ChosenGui
|
|
38
40
|
else:
|
|
39
41
|
raise NotImplementedError(f"Gui {gui} not available")
|
|
40
42
|
return ChosenGui
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: interactive_pipe
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!
|
|
5
5
|
Author-email: Balthazar Neveu <balthazarneveu@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/balthazarneveu/interactive_pipe
|
|
@@ -21,6 +21,7 @@ Requires-Dist: opencv_python_headless>=4.8.1.78
|
|
|
21
21
|
Requires-Dist: pytest>=6.2.5
|
|
22
22
|
Requires-Dist: ipywidgets>=8.0.7
|
|
23
23
|
Requires-Dist: pandas
|
|
24
|
+
Requires-Dist: gradio
|
|
24
25
|
Provides-Extra: qt6
|
|
25
26
|
Requires-Dist: PyQt6>=6.5.2; extra == "qt6"
|
|
26
27
|
Requires-Dist: PyQt6_sip>=13.5.2; extra == "qt6"
|
|
@@ -39,6 +40,7 @@ Requires-Dist: opencv_python_headless>=4.8.1.78; extra == "full"
|
|
|
39
40
|
Requires-Dist: pytest>=6.2.5; extra == "full"
|
|
40
41
|
Requires-Dist: ipywidgets>=8.0.7; extra == "full"
|
|
41
42
|
Requires-Dist: pandas; extra == "full"
|
|
43
|
+
Requires-Dist: gradio; extra == "full"
|
|
42
44
|
|
|
43
45
|
# `interactive_pipe`
|
|
44
46
|
|
|
@@ -93,7 +95,7 @@ pip install -e ".[full]"
|
|
|
93
95
|
|
|
94
96
|
## :scroll: Features
|
|
95
97
|
|
|
96
|
-
**Version 0.
|
|
98
|
+
**Version 0.7.0**
|
|
97
99
|
- Modular multi-image processing filters
|
|
98
100
|
- Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
|
|
99
101
|
- Support in jupyter notebooks
|
|
@@ -101,6 +103,7 @@ pip install -e ".[full]"
|
|
|
101
103
|
- Cache intermediate results in RAM for much faster processing
|
|
102
104
|
- `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
|
|
103
105
|
- Support Curve plots (2D signals)
|
|
106
|
+
- :new: gradio backend (+allows sharing with others)
|
|
104
107
|
|
|
105
108
|
|
|
106
109
|
|
|
@@ -122,7 +125,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
122
125
|
- supported backends
|
|
123
126
|
- :ok: `gui='qt'` pyQt/pySide
|
|
124
127
|
- :ok: `gui='mpl'` matplotlib
|
|
125
|
-
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
128
|
+
- :ok: `gui='nb'` ipywidget for jupyter notebooks
|
|
129
|
+
- :test_tube: `gui='gradio'` gradio wrapping (+use `share_gradio_app=True` to share your app with others)
|
|
126
130
|
- tested platforms
|
|
127
131
|
- :ok: Linux (Ubuntu / KDE Neon)
|
|
128
132
|
- :ok: RapsberryPi
|
|
@@ -130,25 +134,18 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
130
134
|
|
|
131
135
|
|
|
132
136
|
|
|
133
|
-
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
|
|
134
|
-
|:-----: |:-----:|:------:|:----: |
|
|
135
|
-
| Backend name | `qt` | `mpl` | `nb`|
|
|
136
|
-
| Preview |  |  |  |
|
|
137
|
-
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
138
|
-
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
|
139
|
-
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
140
|
-
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
141
|
-
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
137
|
+
| :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
|
|
138
|
+
|:-----: |:-----:|:------:|:----: |:----: |
|
|
139
|
+
| Backend name | `qt` | `mpl` | `nb`| `gradio` |
|
|
140
|
+
| Preview |  |  |  | |
|
|
141
|
+
| Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:|
|
|
142
|
+
| Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
|
143
|
+
| Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
144
|
+
| Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
|
|
145
|
+
| Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign:|
|
|
142
146
|
|
|
143
147
|
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
#### :test_tube: Experimental features
|
|
147
|
-
- Custom events on specific key press
|
|
148
|
-
- Display the execution graph of the pipeline `G` key
|
|
149
|
-
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
150
|
-
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
151
|
-
|
|
152
149
|
# Tutorials
|
|
153
150
|
|
|
154
151
|
### Learn by examples
|
|
@@ -163,12 +160,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
|
|
|
163
160
|

|
|
164
161
|
|
|
165
162
|
|
|
166
|
-
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
167
|
-
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
168
|
-
|
|
169
|
-
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
170
163
|
|
|
171
|
-

|
|
172
164
|
|
|
173
165
|
|
|
174
166
|
# Tutorials
|
|
@@ -259,7 +251,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
|
|
|
259
251
|
```
|
|
260
252
|
|
|
261
253
|
- Note that you can also create filters which take no inputs and simply "generate" images.
|
|
262
|
-
- The `color_choice` list will be
|
|
254
|
+
- The `color_choice` list will be turned into a nice dropdown menu. Default value here will be red as this is the first element of the list!
|
|
263
255
|
----------
|
|
264
256
|
|
|
265
257
|
:bulb: Can filters communicate together?
|
|
@@ -313,7 +305,8 @@ if __name__ == '__main__':
|
|
|
313
305
|
### History
|
|
314
306
|
- Interactive pipe was initially developped by [Balthazar Neveu](https://github.com/balthazarneveu) as part of the [irdrone project](https://github.com/wisescootering/infrareddrone/tree/master/interactive) based on matplotlib.
|
|
315
307
|
- Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
|
|
316
|
-
-
|
|
308
|
+
- August 2023: rewriting the whole core and supporting several graphical backends!
|
|
309
|
+
- September 2024: Gradio backend
|
|
317
310
|
|
|
318
311
|
|
|
319
312
|
|
|
@@ -333,3 +326,23 @@ if __name__ == '__main__':
|
|
|
333
326
|
- Exploratory backends
|
|
334
327
|
- Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
|
|
335
328
|
- Create a [Kivy](https://kivy.org/) backend
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
### Further examples
|
|
332
|
+
|
|
333
|
+
#### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
|
|
334
|
+
[ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
|
|
335
|
+
|
|
336
|
+
:warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
|
|
337
|
+
|
|
338
|
+

|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
#### :test_tube: Experimental features
|
|
345
|
+
- Custom events on specific key press
|
|
346
|
+
- Display the execution graph of the pipeline `G` key
|
|
347
|
+
- [thirdparty/music](/src/interactive_pipe/thirdparty/music.py) Play audio (Qt backend only). Play songs on spotify (linux only) when the spotify app is running.
|
|
348
|
+
- [thirdparty/images_openai_api](/src/interactive_pipe/thirdparty/images_openai_api.py) Generate images from prompt using OpenAI API image generation DALL-E Model (:dollar: paid service ~ 2cents/image)
|
|
@@ -20,6 +20,8 @@ src/interactive_pipe/data_objects/data.py
|
|
|
20
20
|
src/interactive_pipe/data_objects/image.py
|
|
21
21
|
src/interactive_pipe/data_objects/parameters.py
|
|
22
22
|
src/interactive_pipe/graphical/__init__.py
|
|
23
|
+
src/interactive_pipe/graphical/gradio_control.py
|
|
24
|
+
src/interactive_pipe/graphical/gradio_gui.py
|
|
23
25
|
src/interactive_pipe/graphical/gui.py
|
|
24
26
|
src/interactive_pipe/graphical/mpl_control.py
|
|
25
27
|
src/interactive_pipe/graphical/mpl_gui.py
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/requires.txt
RENAMED
|
@@ -8,6 +8,7 @@ opencv_python_headless>=4.8.1.78
|
|
|
8
8
|
pytest>=6.2.5
|
|
9
9
|
ipywidgets>=8.0.7
|
|
10
10
|
pandas
|
|
11
|
+
gradio
|
|
11
12
|
|
|
12
13
|
[full]
|
|
13
14
|
PyQt6>=6.5.2
|
|
@@ -16,6 +17,7 @@ opencv_python_headless>=4.8.1.78
|
|
|
16
17
|
pytest>=6.2.5
|
|
17
18
|
ipywidgets>=8.0.7
|
|
18
19
|
pandas
|
|
20
|
+
gradio
|
|
19
21
|
|
|
20
22
|
[notebook]
|
|
21
23
|
ipywidgets>=8.0.7
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/__init__.py
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/curves.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/image.py
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/parameters.py
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_control.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_window.py
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/nb_control.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/qt_control.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/filter_decorator.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/pipeline_decorator.py
RENAMED
|
File without changes
|
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe/thirdparty/music_spotify.py
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{interactive_pipe-0.6.1 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|