Start of crop widget
This commit is contained in:
@ -13,7 +13,7 @@ from .layout_manager import LayoutManager
|
||||
|
||||
from .widgets.base_widget import BaseWidget
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
||||
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
85
negstation/widgets/crop_widget.py
Normal file
85
negstation/widgets/crop_widget.py
Normal file
@ -0,0 +1,85 @@
|
||||
import dearpygui.dearpygui as dpg
|
||||
import numpy as np
|
||||
from .stage_viewer_widget import PipelineStageViewer
|
||||
|
||||
|
||||
class CropWidget(PipelineStageViewer):
|
||||
name = "Crop Image"
|
||||
register = True
|
||||
has_pipeline_in = True
|
||||
has_pipeline_out = True
|
||||
|
||||
def __init__(self, manager, logger):
|
||||
super().__init__(manager, logger)
|
||||
self.crop_start = None # (x, y)
|
||||
self.crop_end = None # (x, y)
|
||||
self.crop_active = False
|
||||
|
||||
self.manager.bus.subscribe("img_clicked", self.on_click)
|
||||
self.manager.bus.subscribe("img_dragged", self.on_drag)
|
||||
|
||||
def create_pipeline_stage_content(self):
|
||||
super().create_pipeline_stage_content()
|
||||
|
||||
# def on_full_res_pipeline_data(self, img):
|
||||
# pass
|
||||
|
||||
def on_pipeline_data(self, img):
|
||||
if img is None:
|
||||
return
|
||||
self.img = img
|
||||
|
||||
if self.crop_start and self.crop_end:
|
||||
x0, y0 = self.crop_start
|
||||
x1, y1 = self.crop_end
|
||||
x0, x1 = sorted((int(x0), int(x1)))
|
||||
y0, y1 = sorted((int(y0), int(y1)))
|
||||
|
||||
x0 = max(0, min(x0, img.shape[1]-1))
|
||||
x1 = max(0, min(x1, img.shape[1]-1))
|
||||
y0 = max(0, min(y0, img.shape[0]-1))
|
||||
y1 = max(0, min(y1, img.shape[0]-1))
|
||||
|
||||
cropped = img[y0:y1, x0:x1, :]
|
||||
self.publish_stage(cropped)
|
||||
else:
|
||||
self.publish_stage(img)
|
||||
|
||||
self.needs_update = True
|
||||
|
||||
def on_click(self, data):
|
||||
if data["obj"] is not self:
|
||||
return
|
||||
if data["button"] == "left":
|
||||
self.crop_start = data["pos"]
|
||||
self.crop_end = data["pos"]
|
||||
self.crop_active = True
|
||||
self.needs_update = True
|
||||
|
||||
def on_drag(self, data):
|
||||
if data["obj"] is not self or not self.crop_active:
|
||||
return
|
||||
self.crop_end = data["pos"]
|
||||
self.needs_update = True
|
||||
|
||||
def update_texture(self, img):
|
||||
super().update_texture(img)
|
||||
if self.crop_start and self.crop_end:
|
||||
# map image coords back to screen coords
|
||||
x0, y0 = self.crop_start
|
||||
x1, y1 = self.crop_end
|
||||
h, w, _ = self.img.shape
|
||||
img_x, img_y = self.image_position
|
||||
img_w, img_h = self.scaled_size
|
||||
|
||||
p0 = (
|
||||
img_x + x0 / w * img_w,
|
||||
img_y + y0 / h * img_h
|
||||
)
|
||||
p1 = (
|
||||
img_x + x1 / w * img_w,
|
||||
img_y + y1 / h * img_h
|
||||
)
|
||||
|
||||
dpg.draw_rectangle(pmin=p0, pmax=p1, color=(255, 255, 0, 255),
|
||||
fill=(255, 255, 0, 50), thickness=2, parent=self.drawlist)
|
@ -66,6 +66,7 @@ class PipelineStageViewer(PipelineStageWidget):
|
||||
if app_data[0] == 0
|
||||
else ("left" if app_data[0] == 1 else ("middle"))
|
||||
),
|
||||
"obj":self,
|
||||
},
|
||||
)
|
||||
|
||||
@ -93,7 +94,8 @@ class PipelineStageViewer(PipelineStageWidget):
|
||||
"stage_id": self.pipeline_stage_in_id,
|
||||
"pos": (x, y),
|
||||
"button": data['button'],
|
||||
"delta": data['delta']
|
||||
"delta": data['delta'],
|
||||
"obj":self,
|
||||
},
|
||||
)
|
||||
|
||||
@ -120,7 +122,8 @@ class PipelineStageViewer(PipelineStageWidget):
|
||||
{
|
||||
"stage_id": self.pipeline_stage_in_id,
|
||||
"pos": (x, y),
|
||||
"delta": data
|
||||
"delta": data,
|
||||
"obj":self,
|
||||
},
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user