interactive-pipe 0.6.0__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.
Files changed (60) hide show
  1. {interactive_pipe-0.6.0/src/interactive_pipe.egg-info → interactive_pipe-0.7.0}/PKG-INFO +53 -31
  2. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/pyproject.toml +10 -2
  3. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/readme.md +45 -31
  4. interactive_pipe-0.7.0/src/interactive_pipe/graphical/gradio_control.py +95 -0
  5. interactive_pipe-0.7.0/src/interactive_pipe/graphical/gradio_gui.py +173 -0
  6. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/choose_backend.py +2 -0
  7. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0/src/interactive_pipe.egg-info}/PKG-INFO +53 -31
  8. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/SOURCES.txt +2 -0
  9. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/requires.txt +8 -0
  10. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/LICENSE +0 -0
  11. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/setup.cfg +0 -0
  12. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/__init__.py +0 -0
  13. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/__init__.py +0 -0
  14. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/cache.py +0 -0
  15. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/engine.py +0 -0
  16. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/filter.py +0 -0
  17. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/graph.py +0 -0
  18. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/pipeline.py +0 -0
  19. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/core/signature.py +0 -0
  20. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/__init__.py +0 -0
  21. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/curves.py +0 -0
  22. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/data.py +0 -0
  23. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/image.py +0 -0
  24. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/data_objects/parameters.py +0 -0
  25. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/__init__.py +0 -0
  26. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/gui.py +0 -0
  27. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_control.py +0 -0
  28. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_gui.py +0 -0
  29. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/mpl_window.py +0 -0
  30. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/nb_control.py +0 -0
  31. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/nb_gui.py +0 -0
  32. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/qt_control.py +0 -0
  33. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/qt_gui.py +0 -0
  34. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/graphical/window.py +0 -0
  35. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/__init__.py +0 -0
  36. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/control.py +0 -0
  37. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/keyboard.py +0 -0
  38. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/headless/pipeline.py +0 -0
  39. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/__init__.py +0 -0
  40. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/_private.py +0 -0
  41. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/control_abbreviation.py +0 -0
  42. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/filter_decorator.py +0 -0
  43. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/keyword_args_analyzer.py +0 -0
  44. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/helper/pipeline_decorator.py +0 -0
  45. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/thirdparty/images_openai_api.py +0 -0
  46. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe/thirdparty/music_spotify.py +0 -0
  47. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/dependency_links.txt +0 -0
  48. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/src/interactive_pipe.egg-info/top_level.txt +0 -0
  49. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_cache.py +0 -0
  50. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_control_abbreviations.py +0 -0
  51. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_controller.py +0 -0
  52. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_core.py +0 -0
  53. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_curves.py +0 -0
  54. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_decorator.py +0 -0
  55. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_engine.py +0 -0
  56. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_filter.py +0 -0
  57. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_headless.py +0 -0
  58. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_image.py +0 -0
  59. {interactive_pipe-0.6.0 → interactive_pipe-0.7.0}/test/test_parameters.py +0 -0
  60. {interactive_pipe-0.6.0 → 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.6.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
@@ -15,6 +15,13 @@ Requires-Dist: matplotlib>=3.5.3
15
15
  Requires-Dist: numpy>=1.21.6
16
16
  Requires-Dist: Pillow>=9.0.1
17
17
  Requires-Dist: PyYAML>=5.4.1
18
+ Requires-Dist: PyQt6>=6.5.2
19
+ Requires-Dist: PyQt6_sip>=13.5.2
20
+ Requires-Dist: opencv_python_headless>=4.8.1.78
21
+ Requires-Dist: pytest>=6.2.5
22
+ Requires-Dist: ipywidgets>=8.0.7
23
+ Requires-Dist: pandas
24
+ Requires-Dist: gradio
18
25
  Provides-Extra: qt6
19
26
  Requires-Dist: PyQt6>=6.5.2; extra == "qt6"
20
27
  Requires-Dist: PyQt6_sip>=13.5.2; extra == "qt6"
@@ -33,11 +40,12 @@ Requires-Dist: opencv_python_headless>=4.8.1.78; extra == "full"
33
40
  Requires-Dist: pytest>=6.2.5; extra == "full"
34
41
  Requires-Dist: ipywidgets>=8.0.7; extra == "full"
35
42
  Requires-Dist: pandas; extra == "full"
43
+ Requires-Dist: gradio; extra == "full"
36
44
 
37
45
  # `interactive_pipe`
38
46
 
39
47
  Quick setup
40
- `pip install interactive-pipe[full]`
48
+ `pip install interactive-pipe`
41
49
 
42
50
  ### Concept
43
51
  - Develop an algorithm while debugging visually with plots, while checking robustness & continuity to parameters change.
@@ -58,8 +66,12 @@ Quick setup
58
66
 
59
67
  ----------------------
60
68
 
61
- ### Setup
62
- `pip install interactive-pipe[full]`
69
+ ### Local setup
70
+ ```
71
+ git clone git@github.com:balthazarneveu/interactive_pipe.git
72
+ cd interactive-pipe
73
+ pip install -e ".[full]"
74
+ ```
63
75
 
64
76
  ----------------------
65
77
 
@@ -82,7 +94,8 @@ Quick setup
82
94
  ----------------------
83
95
 
84
96
  ## :scroll: Features
85
- **Version 0.6.0**
97
+
98
+ **Version 0.7.0**
86
99
  - Modular multi-image processing filters
87
100
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
88
101
  - Support in jupyter notebooks
@@ -90,16 +103,9 @@ Quick setup
90
103
  - Cache intermediate results in RAM for much faster processing
91
104
  - `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
92
105
  - Support Curve plots (2D signals)
93
-
94
- #### :soon: Upcoming features:
95
- - :soon: Scientific visual debugging: Display both colored images, heatmaps & graphs
106
+ - :new: gradio backend (+allows sharing with others)
96
107
 
97
108
 
98
- #### :test_tube: Experimental features
99
- - custom events on specific key press
100
- - Display the execution graph of the pipeline
101
- - [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.
102
- - [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)
103
109
 
104
110
  #### :keyboard: Keyboard shortcuts
105
111
  Shortcuts while using the GUI (QT & matplotlib backends)
@@ -119,7 +125,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
119
125
  - supported backends
120
126
  - :ok: `gui='qt'` pyQt/pySide
121
127
  - :ok: `gui='mpl'` matplotlib
122
- - :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)
123
130
  - tested platforms
124
131
  - :ok: Linux (Ubuntu / KDE Neon)
125
132
  - :ok: RapsberryPi
@@ -127,16 +134,15 @@ Shortcuts while using the GUI (QT & matplotlib backends)
127
134
 
128
135
 
129
136
 
130
- | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
131
- |:-----: |:-----:|:------:|:----: |
132
- | Backend name | `qt` | `mpl` | `nb`|
133
- | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) |
134
- | Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
135
- | Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
136
- | Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
137
- | Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
138
- | Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
139
-
137
+ | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
138
+ |:-----: |:-----:|:------:|:----: |:----: |
139
+ | Backend name | `qt` | `mpl` | `nb`| `gradio` |
140
+ | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) | |
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:|
140
146
 
141
147
 
142
148
 
@@ -154,12 +160,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
154
160
  ![Speech processing exploration in a notebook](/doc/images/jupyter_integration_speech.png)
155
161
 
156
162
 
157
- #### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
158
- [ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
159
163
 
160
- :warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
161
-
162
- ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
163
164
 
164
165
 
165
166
  # Tutorials
@@ -250,7 +251,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
250
251
  ```
251
252
 
252
253
  - Note that you can also create filters which take no inputs and simply "generate" images.
253
- - The `color_choice` list will be turnt into a nice dropdown menu. Default value here will be red as this is the first element of the list!
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!
254
255
  ----------
255
256
 
256
257
  :bulb: Can filters communicate together?
@@ -304,7 +305,8 @@ if __name__ == '__main__':
304
305
  ### History
305
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.
306
307
  - Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
307
- - Summer 2023: rewriting the whole core and supporting several graphical backends!
308
+ - August 2023: rewriting the whole core and supporting several graphical backends!
309
+ - September 2024: Gradio backend
308
310
 
309
311
 
310
312
 
@@ -324,3 +326,23 @@ if __name__ == '__main__':
324
326
  - Exploratory backends
325
327
  - Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
326
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
+ ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
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.6.0"
8
+ version = "0.7.0"
9
9
  authors = [
10
10
  { name="Balthazar Neveu", email="balthazarneveu@gmail.com" },
11
11
  ]
@@ -14,6 +14,13 @@ dependencies = [
14
14
  "numpy>=1.21.6",
15
15
  "Pillow>=9.0.1",
16
16
  "PyYAML>=5.4.1",
17
+ "PyQt6>=6.5.2",
18
+ "PyQt6_sip>=13.5.2",
19
+ "opencv_python_headless>=4.8.1.78",
20
+ "pytest>=6.2.5",
21
+ "ipywidgets>=8.0.7",
22
+ "pandas",
23
+ "gradio",
17
24
  ]
18
25
 
19
26
  description = "Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!"
@@ -56,4 +63,5 @@ full=[
56
63
  "pytest>=6.2.5",
57
64
  "ipywidgets>=8.0.7",
58
65
  "pandas",
59
- ]
66
+ "gradio",
67
+ ]
@@ -1,7 +1,7 @@
1
1
  # `interactive_pipe`
