Commit 32c0facb authored by dmMaze's avatar dmMaze
Browse files

update rect tool & readme

parent b9e56743
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -42,11 +42,23 @@


## 画板

## 修复画笔
<img src="doc/src/imgedit_inpaint.gif">
<p align = "center">
暂时就一个修复画笔
修复画笔
</p>

### 矩形工具
<img src="doc/src/rect_tool.gif">
<p align = "center">
矩形工具
</p>

按下鼠标左键拖动矩形框抹除框内文字, 按下右键拉框清除框内修复结果.  
抹除结果取决于算法(gif中的"方法1"和"方法2")对文字区域估算的准确程度, 一般拉的框最好稍大于需要抹除的文本块. 两种方法都比较玄学, 能够应付绝大多数简单文字简单背景, 部分复杂背景简单文字/简单背景复杂文字, 少数复杂背景复杂文字, 可以多拉几次试试.  
勾选"自动"拉完框立即修复, 否则需要按下"修复"或者空格键才进行修复, 或"Ctrl+D"删除矩形选框.  

## 文本编辑
<img src="doc/src/textedit.gif">

@@ -58,10 +70,12 @@
## 界面说明及快捷键
* Ctrl+Z, Ctrl+Y可以撤销重做大部分操作,注意翻页后撤消重做栈会清空
* A/D翻页, 如果当前页面未保存会自动保存
* 文本编辑模式下(底部最右"T"图标), W激活文本块创建模式后在画布右键拉文本框
* 画板模式右下角滑条改原图透明度
* "T"切换到文本编辑模式下(底部最右"T"图标), W激活文本块创建模式后在画布右键拉文本框
* "P"切换到画板模式, 右下角滑条改原图透明度
* 底部左侧"OCR"和"A"按钮控制启用/禁用OCR翻译功能, 禁用后再Run程序就只做文本检测和抹字  
* 设置面板配置各自动化模块参数
* Ctrl++/-或滚轮缩放画布

<img src="doc/src/configpanel.png">  

## 自动化模块
@@ -94,6 +108,5 @@
* 如果电脑带N卡, 程序默认对所有模型启用GPU加速, 默认配置下显存占用在6G左右. 4G显存调小修复器inpaint_size即可. 

# TODO
- 优化CPU模式下的速度, 主要是输入从整张图改成区块,并在修复前判定是否需要调用开销较大的修复方法
- 支持更多语言的OCR模型
- ...
+14 −1
Original line number Diff line number Diff line
@@ -43,11 +43,22 @@ preview


## Image editing

### inpaint tool
<img src="doc/src/imgedit_inpaint.gif">
<p align = "center">
Image editing mode, inpainting tool
</p>

### rect tool
<img src="doc/src/rect_tool.gif">
<p align = "center">
rect tool
</p>

Drag the rectangle with left button pressed to erase the text inside the box, press right button and drag to clear inpainted result.  
The result depends on how accurately the algorithm ("method 1" and "method 2" in the gif) extracts the text mask. It could perform worse on complex text & background.  

## Text editing
<img src="doc/src/textedit.gif">
<p align = "center">
@@ -57,10 +68,12 @@ Text editing mode
## Shortcuts
* A/D to turn the page
* Ctrl+Z, Ctrl+Y to undo/redo most operations, note the undo stack will be cleared after you turn the page.
* Click the "T" button on the bottom toolbar to enter/leave text-editing mode, press W to activate text block creating mode, then drag the mouse on the canvas with the right button clicked to add a new text block. (see the text editing gif)
* T to text-editting mode, (or the "T" button on the bottom toolbar) press W to activate text block creating mode, then drag the mouse on the canvas with the right button clicked to add a new text block. (see the text editing gif)
* P to image-editting mode.  
* In the image editing mode, use the slider on the right bottom to control the original image transparency.
* The "OCR" and "A" button in the bottom toolbar controls whether to enable OCR and translation, if you disable them, the program will only do the text detection and removal.  
* Set parameters of automatic modules in the config panel.  
* Ctrl++/ to resize image
  
<img src="doc/src/configpanel.png">  

doc/src/rect_tool.gif

