Loading ballontranslator/dl/textdetector/textblock.py +11 −3 Original line number Diff line number Diff line Loading @@ -204,7 +204,14 @@ class TextBlock(object): def get_text(self): if isinstance(self.text, str): return self.text return ' '.join(self.text).strip() text = '' for t in self.text: if text and t: if text[-1].isalpha() and t[0].isalpha(): text += ' ' text += t return text.strip() def set_font_colors(self, frgb, srgb, accumulate=True): self.accumulate_color = accumulate Loading Loading @@ -490,14 +497,15 @@ def group_output(blks, lines, im_w, im_h, mask=None, sort_blklist=True) -> List[ continue # blk.line_spacing = blk.bounding_rect()[3] / num_lines / blk.font_size resize_ratio = 1.1 expand_size = max(int(blk.font_size * 0.1), 2) rad = np.deg2rad(blk.angle) shifted_vec = np.array([[[-1, -1],[1, -1],[1, 1],[-1, 1]]]) shifted_vec = shifted_vec * np.array([[[np.sin(rad), np.cos(rad)]]]) * blk.font_size * (resize_ratio - 1) shifted_vec = shifted_vec * np.array([[[np.sin(rad), np.cos(rad)]]]) * expand_size lines = blk.lines_array() + shifted_vec lines[..., 0] = np.clip(lines[..., 0], 0, im_w-1) lines[..., 1] = np.clip(lines[..., 1], 0, im_h-1) blk.lines = lines.astype(np.int64).tolist() blk.font_size = int(resize_ratio * blk.font_size) blk.font_size += expand_size return final_blk_list Loading ballontranslator/ui/mainwindow.py +19 −8 Original line number Diff line number Diff line import os.path as osp import os import os, re from typing import List from qtpy.QtWidgets import QMainWindow, QHBoxLayout, QVBoxLayout, QApplication, QStackedWidget, QWidget, QSplitter, QListWidget, QShortcut, QListWidgetItem from qtpy.QtCore import Qt, QPoint, QSize Loading @@ -8,6 +9,8 @@ from qtpy.QtGui import QGuiApplication, QIcon, QCloseEvent, QKeySequence, QImage from utils.logger import logger as LOGGER from utils.io_utils import json_dump_nested_obj from utils.text_processing import is_cjk, full_len, half_len from dl.textdetector import TextBlock from .misc import ProjImgTrans, ndarray2pixmap, pixmap2ndarray from .canvas import Canvas from .configpanel import ConfigPanel Loading Loading @@ -471,19 +474,26 @@ class MainWindow(QMainWindow): def on_imgtrans_pipeline_finished(self): self.pageListCurrentItemChanged() def on_pagtrans_finished(self, page_index: int): def postprocess_translations(self, blk_list: List[TextBlock]) -> None: src_is_cjk = is_cjk(self.config.dl.translate_source) tgt_is_cjk = is_cjk(self.config.dl.translate_target) if tgt_is_cjk: for blk in self.imgtrans_proj.get_blklist_byidx(page_index): if blk.vertical: blk._alignment = 1 blk.vertical = False for blk in blk_list: if src_is_cjk: blk.translation = full_len(blk.translation) else: blk.translation = half_len(blk.translation) blk.translation = re.sub(r'([?.!"])\s+', r'\1', blk.translation) # remove spaces following punctuations elif src_is_cjk: for blk in blk_list: if blk.vertical: blk._alignment = 1 blk.translation = half_len(blk.translation) blk.vertical = False def on_pagtrans_finished(self, page_index: int): blk_list = self.imgtrans_proj.get_blklist_byidx(page_index) self.postprocess_translations(blk_list) # override font format if necessary override_fnt_size = self.config.let_fntsize_flag == 1 Loading @@ -491,7 +501,7 @@ class MainWindow(QMainWindow): override_fnt_color = self.config.let_fntcolor_flag == 1 override_alignment = self.config.let_alignment_flag == 1 gf = self.textPanel.formatpanel.global_format blk_list = self.imgtrans_proj.get_blklist_byidx(page_index) for blk in blk_list: if override_fnt_size: blk.font_size = gf.size Loading @@ -511,6 +521,7 @@ class MainWindow(QMainWindow): self.imgtrans_proj.set_current_img_byidx(page_index) self.canvas.updateCanvas() self.st_manager.updateSceneTextitems() self.saveCurrentPage(False, False) if page_index + 1 == self.imgtrans_proj.num_pages: self.st_manager.auto_textlayout_flag = False Loading ballontranslator/ui/misc.py +7 −2 Original line number Diff line number Diff line Loading @@ -196,13 +196,18 @@ class ProjImgTrans: self.not_found_pages[imname] = [TextBlock(**blk_dict) for blk_dict in page_dict[imname]] except Exception as e: raise ProjectNotSupportedException(e) set_img_failed = False if 'current_img' in proj_dict: current_img = proj_dict['current_img'] try: self.set_current_img(current_img) except ImgnameNotInProjectException: LOGGER.warning(f'{current_img} not found.') set_img_failed = True else: set_img_failed = True LOGGER.warning(f'{current_img} not found.') if set_img_failed: if len(self.pages) > 0: self.set_current_img_byidx(0) def set_current_img(self, imgname: str): Loading ballontranslator/ui/scenetext_manager.py +6 −3 Original line number Diff line number Diff line Loading @@ -467,6 +467,7 @@ class SceneTextManager(QObject): if self.config.let_uppercase_flag: text = text.upper() words, delimiter = seg_text(text, self.config.dl.translate_target) if len(words) == 0: return Loading Loading @@ -507,8 +508,10 @@ class SceneTextManager(QObject): else: resize_ratio = 1.1 else: if ballon_area / text_area < 1.8: # default eng->cjk font_size = 1.1 * detected_size, because detected eng bboxes are a bit small resize_ratio = 0.9 if ballon_area / text_area < 1.5: # default eng->cjk font_size = 1.1 * detected_size, because detected eng bboxes are a bit small # print(1.8 * text_area / ballon_area) resize_ratio = max(ballon_area / 1.5 / text_area, 0.5) if resize_ratio != 1: new_font_size = blk_font.pointSizeF() * resize_ratio Loading ballontranslator/utils/text_layout.py +33 −13 Original line number Diff line number Diff line Loading @@ -54,11 +54,6 @@ def layout_lines_aligncenter( centroid_x, centroid_y = centroid # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) # m = cv2.moments(mask) mask = 255 - mask # centroid_y = int(m['m01'] / m['m00']) Loading @@ -70,11 +65,11 @@ def layout_lines_aligncenter( wlst_left, wlst_right = [], [] sum_left, sum_right = 0, 0 if num_words > 1: wl_cumsums = np.cumsum(np.array(wl_list, dtype=np.float64)) wl_cumsums -= wl_cumsums[-1] / 2 wl_array = np.array(wl_list, dtype=np.float64) wl_cumsums = np.cumsum(wl_array) wl_cumsums = wl_cumsums - wl_cumsums[-1] / 2 - wl_array / 2 central_index = np.argmin(np.abs(wl_cumsums)) if wl_list[central_index] < 0: central_index += 1 if central_index > 0: wlst_left = words[:central_index] len_left = wl_list[:central_index] Loading Loading @@ -148,7 +143,7 @@ def layout_lines_aligncenter( new_len = line.length + wl + delimiter_len new_x = centroid_x - new_len // 2 right_x = new_x + new_len if new_x <= 0 or right_x >= bw or new_len > max_central_width: if new_x <= 0 or right_x >= bw: line_valid = False elif mask[pos_y: line_bottom, new_x].sum() > 0 or\ mask[pos_y: line_bottom, right_x].sum() > 0: Loading @@ -158,7 +153,16 @@ def layout_lines_aligncenter( if line_valid: line.append_right(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: line_valid = False if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) sum_right -= wl else: line.strip_spacing() break if not line_valid: pos_x = centroid_x - wl // 2 pos_y = line_bottom line_bottom += line_height Loading @@ -181,7 +185,7 @@ def layout_lines_aligncenter( new_len = line.length + wl + delimiter_len new_x = centroid_x - new_len // 2 right_x = new_x + new_len if new_x <= 0 or right_x >= bw or new_len > max_central_width: if new_x <= 0 or right_x >= bw: line_valid = False elif mask[pos_y: line_bottom, new_x].sum() > 0 or\ mask[pos_y: line_bottom, right_x].sum() > 0: Loading @@ -191,7 +195,16 @@ def layout_lines_aligncenter( if line_valid: line.append_left(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: line_valid = False if sum_left > 0: w, wl = wlst_left.pop(-1), len_left.pop(-1) sum_left -= wl else: line.strip_spacing() break if not line_valid : pos_x = centroid_x - wl // 2 pos_y -= line_height line_bottom = pos_y + line_height Loading @@ -199,6 +212,13 @@ def layout_lines_aligncenter( line = Line(w, pos_x, pos_y, wl, spacing) lines.insert(0, line) # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) # for line in lines: # cv2.rectangle(rbgmsk, (line.pos_x, line.pos_y), (line.pos_x + line.length, line.pos_y + line_height), (0, 255, 0)) # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) return lines def layout_lines_alignleft( Loading Loading
ballontranslator/dl/textdetector/textblock.py +11 −3 Original line number Diff line number Diff line Loading @@ -204,7 +204,14 @@ class TextBlock(object): def get_text(self): if isinstance(self.text, str): return self.text return ' '.join(self.text).strip() text = '' for t in self.text: if text and t: if text[-1].isalpha() and t[0].isalpha(): text += ' ' text += t return text.strip() def set_font_colors(self, frgb, srgb, accumulate=True): self.accumulate_color = accumulate Loading Loading @@ -490,14 +497,15 @@ def group_output(blks, lines, im_w, im_h, mask=None, sort_blklist=True) -> List[ continue # blk.line_spacing = blk.bounding_rect()[3] / num_lines / blk.font_size resize_ratio = 1.1 expand_size = max(int(blk.font_size * 0.1), 2) rad = np.deg2rad(blk.angle) shifted_vec = np.array([[[-1, -1],[1, -1],[1, 1],[-1, 1]]]) shifted_vec = shifted_vec * np.array([[[np.sin(rad), np.cos(rad)]]]) * blk.font_size * (resize_ratio - 1) shifted_vec = shifted_vec * np.array([[[np.sin(rad), np.cos(rad)]]]) * expand_size lines = blk.lines_array() + shifted_vec lines[..., 0] = np.clip(lines[..., 0], 0, im_w-1) lines[..., 1] = np.clip(lines[..., 1], 0, im_h-1) blk.lines = lines.astype(np.int64).tolist() blk.font_size = int(resize_ratio * blk.font_size) blk.font_size += expand_size return final_blk_list Loading
ballontranslator/ui/mainwindow.py +19 −8 Original line number Diff line number Diff line import os.path as osp import os import os, re from typing import List from qtpy.QtWidgets import QMainWindow, QHBoxLayout, QVBoxLayout, QApplication, QStackedWidget, QWidget, QSplitter, QListWidget, QShortcut, QListWidgetItem from qtpy.QtCore import Qt, QPoint, QSize Loading @@ -8,6 +9,8 @@ from qtpy.QtGui import QGuiApplication, QIcon, QCloseEvent, QKeySequence, QImage from utils.logger import logger as LOGGER from utils.io_utils import json_dump_nested_obj from utils.text_processing import is_cjk, full_len, half_len from dl.textdetector import TextBlock from .misc import ProjImgTrans, ndarray2pixmap, pixmap2ndarray from .canvas import Canvas from .configpanel import ConfigPanel Loading Loading @@ -471,19 +474,26 @@ class MainWindow(QMainWindow): def on_imgtrans_pipeline_finished(self): self.pageListCurrentItemChanged() def on_pagtrans_finished(self, page_index: int): def postprocess_translations(self, blk_list: List[TextBlock]) -> None: src_is_cjk = is_cjk(self.config.dl.translate_source) tgt_is_cjk = is_cjk(self.config.dl.translate_target) if tgt_is_cjk: for blk in self.imgtrans_proj.get_blklist_byidx(page_index): if blk.vertical: blk._alignment = 1 blk.vertical = False for blk in blk_list: if src_is_cjk: blk.translation = full_len(blk.translation) else: blk.translation = half_len(blk.translation) blk.translation = re.sub(r'([?.!"])\s+', r'\1', blk.translation) # remove spaces following punctuations elif src_is_cjk: for blk in blk_list: if blk.vertical: blk._alignment = 1 blk.translation = half_len(blk.translation) blk.vertical = False def on_pagtrans_finished(self, page_index: int): blk_list = self.imgtrans_proj.get_blklist_byidx(page_index) self.postprocess_translations(blk_list) # override font format if necessary override_fnt_size = self.config.let_fntsize_flag == 1 Loading @@ -491,7 +501,7 @@ class MainWindow(QMainWindow): override_fnt_color = self.config.let_fntcolor_flag == 1 override_alignment = self.config.let_alignment_flag == 1 gf = self.textPanel.formatpanel.global_format blk_list = self.imgtrans_proj.get_blklist_byidx(page_index) for blk in blk_list: if override_fnt_size: blk.font_size = gf.size Loading @@ -511,6 +521,7 @@ class MainWindow(QMainWindow): self.imgtrans_proj.set_current_img_byidx(page_index) self.canvas.updateCanvas() self.st_manager.updateSceneTextitems() self.saveCurrentPage(False, False) if page_index + 1 == self.imgtrans_proj.num_pages: self.st_manager.auto_textlayout_flag = False Loading
ballontranslator/ui/misc.py +7 −2 Original line number Diff line number Diff line Loading @@ -196,13 +196,18 @@ class ProjImgTrans: self.not_found_pages[imname] = [TextBlock(**blk_dict) for blk_dict in page_dict[imname]] except Exception as e: raise ProjectNotSupportedException(e) set_img_failed = False if 'current_img' in proj_dict: current_img = proj_dict['current_img'] try: self.set_current_img(current_img) except ImgnameNotInProjectException: LOGGER.warning(f'{current_img} not found.') set_img_failed = True else: set_img_failed = True LOGGER.warning(f'{current_img} not found.') if set_img_failed: if len(self.pages) > 0: self.set_current_img_byidx(0) def set_current_img(self, imgname: str): Loading
ballontranslator/ui/scenetext_manager.py +6 −3 Original line number Diff line number Diff line Loading @@ -467,6 +467,7 @@ class SceneTextManager(QObject): if self.config.let_uppercase_flag: text = text.upper() words, delimiter = seg_text(text, self.config.dl.translate_target) if len(words) == 0: return Loading Loading @@ -507,8 +508,10 @@ class SceneTextManager(QObject): else: resize_ratio = 1.1 else: if ballon_area / text_area < 1.8: # default eng->cjk font_size = 1.1 * detected_size, because detected eng bboxes are a bit small resize_ratio = 0.9 if ballon_area / text_area < 1.5: # default eng->cjk font_size = 1.1 * detected_size, because detected eng bboxes are a bit small # print(1.8 * text_area / ballon_area) resize_ratio = max(ballon_area / 1.5 / text_area, 0.5) if resize_ratio != 1: new_font_size = blk_font.pointSizeF() * resize_ratio Loading
ballontranslator/utils/text_layout.py +33 −13 Original line number Diff line number Diff line Loading @@ -54,11 +54,6 @@ def layout_lines_aligncenter( centroid_x, centroid_y = centroid # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) # m = cv2.moments(mask) mask = 255 - mask # centroid_y = int(m['m01'] / m['m00']) Loading @@ -70,11 +65,11 @@ def layout_lines_aligncenter( wlst_left, wlst_right = [], [] sum_left, sum_right = 0, 0 if num_words > 1: wl_cumsums = np.cumsum(np.array(wl_list, dtype=np.float64)) wl_cumsums -= wl_cumsums[-1] / 2 wl_array = np.array(wl_list, dtype=np.float64) wl_cumsums = np.cumsum(wl_array) wl_cumsums = wl_cumsums - wl_cumsums[-1] / 2 - wl_array / 2 central_index = np.argmin(np.abs(wl_cumsums)) if wl_list[central_index] < 0: central_index += 1 if central_index > 0: wlst_left = words[:central_index] len_left = wl_list[:central_index] Loading Loading @@ -148,7 +143,7 @@ def layout_lines_aligncenter( new_len = line.length + wl + delimiter_len new_x = centroid_x - new_len // 2 right_x = new_x + new_len if new_x <= 0 or right_x >= bw or new_len > max_central_width: if new_x <= 0 or right_x >= bw: line_valid = False elif mask[pos_y: line_bottom, new_x].sum() > 0 or\ mask[pos_y: line_bottom, right_x].sum() > 0: Loading @@ -158,7 +153,16 @@ def layout_lines_aligncenter( if line_valid: line.append_right(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: line_valid = False if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) sum_right -= wl else: line.strip_spacing() break if not line_valid: pos_x = centroid_x - wl // 2 pos_y = line_bottom line_bottom += line_height Loading @@ -181,7 +185,7 @@ def layout_lines_aligncenter( new_len = line.length + wl + delimiter_len new_x = centroid_x - new_len // 2 right_x = new_x + new_len if new_x <= 0 or right_x >= bw or new_len > max_central_width: if new_x <= 0 or right_x >= bw: line_valid = False elif mask[pos_y: line_bottom, new_x].sum() > 0 or\ mask[pos_y: line_bottom, right_x].sum() > 0: Loading @@ -191,7 +195,16 @@ def layout_lines_aligncenter( if line_valid: line.append_left(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: line_valid = False if sum_left > 0: w, wl = wlst_left.pop(-1), len_left.pop(-1) sum_left -= wl else: line.strip_spacing() break if not line_valid : pos_x = centroid_x - wl // 2 pos_y -= line_height line_bottom = pos_y + line_height Loading @@ -199,6 +212,13 @@ def layout_lines_aligncenter( line = Line(w, pos_x, pos_y, wl, spacing) lines.insert(0, line) # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) # for line in lines: # cv2.rectangle(rbgmsk, (line.pos_x, line.pos_y), (line.pos_x + line.length, line.pos_y + line_height), (0, 255, 0)) # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) return lines def layout_lines_alignleft( Loading