Loading ui/canvas.py +25 −11 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ class Canvas(QGraphicsScene): scalefactor_changed = pyqtSignal() end_create_textblock = pyqtSignal(QRectF) end_create_rect = pyqtSignal(QRectF) delete_textblks = pyqtSignal() finish_painting = pyqtSignal(StrokeItem) finish_erasing = pyqtSignal(StrokeItem) Loading @@ -78,9 +79,8 @@ class Canvas(QGraphicsScene): canvas_undostack_changed = pyqtSignal() imgtrans_proj: ProjImgTrans = None painting = False painting_pen = QPen() image_edit_mode = None image_edit_mode = ImageEditMode.NONE alt_pressed = False scale_tool_mode = False Loading Loading @@ -241,7 +241,7 @@ class Canvas(QGraphicsScene): item.setPen(self.painting_pen) item.setParentItem(self.drawingLayer) def startCreateTextblock(self, pos: QPointF): def startCreateTextblock(self, pos: QPointF, hide_control: bool = False): self.creating_textblock = True self.create_block_origin = pos self.gv.viewport().setCursor(Qt.CrossCursor) Loading @@ -249,11 +249,16 @@ class Canvas(QGraphicsScene): self.txtblkShapeControl.setPos(0, 0) self.txtblkShapeControl.setRotation(0) self.txtblkShapeControl.setRect(QRectF(pos, QSizeF(1, 1))) if hide_control: self.txtblkShapeControl.hideControls() self.txtblkShapeControl.show() def endCreateTextblock(self): self.creating_textblock = False self.gv.viewport().setCursor(Qt.ArrowCursor) if self.creating_normal_rect: self.end_create_rect.emit(self.txtblkShapeControl.rect()) else: self.txtblkShapeControl.hide() self.end_create_textblock.emit(self.txtblkShapeControl.rect()) Loading Loading @@ -290,6 +295,8 @@ class Canvas(QGraphicsScene): elif self.painting: self.stroke_path_item = PenStrokeItem(self.imgLayer.mapFromScene(event.scenePos())) self.addStrokeItem(self.stroke_path_item) elif self.creating_normal_rect: return self.startCreateTextblock(event.scenePos(), hide_control=True) elif event.button() == Qt.MouseButton.RightButton: if self.painting: Loading @@ -298,11 +305,15 @@ class Canvas(QGraphicsScene): return super().mousePressEvent(event) @property def creating_normal_rect(self): return self.image_edit_mode == ImageEditMode.RectTool def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None: if event.button() == Qt.RightButton: if self.creating_textblock: return self.endCreateTextblock() elif self.stroke_path_item is not None: elif event.button() == Qt.RightButton: if self.stroke_path_item is not None: self.finish_erasing.emit(self.stroke_path_item) elif event.button() == Qt.MouseButton.LeftButton: if self.stroke_path_item is not None: Loading Loading @@ -351,7 +362,11 @@ class Canvas(QGraphicsScene): self.maskLayer.setVisible(False) self.gv.setCursor(self.default_cursor) self.gv.setDragMode(QGraphicsView.ScrollHandDrag) self.painting = False self.image_edit_mode = ImageEditMode.NONE @property def painting(self): return self.image_edit_mode == ImageEditMode.PenTool or self.image_edit_mode == ImageEditMode.InpaintTool def setMaskTransparencyBySlider(self, slider_value: int): self.setMaskTransparency(slider_value / 100) Loading @@ -378,7 +393,6 @@ class Canvas(QGraphicsScene): def on_hide_canvas(self): self.alt_pressed = False self.scale_tool_mode = False self.textblock_mode = False self.creating_textblock = False self.create_block_origin = None self.editing_textblkitem = None Loading ui/constants.py +1 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ CONFIG_FONTSIZE_HEADER = 24 CONFIG_FONTSIZE_TABLE = 14 CONFIG_FONTSIZE_CONTENT = 14 CONFIG_COMBOBOX_HEIGHT = 45 CONFIG_COMBOBOX_SHORT = 300 CONFIG_COMBOBOX_MIDEAN = 500 CONFIG_COMBOBOX_LONG = 700 Loading ui/drawingpanel.py +133 −49 Original line number Diff line number Diff line from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QSize, QLineF from PyQt5.QtWidgets import QBoxLayout, QCheckBox, QHBoxLayout, QGraphicsView, QUndoCommand, QStackedWidget, QVBoxLayout, QLabel, QGraphicsEllipseItem from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QSize, QLineF, QRect, QRectF from PyQt5.QtWidgets import QComboBox, QSizePolicy, QBoxLayout, QCheckBox, QHBoxLayout, QGraphicsView, QUndoCommand, QStackedWidget, QVBoxLayout, QLabel, QGraphicsEllipseItem from PyQt5.QtGui import QPen, QColor, QCursor, QPainter, QPixmap, QBrush, QFontMetrics from .stylewidgets import Widget, SeparatorWidget, ColorPicker, PaintQSlider from .canvas import Canvas from .misc import DrawPanelConfig from utils.imgproc_utils import enlarge_window from typing import Union, Tuple, List import numpy as np import cv2 from utils.imgproc_utils import enlarge_window from utils.textblock_mask import canny_flood, connected_canny_flood from .dl_manager import DLManager from .image_edit import ImageEditMode, StrokeItem from .configpanel import InpaintConfigPanel from .stylewidgets import Widget, SeparatorWidget, ColorPicker, PaintQSlider from .canvas import Canvas from .misc import DrawPanelConfig from .constants import CONFIG_COMBOBOX_SHORT, CONFIG_COMBOBOX_HEIGHT INPAINT_BRUSH_COLOR = QColor(127, 0, 127, 127) MAX_PEN_SIZE = 1000 Loading Loading @@ -145,6 +149,41 @@ class PenConfigPanel(Widget): self.colorChanged.emit(color) class RectPanel(Widget): method_changed = pyqtSignal(int) def __init__(self, inpainter_panel: InpaintConfigPanel, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.inpainter_panel = inpainter_panel self.methodComboBox = QComboBox() self.methodComboBox.setFixedHeight(CONFIG_COMBOBOX_HEIGHT) self.methodComboBox.setFixedWidth(CONFIG_COMBOBOX_SHORT) self.methodComboBox.addItems([self.tr('method 1'), self.tr('method 2')]) layout = QVBoxLayout(self) layout.setAlignment(Qt.AlignmentFlag.AlignTop) layout.addWidget(self.methodComboBox) layout.addWidget(inpainter_panel) layout.setSpacing(20) self.vlayout = layout def showEvent(self, e) -> None: self.inpainter_panel.needInpaintChecker.setVisible(False) self.vlayout.addWidget(self.inpainter_panel) super().showEvent(e) def hideEvent(self, e) -> None: self.vlayout.removeWidget(self.inpainter_panel) self.inpainter_panel.needInpaintChecker.setVisible(True) return super().hideEvent(e) def get_maskseg_method(self): if self.methodComboBox.currentIndex() == 0: return canny_flood else: return connected_canny_flood class DrawingPanel(Widget): scale_tool_pos: QPointF = None Loading @@ -163,11 +202,13 @@ class DrawingPanel(Widget): canvas.scale_tool.connect(self.on_scale_tool) canvas.end_scale_tool.connect(self.on_end_scale_tool) canvas.scalefactor_changed.connect(self.on_canvas_scalefactor_changed) canvas.end_create_rect.connect(self.on_end_create_rect) self.currentTool: DrawToolCheckBox = None self.handTool = DrawToolCheckBox() self.handTool.setObjectName("DrawHandTool") self.handTool.checked.connect(self.on_use_handtool) self.handTool.stateChanged.connect(self.on_handchecker_changed) self.inpaintTool = DrawToolCheckBox() self.inpaintTool.setObjectName("DrawInpaintTool") self.inpaintTool.checked.connect(self.on_use_inpainttool) Loading @@ -176,7 +217,8 @@ class DrawingPanel(Widget): self.rectTool = DrawToolCheckBox() self.rectTool.setObjectName("DrawRectTool") self.rectTool.checked.connect(self.on_use_rectremoval_tool) self.rectTool.checked.connect(self.on_use_rect_tool) self.rectPanel = RectPanel(inpainter_panel) self.penTool = DrawToolCheckBox() self.penTool.setObjectName("DrawPenTool") Loading @@ -201,8 +243,10 @@ class DrawingPanel(Widget): self.setPenToolColor([0, 0, 0, 127]) self.toolConfigStackwidget = QStackedWidget() self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.addWidget(self.inpaintConfigPanel) self.toolConfigStackwidget.addWidget(self.penConfigPanel) self.toolConfigStackwidget.addWidget(self.rectPanel) self.maskTransperancySlider = PaintQSlider(' value%', Qt.Orientation.Horizontal) self.maskTransperancySlider.setFixedHeight(40) Loading Loading @@ -244,16 +288,13 @@ class DrawingPanel(Widget): def on_use_handtool(self) -> None: if self.currentTool is not None and self.currentTool != self.handTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.hide() self.currentTool = self.handTool self.canvas.gv.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) self.canvas.painting = False self.canvas.image_edit_mode = ImageEditMode.HandTool def on_use_inpainttool(self) -> None: if self.currentTool is not None and self.currentTool != self.inpaintTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.show() self.currentTool = self.inpaintTool self.canvas.image_edit_mode = ImageEditMode.InpaintTool self.canvas.painting_pen = self.inpaint_pen Loading @@ -261,12 +302,10 @@ class DrawingPanel(Widget): if self.isVisible(): self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.setInpaintCursor() self.canvas.painting = True def on_use_pentool(self) -> None: if self.currentTool is not None and self.currentTool != self.penTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.show() self.currentTool = self.penTool self.canvas.painting_pen = self.pentool_pen self.canvas.image_edit_mode = ImageEditMode.PenTool Loading @@ -274,10 +313,15 @@ class DrawingPanel(Widget): if self.isVisible(): self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.setPenCursor() self.canvas.painting = True def on_use_rectremoval_tool(self) -> None: print('use rect removal tool') def on_use_rect_tool(self) -> None: if self.currentTool is not None and self.currentTool != self.rectTool: self.currentTool.setChecked(False) self.currentTool = self.rectTool self.toolConfigStackwidget.setCurrentWidget(self.rectPanel) self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.canvas.image_edit_mode = ImageEditMode.RectTool def get_config(self) -> DrawPanelConfig: config = DrawPanelConfig() Loading Loading @@ -408,8 +452,9 @@ class DrawingPanel(Widget): self.inpaint_stroke.addStroke(inpaint_stroke.stroke) self.canvas.removeItem(inpaint_stroke) def runInpaint(self): def runInpaint(self, inpaint_dict=None): if inpaint_dict is None: if self.inpaint_stroke is None: return mask = self.inpaint_stroke.getSubimg(convert_mask=True) Loading @@ -434,9 +479,9 @@ class DrawingPanel(Widget): mask = cv2.copyMakeBorder(mask, top, bottom, left, right, cv2.BORDER_CONSTANT, value=0) inpaint_rect = rect_enlarged img = img[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]] self.canvas.painting = False inpaint_dict = {'img': img, 'mask': mask, 'inpaint_rect': inpaint_rect} self.canvas.image_edit_mode = ImageEditMode.NONE self.dl_manager.canvas_inpaint(inpaint_dict) def on_inpaint_finished(self, inpaint_dict): Loading @@ -444,12 +489,16 @@ class DrawingPanel(Widget): inpaint_rect = inpaint_dict['inpaint_rect'] mask_array = self.canvas.imgtrans_proj.mask_array mask = cv2.bitwise_or(inpaint_dict['mask'], mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]) if self.inpaint_stroke is not None: self.canvas.removeItem(self.inpaint_stroke) self.inpaint_stroke = None self.canvas.undoStack.push(InpaintUndoCommand(self.canvas, inpainted, mask, inpaint_rect)) self.canvas.undoStack.push(InpaintUndoCommand(self.canvas, inpainted, mask, inpaint_rect)) if self.currentTool == self.inpaintTool: self.canvas.painting = True self.canvas.image_edit_mode = ImageEditMode.InpaintTool elif self.currentTool == self.rectTool: self.canvas.image_edit_mode = ImageEditMode.RectTool def on_finish_erasing(self, stroke_item: StrokeItem): Loading Loading @@ -479,7 +528,7 @@ class DrawingPanel(Widget): def on_inpaint_failed(self): if self.currentTool == self.inpaintTool and self.inpaint_stroke is not None: self.canvas.painting = True self.canvas.image_edit_mode = ImageEditMode.InpaintTool self.canvas.removeItem(self.inpaint_stroke) self.inpaint_stroke = None Loading Loading @@ -549,6 +598,40 @@ class DrawingPanel(Widget): def setInpaintCursor(self): self.canvas.gv.setCursor(self.get_pen_cursor(INPAINT_BRUSH_COLOR, self.inpaint_pen.width())) def on_handchecker_changed(self): if self.handTool.isChecked(): self.toolConfigStackwidget.hide() else: self.toolConfigStackwidget.show() def on_end_create_rect(self, rect: QRectF): if self.currentTool == self.rectTool: self.canvas.image_edit_mode = ImageEditMode.NONE img = self.canvas.imgtrans_proj.inpainted_array im_h, im_w = img.shape[:2] xyxy = [rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()] xyxy = np.array(xyxy) / self.canvas.scale_factor xyxy[[0, 2]] = np.clip(xyxy[[0, 2]], 0, im_w - 1) xyxy[[1, 3]] = np.clip(xyxy[[1, 3]], 0, im_h - 1) x1, y1, x2, y2 = xyxy.astype(np.int64) if y2 - y1 < 2 or x2 - x1 < 2: self.canvas.txtblkShapeControl.showControls() self.canvas.txtblkShapeControl.hide() self.canvas.image_edit_mode = ImageEditMode.RectTool return im = img[y1: y2, x1: x2] maskseg_method = self.rectPanel.get_maskseg_method() mask, ballon_mask, bub_dict = maskseg_method(im) inpaint_dict = {'img': im, 'mask': mask, 'inpaint_rect': [x1, y1, x2, y2]} self.runInpaint(inpaint_dict=inpaint_dict) # self.canvas.image_edit_mode = ImageEditMode.RectTool # cv2.imshow('img', im) # cv2.imshow('mask', mask) # cv2.imshow('ballon_mask', ballon_mask) # cv2.waitKey(0) class InpaintUndoCommand(QUndoCommand): def __init__(self, canvas: Canvas, inpainted: np.ndarray, mask: np.ndarray, inpaint_rect: list): Loading Loading @@ -585,3 +668,4 @@ class InpaintUndoCommand(QUndoCommand): mask_view[:] = self.undo_mask self.canvas.setInpaintLayer() self.canvas.setMaskLayer() ui/image_edit.py +2 −0 Original line number Diff line number Diff line Loading @@ -10,9 +10,11 @@ import cv2 SIZE_MAX = 2147483647 class ImageEditMode: NONE = 0 HandTool = 0 InpaintTool = 1 PenTool = 2 RectTool = 3 class StrokeItem(QGraphicsPathItem): def __init__(self, origin_point: QPointF): Loading ui/mainwindow.py +5 −2 Original line number Diff line number Diff line Loading @@ -56,12 +56,14 @@ class MainWindow(QMainWindow): if osp.exists(proj_dir): self.openDir(proj_dir) textblock_mode = self.config.imgtrans_textblock self.bottomBar.texteditChecker.click() self.bottomBar.paintChecker.click() if self.config.imgtrans_textedit: if textblock_mode: self.bottomBar.textblockChecker.setChecked(True) self.bottomBar.texteditChecker.click() if self.config.imgtrans_textblock: self.bottomBar.textblockChecker.click() elif not self.config.imgtrans_paintmode: self.bottomBar.paintChecker.click() self.comicTransSplitter.setStretchFactor(2, 0.5) Loading Loading @@ -315,6 +317,7 @@ class MainWindow(QMainWindow): self.rightComicTransStackPanel.setCurrentIndex(1) self.st_manager.setTextEditMode(True) self.bottomBar.originalSlider.setHidden(True) self.setTextBlockMode() else: self.bottomBar.textblockChecker.hide() self.rightComicTransStackPanel.setHidden(True) Loading Loading
ui/canvas.py +25 −11 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ class Canvas(QGraphicsScene): scalefactor_changed = pyqtSignal() end_create_textblock = pyqtSignal(QRectF) end_create_rect = pyqtSignal(QRectF) delete_textblks = pyqtSignal() finish_painting = pyqtSignal(StrokeItem) finish_erasing = pyqtSignal(StrokeItem) Loading @@ -78,9 +79,8 @@ class Canvas(QGraphicsScene): canvas_undostack_changed = pyqtSignal() imgtrans_proj: ProjImgTrans = None painting = False painting_pen = QPen() image_edit_mode = None image_edit_mode = ImageEditMode.NONE alt_pressed = False scale_tool_mode = False Loading Loading @@ -241,7 +241,7 @@ class Canvas(QGraphicsScene): item.setPen(self.painting_pen) item.setParentItem(self.drawingLayer) def startCreateTextblock(self, pos: QPointF): def startCreateTextblock(self, pos: QPointF, hide_control: bool = False): self.creating_textblock = True self.create_block_origin = pos self.gv.viewport().setCursor(Qt.CrossCursor) Loading @@ -249,11 +249,16 @@ class Canvas(QGraphicsScene): self.txtblkShapeControl.setPos(0, 0) self.txtblkShapeControl.setRotation(0) self.txtblkShapeControl.setRect(QRectF(pos, QSizeF(1, 1))) if hide_control: self.txtblkShapeControl.hideControls() self.txtblkShapeControl.show() def endCreateTextblock(self): self.creating_textblock = False self.gv.viewport().setCursor(Qt.ArrowCursor) if self.creating_normal_rect: self.end_create_rect.emit(self.txtblkShapeControl.rect()) else: self.txtblkShapeControl.hide() self.end_create_textblock.emit(self.txtblkShapeControl.rect()) Loading Loading @@ -290,6 +295,8 @@ class Canvas(QGraphicsScene): elif self.painting: self.stroke_path_item = PenStrokeItem(self.imgLayer.mapFromScene(event.scenePos())) self.addStrokeItem(self.stroke_path_item) elif self.creating_normal_rect: return self.startCreateTextblock(event.scenePos(), hide_control=True) elif event.button() == Qt.MouseButton.RightButton: if self.painting: Loading @@ -298,11 +305,15 @@ class Canvas(QGraphicsScene): return super().mousePressEvent(event) @property def creating_normal_rect(self): return self.image_edit_mode == ImageEditMode.RectTool def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None: if event.button() == Qt.RightButton: if self.creating_textblock: return self.endCreateTextblock() elif self.stroke_path_item is not None: elif event.button() == Qt.RightButton: if self.stroke_path_item is not None: self.finish_erasing.emit(self.stroke_path_item) elif event.button() == Qt.MouseButton.LeftButton: if self.stroke_path_item is not None: Loading Loading @@ -351,7 +362,11 @@ class Canvas(QGraphicsScene): self.maskLayer.setVisible(False) self.gv.setCursor(self.default_cursor) self.gv.setDragMode(QGraphicsView.ScrollHandDrag) self.painting = False self.image_edit_mode = ImageEditMode.NONE @property def painting(self): return self.image_edit_mode == ImageEditMode.PenTool or self.image_edit_mode == ImageEditMode.InpaintTool def setMaskTransparencyBySlider(self, slider_value: int): self.setMaskTransparency(slider_value / 100) Loading @@ -378,7 +393,6 @@ class Canvas(QGraphicsScene): def on_hide_canvas(self): self.alt_pressed = False self.scale_tool_mode = False self.textblock_mode = False self.creating_textblock = False self.create_block_origin = None self.editing_textblkitem = None Loading
ui/constants.py +1 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ CONFIG_FONTSIZE_HEADER = 24 CONFIG_FONTSIZE_TABLE = 14 CONFIG_FONTSIZE_CONTENT = 14 CONFIG_COMBOBOX_HEIGHT = 45 CONFIG_COMBOBOX_SHORT = 300 CONFIG_COMBOBOX_MIDEAN = 500 CONFIG_COMBOBOX_LONG = 700 Loading
ui/drawingpanel.py +133 −49 Original line number Diff line number Diff line from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QSize, QLineF from PyQt5.QtWidgets import QBoxLayout, QCheckBox, QHBoxLayout, QGraphicsView, QUndoCommand, QStackedWidget, QVBoxLayout, QLabel, QGraphicsEllipseItem from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QSize, QLineF, QRect, QRectF from PyQt5.QtWidgets import QComboBox, QSizePolicy, QBoxLayout, QCheckBox, QHBoxLayout, QGraphicsView, QUndoCommand, QStackedWidget, QVBoxLayout, QLabel, QGraphicsEllipseItem from PyQt5.QtGui import QPen, QColor, QCursor, QPainter, QPixmap, QBrush, QFontMetrics from .stylewidgets import Widget, SeparatorWidget, ColorPicker, PaintQSlider from .canvas import Canvas from .misc import DrawPanelConfig from utils.imgproc_utils import enlarge_window from typing import Union, Tuple, List import numpy as np import cv2 from utils.imgproc_utils import enlarge_window from utils.textblock_mask import canny_flood, connected_canny_flood from .dl_manager import DLManager from .image_edit import ImageEditMode, StrokeItem from .configpanel import InpaintConfigPanel from .stylewidgets import Widget, SeparatorWidget, ColorPicker, PaintQSlider from .canvas import Canvas from .misc import DrawPanelConfig from .constants import CONFIG_COMBOBOX_SHORT, CONFIG_COMBOBOX_HEIGHT INPAINT_BRUSH_COLOR = QColor(127, 0, 127, 127) MAX_PEN_SIZE = 1000 Loading Loading @@ -145,6 +149,41 @@ class PenConfigPanel(Widget): self.colorChanged.emit(color) class RectPanel(Widget): method_changed = pyqtSignal(int) def __init__(self, inpainter_panel: InpaintConfigPanel, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.inpainter_panel = inpainter_panel self.methodComboBox = QComboBox() self.methodComboBox.setFixedHeight(CONFIG_COMBOBOX_HEIGHT) self.methodComboBox.setFixedWidth(CONFIG_COMBOBOX_SHORT) self.methodComboBox.addItems([self.tr('method 1'), self.tr('method 2')]) layout = QVBoxLayout(self) layout.setAlignment(Qt.AlignmentFlag.AlignTop) layout.addWidget(self.methodComboBox) layout.addWidget(inpainter_panel) layout.setSpacing(20) self.vlayout = layout def showEvent(self, e) -> None: self.inpainter_panel.needInpaintChecker.setVisible(False) self.vlayout.addWidget(self.inpainter_panel) super().showEvent(e) def hideEvent(self, e) -> None: self.vlayout.removeWidget(self.inpainter_panel) self.inpainter_panel.needInpaintChecker.setVisible(True) return super().hideEvent(e) def get_maskseg_method(self): if self.methodComboBox.currentIndex() == 0: return canny_flood else: return connected_canny_flood class DrawingPanel(Widget): scale_tool_pos: QPointF = None Loading @@ -163,11 +202,13 @@ class DrawingPanel(Widget): canvas.scale_tool.connect(self.on_scale_tool) canvas.end_scale_tool.connect(self.on_end_scale_tool) canvas.scalefactor_changed.connect(self.on_canvas_scalefactor_changed) canvas.end_create_rect.connect(self.on_end_create_rect) self.currentTool: DrawToolCheckBox = None self.handTool = DrawToolCheckBox() self.handTool.setObjectName("DrawHandTool") self.handTool.checked.connect(self.on_use_handtool) self.handTool.stateChanged.connect(self.on_handchecker_changed) self.inpaintTool = DrawToolCheckBox() self.inpaintTool.setObjectName("DrawInpaintTool") self.inpaintTool.checked.connect(self.on_use_inpainttool) Loading @@ -176,7 +217,8 @@ class DrawingPanel(Widget): self.rectTool = DrawToolCheckBox() self.rectTool.setObjectName("DrawRectTool") self.rectTool.checked.connect(self.on_use_rectremoval_tool) self.rectTool.checked.connect(self.on_use_rect_tool) self.rectPanel = RectPanel(inpainter_panel) self.penTool = DrawToolCheckBox() self.penTool.setObjectName("DrawPenTool") Loading @@ -201,8 +243,10 @@ class DrawingPanel(Widget): self.setPenToolColor([0, 0, 0, 127]) self.toolConfigStackwidget = QStackedWidget() self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.addWidget(self.inpaintConfigPanel) self.toolConfigStackwidget.addWidget(self.penConfigPanel) self.toolConfigStackwidget.addWidget(self.rectPanel) self.maskTransperancySlider = PaintQSlider(' value%', Qt.Orientation.Horizontal) self.maskTransperancySlider.setFixedHeight(40) Loading Loading @@ -244,16 +288,13 @@ class DrawingPanel(Widget): def on_use_handtool(self) -> None: if self.currentTool is not None and self.currentTool != self.handTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.hide() self.currentTool = self.handTool self.canvas.gv.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) self.canvas.painting = False self.canvas.image_edit_mode = ImageEditMode.HandTool def on_use_inpainttool(self) -> None: if self.currentTool is not None and self.currentTool != self.inpaintTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.show() self.currentTool = self.inpaintTool self.canvas.image_edit_mode = ImageEditMode.InpaintTool self.canvas.painting_pen = self.inpaint_pen Loading @@ -261,12 +302,10 @@ class DrawingPanel(Widget): if self.isVisible(): self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.setInpaintCursor() self.canvas.painting = True def on_use_pentool(self) -> None: if self.currentTool is not None and self.currentTool != self.penTool: self.currentTool.setChecked(False) self.toolConfigStackwidget.show() self.currentTool = self.penTool self.canvas.painting_pen = self.pentool_pen self.canvas.image_edit_mode = ImageEditMode.PenTool Loading @@ -274,10 +313,15 @@ class DrawingPanel(Widget): if self.isVisible(): self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.setPenCursor() self.canvas.painting = True def on_use_rectremoval_tool(self) -> None: print('use rect removal tool') def on_use_rect_tool(self) -> None: if self.currentTool is not None and self.currentTool != self.rectTool: self.currentTool.setChecked(False) self.currentTool = self.rectTool self.toolConfigStackwidget.setCurrentWidget(self.rectPanel) self.canvas.gv.setDragMode(QGraphicsView.DragMode.NoDrag) self.canvas.image_edit_mode = ImageEditMode.RectTool def get_config(self) -> DrawPanelConfig: config = DrawPanelConfig() Loading Loading @@ -408,8 +452,9 @@ class DrawingPanel(Widget): self.inpaint_stroke.addStroke(inpaint_stroke.stroke) self.canvas.removeItem(inpaint_stroke) def runInpaint(self): def runInpaint(self, inpaint_dict=None): if inpaint_dict is None: if self.inpaint_stroke is None: return mask = self.inpaint_stroke.getSubimg(convert_mask=True) Loading @@ -434,9 +479,9 @@ class DrawingPanel(Widget): mask = cv2.copyMakeBorder(mask, top, bottom, left, right, cv2.BORDER_CONSTANT, value=0) inpaint_rect = rect_enlarged img = img[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]] self.canvas.painting = False inpaint_dict = {'img': img, 'mask': mask, 'inpaint_rect': inpaint_rect} self.canvas.image_edit_mode = ImageEditMode.NONE self.dl_manager.canvas_inpaint(inpaint_dict) def on_inpaint_finished(self, inpaint_dict): Loading @@ -444,12 +489,16 @@ class DrawingPanel(Widget): inpaint_rect = inpaint_dict['inpaint_rect'] mask_array = self.canvas.imgtrans_proj.mask_array mask = cv2.bitwise_or(inpaint_dict['mask'], mask_array[inpaint_rect[1]: inpaint_rect[3], inpaint_rect[0]: inpaint_rect[2]]) if self.inpaint_stroke is not None: self.canvas.removeItem(self.inpaint_stroke) self.inpaint_stroke = None self.canvas.undoStack.push(InpaintUndoCommand(self.canvas, inpainted, mask, inpaint_rect)) self.canvas.undoStack.push(InpaintUndoCommand(self.canvas, inpainted, mask, inpaint_rect)) if self.currentTool == self.inpaintTool: self.canvas.painting = True self.canvas.image_edit_mode = ImageEditMode.InpaintTool elif self.currentTool == self.rectTool: self.canvas.image_edit_mode = ImageEditMode.RectTool def on_finish_erasing(self, stroke_item: StrokeItem): Loading Loading @@ -479,7 +528,7 @@ class DrawingPanel(Widget): def on_inpaint_failed(self): if self.currentTool == self.inpaintTool and self.inpaint_stroke is not None: self.canvas.painting = True self.canvas.image_edit_mode = ImageEditMode.InpaintTool self.canvas.removeItem(self.inpaint_stroke) self.inpaint_stroke = None Loading Loading @@ -549,6 +598,40 @@ class DrawingPanel(Widget): def setInpaintCursor(self): self.canvas.gv.setCursor(self.get_pen_cursor(INPAINT_BRUSH_COLOR, self.inpaint_pen.width())) def on_handchecker_changed(self): if self.handTool.isChecked(): self.toolConfigStackwidget.hide() else: self.toolConfigStackwidget.show() def on_end_create_rect(self, rect: QRectF): if self.currentTool == self.rectTool: self.canvas.image_edit_mode = ImageEditMode.NONE img = self.canvas.imgtrans_proj.inpainted_array im_h, im_w = img.shape[:2] xyxy = [rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()] xyxy = np.array(xyxy) / self.canvas.scale_factor xyxy[[0, 2]] = np.clip(xyxy[[0, 2]], 0, im_w - 1) xyxy[[1, 3]] = np.clip(xyxy[[1, 3]], 0, im_h - 1) x1, y1, x2, y2 = xyxy.astype(np.int64) if y2 - y1 < 2 or x2 - x1 < 2: self.canvas.txtblkShapeControl.showControls() self.canvas.txtblkShapeControl.hide() self.canvas.image_edit_mode = ImageEditMode.RectTool return im = img[y1: y2, x1: x2] maskseg_method = self.rectPanel.get_maskseg_method() mask, ballon_mask, bub_dict = maskseg_method(im) inpaint_dict = {'img': im, 'mask': mask, 'inpaint_rect': [x1, y1, x2, y2]} self.runInpaint(inpaint_dict=inpaint_dict) # self.canvas.image_edit_mode = ImageEditMode.RectTool # cv2.imshow('img', im) # cv2.imshow('mask', mask) # cv2.imshow('ballon_mask', ballon_mask) # cv2.waitKey(0) class InpaintUndoCommand(QUndoCommand): def __init__(self, canvas: Canvas, inpainted: np.ndarray, mask: np.ndarray, inpaint_rect: list): Loading Loading @@ -585,3 +668,4 @@ class InpaintUndoCommand(QUndoCommand): mask_view[:] = self.undo_mask self.canvas.setInpaintLayer() self.canvas.setMaskLayer()
ui/image_edit.py +2 −0 Original line number Diff line number Diff line Loading @@ -10,9 +10,11 @@ import cv2 SIZE_MAX = 2147483647 class ImageEditMode: NONE = 0 HandTool = 0 InpaintTool = 1 PenTool = 2 RectTool = 3 class StrokeItem(QGraphicsPathItem): def __init__(self, origin_point: QPointF): Loading
ui/mainwindow.py +5 −2 Original line number Diff line number Diff line Loading @@ -56,12 +56,14 @@ class MainWindow(QMainWindow): if osp.exists(proj_dir): self.openDir(proj_dir) textblock_mode = self.config.imgtrans_textblock self.bottomBar.texteditChecker.click() self.bottomBar.paintChecker.click() if self.config.imgtrans_textedit: if textblock_mode: self.bottomBar.textblockChecker.setChecked(True) self.bottomBar.texteditChecker.click() if self.config.imgtrans_textblock: self.bottomBar.textblockChecker.click() elif not self.config.imgtrans_paintmode: self.bottomBar.paintChecker.click() self.comicTransSplitter.setStretchFactor(2, 0.5) Loading Loading @@ -315,6 +317,7 @@ class MainWindow(QMainWindow): self.rightComicTransStackPanel.setCurrentIndex(1) self.st_manager.setTextEditMode(True) self.bottomBar.originalSlider.setHidden(True) self.setTextBlockMode() else: self.bottomBar.textblockChecker.hide() self.rightComicTransStackPanel.setHidden(True) Loading