0 → 100644
+2.55 MiB
Loading image diff...
+8 −7
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ class Canvas(QGraphicsScene):

    scalefactor_changed = pyqtSignal()
    end_create_textblock = pyqtSignal(QRectF)
    end_create_rect = pyqtSignal(QRectF)
    end_create_rect = pyqtSignal(QRectF, int)
    delete_textblks = pyqtSignal()
    finish_painting = pyqtSignal(StrokeItem)
    finish_erasing = pyqtSignal(StrokeItem)
@@ -253,12 +253,12 @@ class Canvas(QGraphicsScene):
            self.txtblkShapeControl.hideControls()
        self.txtblkShapeControl.show()

    def endCreateTextblock(self):
    def endCreateTextblock(self, btn=0):
        self.creating_textblock = False
        self.gv.setCursor(Qt.ArrowCursor)
        self.txtblkShapeControl.hide()
        if self.creating_normal_rect:
            self.end_create_rect.emit(self.txtblkShapeControl.rect())
            self.end_create_rect.emit(self.txtblkShapeControl.rect(), btn)
            self.txtblkShapeControl.showControls()
        else:
            self.end_create_textblock.emit(self.txtblkShapeControl.rect())
@@ -289,6 +289,8 @@ class Canvas(QGraphicsScene):
            if event.button() == Qt.RightButton:
                if self.hovering_textblkitem is None:
                    return self.startCreateTextblock(event.scenePos())
        elif self.creating_normal_rect:
            return self.startCreateTextblock(event.scenePos(), hide_control=True)
        elif event.button() == Qt.MouseButton.LeftButton:
            if self.alt_pressed:
                self.scale_tool_mode = True
@@ -296,8 +298,6 @@ 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:
@@ -312,7 +312,8 @@ class Canvas(QGraphicsScene):

    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
        if self.creating_textblock:
            return self.endCreateTextblock()
            btn = 0 if event.button() == Qt.MouseButton.LeftButton else 1
            return self.endCreateTextblock(btn=btn)
        elif event.button() == Qt.RightButton:
            if self.stroke_path_item is not None:
                self.finish_erasing.emit(self.stroke_path_item)
+30 −20
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import cv2

from utils.imgproc_utils import enlarge_window
from utils.textblock_mask import canny_flood, connected_canny_flood
from utils.logger import logger

from .dl_manager import DLManager
from .image_edit import ImageEditMode, StrokeItem, PixmapItem
@@ -499,6 +500,10 @@ class DrawingPanel(Widget):
        if inpaint_dict is None:
            if self.inpaint_stroke is None:
                return
            elif self.inpaint_stroke.parentItem() is None:
                logger.warning("sth goes wrong")
                self.canvas.removeItem(self.inpaint_stroke)
                return
            mask = self.inpaint_stroke.getSubimg(convert_mask=True)
            pos = self.inpaint_stroke.subBlockPos()
            if mask is None:
@@ -648,7 +653,7 @@ class DrawingPanel(Widget):
        else:
            self.toolConfigStackwidget.show()

    def on_end_create_rect(self, rect: QRectF):
    def on_end_create_rect(self, rect: QRectF, mode: int):
        if self.currentTool == self.rectTool:
            self.canvas.image_edit_mode = ImageEditMode.NONE
            img = self.canvas.imgtrans_proj.inpainted_array
@@ -662,7 +667,7 @@ class DrawingPanel(Widget):
            if y2 - y1 < 2 or x2 - x1 < 2:
                self.canvas.image_edit_mode = ImageEditMode.RectTool
                return

            if mode == 0:
                im = np.copy(img[y1: y2, x1: x2])
                maskseg_method = self.rectPanel.get_maskseg_method()
                mask, ballon_mask, bub_dict = maskseg_method(im)
@@ -682,6 +687,11 @@ class DrawingPanel(Widget):
                    self.inpaintRect(inpaint_dict)
                else:
                    self.rect_inpaint_dict = inpaint_dict
            else:
                mask = np.zeros((y2 - y1, x2 - x1), dtype=np.uint8)
                erased = self.canvas.imgtrans_proj.img_array[y1: y2, x1: x2]
                self.canvas.undoStack.push(InpaintUndoCommand(self.canvas, erased, mask, [x1, y1, x2, y2]))
                self.canvas.image_edit_mode = ImageEditMode.RectTool
            self.setCrossCursor()

    def inpaintRect(self, inpaint_dict):
Loading