Loading ballontranslator/dl/textdetector/textblock.py +4 −5 Original line number Diff line number Diff line Loading @@ -3,9 +3,10 @@ import numpy as np from shapely.geometry import Polygon import math import copy from utils.imgproc_utils import union_area, xywh2xyxypoly, rotate_polygons import cv2 from utils.imgproc_utils import union_area, xywh2xyxypoly, rotate_polygons, color_difference LANG_LIST = ['eng', 'ja', 'unknown'] LANGCLS2IDX = {'eng': 0, 'ja': 1, 'unknown': 2} Loading Loading @@ -259,10 +260,8 @@ class TextBlock(object): @property def stroke_width(self): var = np.array([self.fg_r, self.fg_g, self.fg_b]) \ - np.array([self.bg_r, self.bg_g, self.bg_b]) var = np.abs(var).sum() if var > 40: diff = color_difference(*self.get_font_colors()) if diff > 20: return self.default_stroke_width return 0 Loading ballontranslator/ui/canvas.py +4 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ class Canvas(QGraphicsScene): finish_erasing = Signal(StrokeItem) delete_textblks = Signal() format_textblks = Signal() layout_textblks = Signal() begin_scale_tool = Signal(QPointF) scale_tool = Signal(QPointF) Loading Loading @@ -401,11 +402,14 @@ class Canvas(QGraphicsScene): menu = QMenu() delete_act = menu.addAction(self.tr("Delete")) format_act = menu.addAction(self.tr("Apply font formatting")) layout_act = menu.addAction(self.tr("Auto layout")) rst = menu.exec_(event.screenPos()) if rst == delete_act: self.delete_textblks.emit() elif rst == format_act: self.format_textblks.emit() elif rst == layout_act: self.layout_textblks.emit() def on_hide_canvas(self): self.alt_pressed = False Loading ballontranslator/ui/mainwindow.py +3 −1 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class MainWindow(QMainWindow): self.drawingPanel.set_config(self.config.drawpanel) self.drawingPanel.initDLModule(dl_manager) self.st_manager.dl_config = self.dl_manager.dl_config if self.config.open_recent_on_startup: self.configPanel.open_on_startup_checker.setChecked(True) Loading Loading @@ -236,7 +238,7 @@ class MainWindow(QMainWindow): self.config.drawpanel = self.drawingPanel.get_config() config_dict = self.config.to_dict() with open(CONFIG_PATH, 'w', encoding='utf8') as f: f.write(json.dumps(config_dict, ensure_ascii=False, indent=4, separators=(',', ':'))) f.write(json.dumps(config_dict, ensure_ascii=False)) if not self.imgtrans_proj.is_empty: self.imgtrans_proj.save() return super().closeEvent(event) Loading ballontranslator/ui/misc.py +1 −1 Original line number Diff line number Diff line Loading @@ -235,7 +235,7 @@ class ProjImgTrans: if not osp.exists(self.directory): raise ProjectDirNotExistException with open(self.proj_path, "w", encoding="utf-8") as f: f.write(json.dumps(self.to_dict(), ensure_ascii=False, indent=4, separators=(',', ':'), cls=TextBlkEncoder)) f.write(json.dumps(self.to_dict(), ensure_ascii=False, cls=TextBlkEncoder)) # if save_mask and self.mask_valid: # self.save_mask(self.current_img, self.mask_array) # if save_inpainted and self.inpainted_valid: Loading ballontranslator/ui/scenetext_manager.py +73 −10 Original line number Diff line number Diff line from typing import List, Union import numpy as np import time from qtpy.QtWidgets import QApplication from qtpy.QtCore import QObject, QRectF, Qt from qtpy.QtGui import QTextCursor from qtpy.QtGui import QTextCursor, QFontMetrics, QFont try: from qtpy.QtWidgets import QUndoCommand except: Loading @@ -15,8 +15,10 @@ from .imgtranspanel import TransPairWidget from .textitem import TextBlkItem, TextBlock, xywh2xyxypoly from .canvas import Canvas from .imgtranspanel import TextPanel, TransTextEdit from .misc import FontFormat from .misc import FontFormat, DLModuleConfig, pt2px from utils.imgproc_utils import extract_ballon_region from utils.text_layout import layout_text class MoveBlkItemsCommand(QUndoCommand): def __init__(self, items: List[TextBlkItem], parent=None): Loading @@ -25,6 +27,14 @@ class MoveBlkItemsCommand(QUndoCommand): self.old_pos_lst = [] self.new_pos_lst = [] for item in items: # color1 = np.array([item.blk.bg_r, item.blk.bg_g, item.blk.bg_b], dtype=np.uint8).reshape(1, 1, 3) # color2 = np.array([item.blk.fg_r, item.blk.fg_g, item.blk.fg_b], dtype=np.uint8).reshape(1, 1, 3) # import cv2 # diff = cv2.cvtColor(color1, cv2.COLOR_RGB2LAB).astype(np.float64) - cv2.cvtColor(color2, cv2.COLOR_RGB2LAB).astype(np.float64) # diff[..., 0] *= 0.392 # diff = np.linalg.norm(diff, axis=2) # print(diff, color1, color2) self.old_pos_lst.append(item.oldPos) self.new_pos_lst.append(item.pos()) item.oldPos = item.pos() Loading Loading @@ -198,6 +208,7 @@ class SceneTextManager(QObject): self.canvas.end_create_textblock.connect(self.onEndCreateTextBlock) self.canvas.delete_textblks.connect(self.onDeleteBlkItems) self.canvas.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) self.canvasUndoStack = self.canvas.undoStack self.txtblkShapeControl = canvas.txtblkShapeControl self.textpanel = textpanel Loading @@ -215,6 +226,8 @@ class SceneTextManager(QObject): self.prev_blkitem: TextBlkItem = None self.dl_config: DLModuleConfig = None def setTextEditMode(self, edit: bool = False): self.editing = edit if edit: Loading Loading @@ -405,6 +418,62 @@ class SceneTextManager(QObject): def onFormatTextblks(self): self.apply_fontformat(self.formatpanel.global_format) def onAutoLayoutTextblks(self): selected_blks = self.get_selected_blkitems() for blkitem in selected_blks: self.layout_textblk(blkitem) def layout_textblk(self, blkitem: TextBlkItem, mask: np.ndarray = None, bounding_rect: List = None): def get_text_size(fm: QFontMetrics, text: str): brt = fm.tightBoundingRect(text) return brt.width(), brt.height() img = self.imgtrans_proj.img_array if img is None: return font_metrics = QFontMetrics(blkitem.font()) text_size_func = lambda text: get_text_size(font_metrics, text) text = blkitem.toPlainText().upper() if bounding_rect is None: bounding_rect = blkitem.absBoundingRect() fmt = blkitem.get_fontformat() padding = int(pt2px(blkitem.font().pointSize()) / 14) # dummpy padding variable new_text, xywh = layout_text(text, self.dl_config.translate_target, blkitem.blk.angle, fmt.line_spacing, fmt.alignment, fmt.vertical, text_size_func, padding, mask, img, bounding_rect) char_fmts = blkitem.get_char_fmts() blkitem.setPlainText('') blkitem.setRect(xywh) blkitem.setPlainText(new_text) # restore char formats cursor = blkitem.textCursor() cpos = 0 num_text = len(new_text) num_fmt = len(char_fmts) for fmt_i in range(num_fmt): fmt = char_fmts[fmt_i] ori_char = text[fmt_i].strip() if ori_char == '': continue else: if cursor.atEnd(): break matched = False while cpos < num_text: if new_text[cpos] == ori_char: matched = True break cpos += 1 if matched: cursor.clearSelection() cursor.setPosition(cpos) cursor.setPosition(cpos+1, QTextCursor.KeepAnchor) cursor.setCharFormat(fmt) cpos += 1 def onEndCreateTextBlock(self, rect: QRectF): scale_f = self.canvas.scale_factor if rect.width() > 1 and rect.height() > 1: Loading Loading @@ -471,13 +540,7 @@ class SceneTextManager(QObject): blk_item.blk.rich_text = '' blk_item.blk.translation = '' blk_item.blk.text = [trans_pair.e_source.toPlainText()] br = blk_item.boundingRect() w, h = br.width(), br.height() sc = blk_item.sceneBoundingRect().center() x = sc.x() / blk_item.scale() - w / 2 y = sc.y() / blk_item.scale() - h / 2 xywh = [x, y, w, h] blk_item.blk._bounding_rect = xywh blk_item.blk._bounding_rect = blk_item.absBoundingRect() blk_item.updateBlkFormat() cbl.append(blk_item.blk) Loading Loading
ballontranslator/dl/textdetector/textblock.py +4 −5 Original line number Diff line number Diff line Loading @@ -3,9 +3,10 @@ import numpy as np from shapely.geometry import Polygon import math import copy from utils.imgproc_utils import union_area, xywh2xyxypoly, rotate_polygons import cv2 from utils.imgproc_utils import union_area, xywh2xyxypoly, rotate_polygons, color_difference LANG_LIST = ['eng', 'ja', 'unknown'] LANGCLS2IDX = {'eng': 0, 'ja': 1, 'unknown': 2} Loading Loading @@ -259,10 +260,8 @@ class TextBlock(object): @property def stroke_width(self): var = np.array([self.fg_r, self.fg_g, self.fg_b]) \ - np.array([self.bg_r, self.bg_g, self.bg_b]) var = np.abs(var).sum() if var > 40: diff = color_difference(*self.get_font_colors()) if diff > 20: return self.default_stroke_width return 0 Loading
ballontranslator/ui/canvas.py +4 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ class Canvas(QGraphicsScene): finish_erasing = Signal(StrokeItem) delete_textblks = Signal() format_textblks = Signal() layout_textblks = Signal() begin_scale_tool = Signal(QPointF) scale_tool = Signal(QPointF) Loading Loading @@ -401,11 +402,14 @@ class Canvas(QGraphicsScene): menu = QMenu() delete_act = menu.addAction(self.tr("Delete")) format_act = menu.addAction(self.tr("Apply font formatting")) layout_act = menu.addAction(self.tr("Auto layout")) rst = menu.exec_(event.screenPos()) if rst == delete_act: self.delete_textblks.emit() elif rst == format_act: self.format_textblks.emit() elif rst == layout_act: self.layout_textblks.emit() def on_hide_canvas(self): self.alt_pressed = False Loading
ballontranslator/ui/mainwindow.py +3 −1 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class MainWindow(QMainWindow): self.drawingPanel.set_config(self.config.drawpanel) self.drawingPanel.initDLModule(dl_manager) self.st_manager.dl_config = self.dl_manager.dl_config if self.config.open_recent_on_startup: self.configPanel.open_on_startup_checker.setChecked(True) Loading Loading @@ -236,7 +238,7 @@ class MainWindow(QMainWindow): self.config.drawpanel = self.drawingPanel.get_config() config_dict = self.config.to_dict() with open(CONFIG_PATH, 'w', encoding='utf8') as f: f.write(json.dumps(config_dict, ensure_ascii=False, indent=4, separators=(',', ':'))) f.write(json.dumps(config_dict, ensure_ascii=False)) if not self.imgtrans_proj.is_empty: self.imgtrans_proj.save() return super().closeEvent(event) Loading
ballontranslator/ui/misc.py +1 −1 Original line number Diff line number Diff line Loading @@ -235,7 +235,7 @@ class ProjImgTrans: if not osp.exists(self.directory): raise ProjectDirNotExistException with open(self.proj_path, "w", encoding="utf-8") as f: f.write(json.dumps(self.to_dict(), ensure_ascii=False, indent=4, separators=(',', ':'), cls=TextBlkEncoder)) f.write(json.dumps(self.to_dict(), ensure_ascii=False, cls=TextBlkEncoder)) # if save_mask and self.mask_valid: # self.save_mask(self.current_img, self.mask_array) # if save_inpainted and self.inpainted_valid: Loading
ballontranslator/ui/scenetext_manager.py +73 −10 Original line number Diff line number Diff line from typing import List, Union import numpy as np import time from qtpy.QtWidgets import QApplication from qtpy.QtCore import QObject, QRectF, Qt from qtpy.QtGui import QTextCursor from qtpy.QtGui import QTextCursor, QFontMetrics, QFont try: from qtpy.QtWidgets import QUndoCommand except: Loading @@ -15,8 +15,10 @@ from .imgtranspanel import TransPairWidget from .textitem import TextBlkItem, TextBlock, xywh2xyxypoly from .canvas import Canvas from .imgtranspanel import TextPanel, TransTextEdit from .misc import FontFormat from .misc import FontFormat, DLModuleConfig, pt2px from utils.imgproc_utils import extract_ballon_region from utils.text_layout import layout_text class MoveBlkItemsCommand(QUndoCommand): def __init__(self, items: List[TextBlkItem], parent=None): Loading @@ -25,6 +27,14 @@ class MoveBlkItemsCommand(QUndoCommand): self.old_pos_lst = [] self.new_pos_lst = [] for item in items: # color1 = np.array([item.blk.bg_r, item.blk.bg_g, item.blk.bg_b], dtype=np.uint8).reshape(1, 1, 3) # color2 = np.array([item.blk.fg_r, item.blk.fg_g, item.blk.fg_b], dtype=np.uint8).reshape(1, 1, 3) # import cv2 # diff = cv2.cvtColor(color1, cv2.COLOR_RGB2LAB).astype(np.float64) - cv2.cvtColor(color2, cv2.COLOR_RGB2LAB).astype(np.float64) # diff[..., 0] *= 0.392 # diff = np.linalg.norm(diff, axis=2) # print(diff, color1, color2) self.old_pos_lst.append(item.oldPos) self.new_pos_lst.append(item.pos()) item.oldPos = item.pos() Loading Loading @@ -198,6 +208,7 @@ class SceneTextManager(QObject): self.canvas.end_create_textblock.connect(self.onEndCreateTextBlock) self.canvas.delete_textblks.connect(self.onDeleteBlkItems) self.canvas.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) self.canvasUndoStack = self.canvas.undoStack self.txtblkShapeControl = canvas.txtblkShapeControl self.textpanel = textpanel Loading @@ -215,6 +226,8 @@ class SceneTextManager(QObject): self.prev_blkitem: TextBlkItem = None self.dl_config: DLModuleConfig = None def setTextEditMode(self, edit: bool = False): self.editing = edit if edit: Loading Loading @@ -405,6 +418,62 @@ class SceneTextManager(QObject): def onFormatTextblks(self): self.apply_fontformat(self.formatpanel.global_format) def onAutoLayoutTextblks(self): selected_blks = self.get_selected_blkitems() for blkitem in selected_blks: self.layout_textblk(blkitem) def layout_textblk(self, blkitem: TextBlkItem, mask: np.ndarray = None, bounding_rect: List = None): def get_text_size(fm: QFontMetrics, text: str): brt = fm.tightBoundingRect(text) return brt.width(), brt.height() img = self.imgtrans_proj.img_array if img is None: return font_metrics = QFontMetrics(blkitem.font()) text_size_func = lambda text: get_text_size(font_metrics, text) text = blkitem.toPlainText().upper() if bounding_rect is None: bounding_rect = blkitem.absBoundingRect() fmt = blkitem.get_fontformat() padding = int(pt2px(blkitem.font().pointSize()) / 14) # dummpy padding variable new_text, xywh = layout_text(text, self.dl_config.translate_target, blkitem.blk.angle, fmt.line_spacing, fmt.alignment, fmt.vertical, text_size_func, padding, mask, img, bounding_rect) char_fmts = blkitem.get_char_fmts() blkitem.setPlainText('') blkitem.setRect(xywh) blkitem.setPlainText(new_text) # restore char formats cursor = blkitem.textCursor() cpos = 0 num_text = len(new_text) num_fmt = len(char_fmts) for fmt_i in range(num_fmt): fmt = char_fmts[fmt_i] ori_char = text[fmt_i].strip() if ori_char == '': continue else: if cursor.atEnd(): break matched = False while cpos < num_text: if new_text[cpos] == ori_char: matched = True break cpos += 1 if matched: cursor.clearSelection() cursor.setPosition(cpos) cursor.setPosition(cpos+1, QTextCursor.KeepAnchor) cursor.setCharFormat(fmt) cpos += 1 def onEndCreateTextBlock(self, rect: QRectF): scale_f = self.canvas.scale_factor if rect.width() > 1 and rect.height() > 1: Loading Loading @@ -471,13 +540,7 @@ class SceneTextManager(QObject): blk_item.blk.rich_text = '' blk_item.blk.translation = '' blk_item.blk.text = [trans_pair.e_source.toPlainText()] br = blk_item.boundingRect() w, h = br.width(), br.height() sc = blk_item.sceneBoundingRect().center() x = sc.x() / blk_item.scale() - w / 2 y = sc.y() / blk_item.scale() - h / 2 xywh = [x, y, w, h] blk_item.blk._bounding_rect = xywh blk_item.blk._bounding_rect = blk_item.absBoundingRect() blk_item.updateBlkFormat() cbl.append(blk_item.blk) Loading