2
2
 
3
3
  Quick setup
4
- `pip install interactive-pipe[full]`
4
+ `pip install interactive-pipe`
5
5
 
6
6
  ### Concept
7
7
  - Develop an algorithm while debugging visually with plots, while checking robustness & continuity to parameters change.
@@ -22,8 +22,12 @@ Quick setup
22
22
 
23
23
  ----------------------
24
24
 
25
- ### Setup
26
- `pip install interactive-pipe[full]`
25
+ ### Local setup
26
+ ```
27
+ git clone git@github.com:balthazarneveu/interactive_pipe.git
28
+ cd interactive-pipe
29
+ pip install -e ".[full]"
30
+ ```
27
31
 
28
32
  ----------------------
29
33
 
@@ -46,7 +50,8 @@ Quick setup
46
50
  ----------------------
47
51
 
48
52
  ## :scroll: Features
49
- **Version 0.6.0**
53
+
54
+ **Version 0.7.0**
50
55
  - Modular multi-image processing filters
51
56
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
52
57
  - Support in jupyter notebooks
@@ -54,17 +59,10 @@ Quick setup
54
59
  - Cache intermediate results in RAM for much faster processing
55
60
  - `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
56
61
  - Support Curve plots (2D signals)
62
+ - :new: gradio backend (+allows sharing with others)
57
63
 
58
- #### :soon: Upcoming features:
59
- - :soon: Scientific visual debugging: Display both colored images, heatmaps & graphs
60
64
 
61
65
 
62
- #### :test_tube: Experimental features
63
- - custom events on specific key press
64
- - Display the execution graph of the pipeline
65
- - [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.
66
- - [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)
67
-
68
66
  #### :keyboard: Keyboard shortcuts
69
67
  Shortcuts while using the GUI (QT & matplotlib backends)
70
68
 
@@ -83,7 +81,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
83
81
  - supported backends
84
82
  - :ok: `gui='qt'` pyQt/pySide
85
83
  - :ok: `gui='mpl'` matplotlib
86
- - :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)
87
86
  - tested platforms
88
87
  - :ok: Linux (Ubuntu / KDE Neon)
89
88
  - :ok: RapsberryPi
@@ -91,16 +90,15 @@ Shortcuts while using the GUI (QT & matplotlib backends)
91
90
 
92
91
 
93
92
 
94
- | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
95
- |:-----: |:-----:|:------:|:----: |
96
- | Backend name | `qt` | `mpl` | `nb`|
97
- | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) |
98
- | Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
99
- | Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
100
- | Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
101
- | Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
102
- | Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
103
-
93
+ | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
94
+ |:-----: |:-----:|:------:|:----: |:----: |
95
+ | Backend name | `qt` | `mpl` | `nb`| `gradio` |
96
+ | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) | |
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:|
104
102
 
105
103
 
106
104
 
@@ -118,12 +116,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
118
116
  ![Speech processing exploration in a notebook](/doc/images/jupyter_integration_speech.png)
119
117
 
120
118
 
121
- #### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
122
- [ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
123
119
 
124
- :warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
125
-
126
- ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
127
120
 
128
121
 
129
122
  # Tutorials
@@ -214,7 +207,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
214
207
  ```
