Added invert widget
This commit is contained in:
@ -5,7 +5,6 @@ import importlib
|
|||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from importlib.machinery import SourceFileLoader
|
|
||||||
|
|
||||||
from .event_bus import EventBus
|
from .event_bus import EventBus
|
||||||
from .image_pipeline import ImagePipeline
|
from .image_pipeline import ImagePipeline
|
||||||
@ -59,6 +58,7 @@ class EditorManager:
|
|||||||
ModuleBaseWidget
|
ModuleBaseWidget
|
||||||
and issubclass(cls, ModuleBaseWidget)
|
and issubclass(cls, ModuleBaseWidget)
|
||||||
and cls is not ModuleBaseWidget
|
and cls is not ModuleBaseWidget
|
||||||
|
and cls.register
|
||||||
):
|
):
|
||||||
logging.info(
|
logging.info(
|
||||||
f" -> Found and registered widget: {name}")
|
f" -> Found and registered widget: {name}")
|
||||||
|
@ -9,6 +9,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
class BaseWidget:
|
class BaseWidget:
|
||||||
name: str = "BaseWidget"
|
name: str = "BaseWidget"
|
||||||
|
register: bool = False
|
||||||
|
|
||||||
def __init__(self, manager: "EditorManager", logger: logging.Logger):
|
def __init__(self, manager: "EditorManager", logger: logging.Logger):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
25
negstation/widgets/invert_stage.py
Normal file
25
negstation/widgets/invert_stage.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import dearpygui.dearpygui as dpg
|
||||||
|
import numpy as np
|
||||||
|
from .pipeline_stage_widget import PipelineStageWidget
|
||||||
|
|
||||||
|
|
||||||
|
class InvertStage(PipelineStageWidget):
|
||||||
|
name = "Invert Image"
|
||||||
|
register = True
|
||||||
|
|
||||||
|
def __init__(self, manager, logger):
|
||||||
|
super().__init__(manager, logger)
|
||||||
|
self.stage_out = "inverted_image"
|
||||||
|
|
||||||
|
def create_content(self):
|
||||||
|
dpg.add_button(label="Invert", callback=lambda s, a, u: self._do_invert())
|
||||||
|
|
||||||
|
def on_stage(self, img):
|
||||||
|
self._do_invert()
|
||||||
|
|
||||||
|
def _do_invert(self):
|
||||||
|
if self.img is None:
|
||||||
|
return
|
||||||
|
inverted = self.img.copy()
|
||||||
|
inverted[...,:3] = 1.0 - inverted[...,:3]
|
||||||
|
self.publish(inverted)
|
@ -7,6 +7,7 @@ from .base_widget import BaseWidget
|
|||||||
|
|
||||||
class OpenImageWidget(BaseWidget):
|
class OpenImageWidget(BaseWidget):
|
||||||
name: str = "Open Image"
|
name: str = "Open Image"
|
||||||
|
register = True
|
||||||
|
|
||||||
def __init__(self, manager, logger, stage_out="loaded_image"):
|
def __init__(self, manager, logger, stage_out="loaded_image"):
|
||||||
super().__init__(manager, logger)
|
super().__init__(manager, logger)
|
||||||
|
63
negstation/widgets/pipeline_stage_widget.py
Normal file
63
negstation/widgets/pipeline_stage_widget.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import dearpygui.dearpygui as dpg
|
||||||
|
import numpy as np
|
||||||
|
from .base_widget import BaseWidget
|
||||||
|
|
||||||
|
|
||||||
|
class PipelineStageWidget(BaseWidget):
|
||||||
|
register = False
|
||||||
|
|
||||||
|
def __init__(self, manager, logger):
|
||||||
|
super().__init__(manager, logger)
|
||||||
|
self.stage_in = ""
|
||||||
|
self.stage_out = ""
|
||||||
|
self.img = None
|
||||||
|
|
||||||
|
self.manager.bus.subscribe(
|
||||||
|
"pipeline_stage", self._on_pipeline, main_thread=True
|
||||||
|
)
|
||||||
|
self.manager.bus.subscribe(
|
||||||
|
"pipeline_stages", self._on_stage_list, main_thread=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
with dpg.window(label=self.name, tag=self.window_tag, width=400, height=300):
|
||||||
|
# top‐row: input / output
|
||||||
|
dpg.add_text("Configuration:")
|
||||||
|
self.combo = dpg.add_combo(
|
||||||
|
label="Stage In", items=[], callback=self._on_select
|
||||||
|
)
|
||||||
|
dpg.add_input_text(
|
||||||
|
label="Stage Out",
|
||||||
|
default_value=self.stage_out,
|
||||||
|
callback=lambda s, a, u: setattr(self, "stage_out", a),
|
||||||
|
)
|
||||||
|
dpg.add_separator()
|
||||||
|
# now let subclasses populate the rest
|
||||||
|
self.create_content()
|
||||||
|
|
||||||
|
def _on_select(self, sender, selected_stage):
|
||||||
|
self.stage_in = selected_stage
|
||||||
|
self.img = self.manager.pipeline.get_stage(selected_stage)
|
||||||
|
self.on_stage(self.img)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_content(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _on_pipeline(self, data):
|
||||||
|
name, img = data
|
||||||
|
if name == self.stage_in:
|
||||||
|
self.img = img
|
||||||
|
self.on_stage(img)
|
||||||
|
|
||||||
|
def _on_stage_list(self, stages):
|
||||||
|
self.stages = stages
|
||||||
|
dpg.configure_item(self.combo, items=stages)
|
||||||
|
|
||||||
|
def on_stage(self, img: np.ndarray):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def publish(self, img: np.ndarray):
|
||||||
|
self.manager.pipeline.add_stage(self.stage_out, img)
|
@ -6,6 +6,7 @@ from .base_widget import BaseWidget
|
|||||||
|
|
||||||
class StageViewerWidget(BaseWidget):
|
class StageViewerWidget(BaseWidget):
|
||||||
name: str = "Image Stage Viewer"
|
name: str = "Image Stage Viewer"
|
||||||
|
register = True
|
||||||
|
|
||||||
def __init__(self, manager, logger):
|
def __init__(self, manager, logger):
|
||||||
super().__init__(manager, logger)
|
super().__init__(manager, logger)
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
[Window][WindowOverViewport_11111111]
|
[Window][WindowOverViewport_11111111]
|
||||||
Pos=0,19
|
Pos=0,19
|
||||||
Size=800,581
|
Size=814,581
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][###22]
|
[Window][###22]
|
||||||
Pos=0,19
|
Pos=0,19
|
||||||
Size=299,581
|
Size=291,244
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000001,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][###27]
|
[Window][###27]
|
||||||
Pos=301,19
|
Pos=293,19
|
||||||
Size=499,581
|
Size=521,581
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
@ -20,8 +20,24 @@ Pos=60,60
|
|||||||
Size=400,400
|
Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Docking][Data]
|
[Window][###41]
|
||||||
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=800,581 Split=X Selected=0x26E8F608
|
Pos=0,312
|
||||||
DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=299,581 Selected=0xEE087978
|
Size=299,288
|
||||||
DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=499,581 CentralNode=1 Selected=0x26E8F608
|
Collapsed=0
|
||||||
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
[Window][###34]
|
||||||
|
Pos=0,265
|
||||||
|
Size=291,335
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000006,0
|
||||||
|
|
||||||
|
[Docking][Data]
|
||||||
|
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=814,581 Split=X Selected=0x26E8F608
|
||||||
|
DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=291,581 Split=Y Selected=0xEE087978
|
||||||
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=299,291 Split=Y Selected=0xEE087978
|
||||||
|
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=299,244 Selected=0xEE087978
|
||||||
|
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=299,335 Selected=0xAA145F7D
|
||||||
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=299,288 Selected=0x7FF1E0B5
|
||||||
|
DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=521,581 CentralNode=1 Selected=0x26E8F608
|
||||||
|
|
||||||
|
@ -6,5 +6,9 @@
|
|||||||
{
|
{
|
||||||
"widget_type": "StageViewerWidget",
|
"widget_type": "StageViewerWidget",
|
||||||
"config": {}
|
"config": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget_type": "InvertStage",
|
||||||
|
"config": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
Reference in New Issue
Block a user