215
208
 
216
209
  - Note that you can also create filters which take no inputs and simply "generate" images.
217
- - The `color_choice` list will be turnt into a nice dropdown menu. Default value here will be red as this is the first element of the list!
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!
218
211
  ----------
219
212
 
220
213
  :bulb: Can filters communicate together?
@@ -268,7 +261,8 @@ if __name__ == '__main__':
268
261
  ### History
269
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.
270
263
  - Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
271
- - Summer 2023: rewriting the whole core and supporting several graphical backends!
264
+ - August 2023: rewriting the whole core and supporting several graphical backends!
265
+ - September 2024: Gradio backend
272
266
 
273
267
 
274
268
 
@@ -287,4 +281,24 @@ if __name__ == '__main__':
287
281
  - Animations/While loops/Video source (Time slider)
288
282
  - Exploratory backends
289
283
  - Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
290
- - 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
+ ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
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}
@@ -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.6.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
@@ -15,6 +15,13 @@ Requires-Dist: matplotlib>=3.5.3
15
15
  Requires-Dist: numpy>=1.21.6
16
16
  Requires-Dist: Pillow>=9.0.1
17
17
  Requires-Dist: PyYAML>=5.4.1
18
+ Requires-Dist: PyQt6>=6.5.2
19
+ Requires-Dist: PyQt6_sip>=13.5.2
20
+ Requires-Dist: opencv_python_headless>=4.8.1.78
21
+ Requires-Dist: pytest>=6.2.5
22
+ Requires-Dist: ipywidgets>=8.0.7
23
+ Requires-Dist: pandas
24
+ Requires-Dist: gradio
18
25
  Provides-Extra: qt6
19
26
  Requires-Dist: PyQt6>=6.5.2; extra == "qt6"
20
27
  Requires-Dist: PyQt6_sip>=13.5.2; extra == "qt6"
@@ -33,11 +40,12 @@ Requires-Dist: opencv_python_headless>=4.8.1.78; extra == "full"
33
40
  Requires-Dist: pytest>=6.2.5; extra == "full"
34
41
  Requires-Dist: ipywidgets>=8.0.7; extra == "full"
35
42
  Requires-Dist: pandas; extra == "full"
43
+ Requires-Dist: gradio; extra == "full"
36
44
 
37
45
  # `interactive_pipe`
38
46
 
39
47
  Quick setup
40
- `pip install interactive-pipe[full]`
48
+ `pip install interactive-pipe`
41
49
 
42
50
  ### Concept
43
51
  - Develop an algorithm while debugging visually with plots, while checking robustness & continuity to parameters change.
@@ -58,8 +66,12 @@ Quick setup
58
66
 
59
67
  ----------------------
60
68
 
61
- ### Setup
62
- `pip install interactive-pipe[full]`
69
+ ### Local setup
70
+ ```
71
+ git clone git@github.com:balthazarneveu/interactive_pipe.git
72
+ cd interactive-pipe
73
+ pip install -e ".[full]"
74
+ ```
63
75
 
64
76
  ----------------------
65
77
 
@@ -82,7 +94,8 @@ Quick setup
82
94
  ----------------------
83
95
 
84
96
  ## :scroll: Features
85
- **Version 0.6.0**
97
+
98
+ **Version 0.7.0**
86
99
  - Modular multi-image processing filters
87
100
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
88
101
  - Support in jupyter notebooks
@@ -90,16 +103,9 @@ Quick setup
90
103
  - Cache intermediate results in RAM for much faster processing
91
104
  - `KeyboardControl` : no slider on UI but exactly the same internal mechanism, update on key press.
92
105
  - Support Curve plots (2D signals)
93
-
94
- #### :soon: Upcoming features:
95
- - :soon: Scientific visual debugging: Display both colored images, heatmaps & graphs
106
+ - :new: gradio backend (+allows sharing with others)
96
107
 
97
108
 
98
- #### :test_tube: Experimental features
99
- - custom events on specific key press
100
- - Display the execution graph of the pipeline
101
- - [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.
102
- - [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)
103
109
 
104
110
  #### :keyboard: Keyboard shortcuts
105
111
  Shortcuts while using the GUI (QT & matplotlib backends)
@@ -119,7 +125,8 @@ Shortcuts while using the GUI (QT & matplotlib backends)
119
125
  - supported backends
120
126
  - :ok: `gui='qt'` pyQt/pySide
121
127
  - :ok: `gui='mpl'` matplotlib
122
- - :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)
123
130
  - tested platforms
124
131
  - :ok: Linux (Ubuntu / KDE Neon)
125
132
  - :ok: RapsberryPi
@@ -127,16 +134,15 @@ Shortcuts while using the GUI (QT & matplotlib backends)
127
134
 
128
135
 
129
136
 
130
- | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* |
131
- |:-----: |:-----:|:------:|:----: |
132
- | Backend name | `qt` | `mpl` | `nb`|
133
- | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) |
134
- | Plot curves | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
135
- | Auto refreshed layout | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
136
- | Keyboard shortcuts / fullscreen| :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
137
- | Audio support | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
138
- | Image buttons| :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
139
-
137
+ | :star: | *PyQt / PySide* | *Matplotlib* | *Jupyter notebooks including Google collab* | *Gradio* |
138
+ |:-----: |:-----:|:------:|:----: |:----: |
139
+ | Backend name | `qt` | `mpl` | `nb`| `gradio` |
140
+ | Preview | ![qt backend](/doc/images/qt_backend.jpg) | ![mpl backend](/doc/images/mpl_backend.jpg) | ![nb backend](/doc/images/notebook_backend.jpg) | |
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:|
140
146
 
141
147
 
142
148
 
@@ -154,12 +160,7 @@ Shortcuts while using the GUI (QT & matplotlib backends)
154
160
  ![Speech processing exploration in a notebook](/doc/images/jupyter_integration_speech.png)
155
161
 
156
162
 
157
- #### [Minimalistic pytorch based ISP ](https://github.com/balthazarneveu/interactive_pipe/tree/sample_interactive_isp/samples/isp)
158
- [ISP means image signal processor](https://en.wikipedia.org/wiki/Image_processor)
159
163
 
160
- :warning: Work in progess (no proper demosaicking, no denoiser, no tone mapping.)
161
-
162
- ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
163
164
 
164
165
 
165
166
  # Tutorials
@@ -250,7 +251,7 @@ def generate_flat_colored_image(color_choice=["red", "green", "blue", "gray"], g
250
251
  ```
251
252
 
252
253
  - Note that you can also create filters which take no inputs and simply "generate" images.
253
- - The `color_choice` list will be turnt into a nice dropdown menu. Default value here will be red as this is the first element of the list!
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!
254
255
  ----------
255
256
 
256
257
  :bulb: Can filters communicate together?
@@ -304,7 +305,8 @@ if __name__ == '__main__':
304
305
  ### History
305
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.
306
307
  - Later, more contributions were also made by [Giuseppe Moschetti](https://github.com/g-moschetti) and Sylvain Leroy.
307
- - Summer 2023: rewriting the whole core and supporting several graphical backends!
308
+ - August 2023: rewriting the whole core and supporting several graphical backends!
309
+ - September 2024: Gradio backend
308
310
 
309
311
 
310
312
 
@@ -324,3 +326,23 @@ if __name__ == '__main__':
324
326
  - Exploratory backends
325
327
  - Create a [textual](https://github.com/Textualize/textual) backend for simplified GUI (probably no images displayed)
326
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
+ ![Ultra simplistic ISP](/doc/images/isp_pipeline.png)
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
@@ -2,6 +2,13 @@ matplotlib>=3.5.3
2
2
  numpy>=1.21.6
3
3
  Pillow>=9.0.1
4
4
  PyYAML>=5.4.1
5
+ PyQt6>=6.5.2
6
+ PyQt6_sip>=13.5.2
7
+ opencv_python_headless>=4.8.1.78
8
+ pytest>=6.2.5
9
+ ipywidgets>=8.0.7
10
+ pandas
11
+ gradio
5
12
 
6
13
  [full]
7
14
  PyQt6>=6.5.2
@@ -10,6 +17,7 @@ opencv_python_headless>=4.8.1.78
10
17
  pytest>=6.2.5
11
18
  ipywidgets>=8.0.7
12
19
  pandas
20
+ gradio
13
21
 
14
22
  [notebook]
15
23
  ipywidgets>=8.0.7