Loading ui/module_parse_widgets.py +0 −4 Original line number Diff line number Diff line Loading @@ -6,10 +6,6 @@ from utils.logger import logger as LOGGER from .custom_widget import ConfigComboBox, ParamComboBox, NoBorderPushBtn from utils.shared import CONFIG_FONTSIZE_CONTENT, CONFIG_COMBOBOX_MIDEAN, CONFIG_COMBOBOX_LONG, CONFIG_COMBOBOX_SHORT, CONFIG_COMBOBOX_HEIGHT from utils.config import pcfg import logging # Настройка логгера logging.basicConfig(level=logging.DEBUG) from qtpy.QtWidgets import QPlainTextEdit, QHBoxLayout, QVBoxLayout, QWidget, QLabel, QCheckBox, QLineEdit, QGridLayout, QPushButton from qtpy.QtCore import Qt, Signal Loading ui/scenetext_manager.py +23 −10 Original line number Diff line number Diff line Loading @@ -693,7 +693,7 @@ class SceneTextManager(QObject): def onAutoLayoutTextblks(self): selected_blks = self.canvas.selected_text_items() old_html_lst, old_rect_lst, trans_widget_lst = [], [], [] selected_blks = [blk for blk in selected_blks if not blk.is_vertical] selected_blks = [blk for blk in selected_blks if not blk.fontformat.vertical] if len(selected_blks) > 0: for blkitem in selected_blks: old_html_lst.append(blkitem.toHtml()) Loading Loading @@ -768,8 +768,6 @@ class SceneTextManager(QObject): region_x, region_y, region_w, region_h = region_rect words, delimiter = seg_text(text, pcfg.module.translate_target) if len(words) == 0: return wl_list = get_words_length_list(QFontMetrics(blk_font), words) text_w, text_h = text_size_func(text) Loading @@ -796,7 +794,7 @@ class SceneTextManager(QObject): resize_ratio = np.clip(min(area_ratio / ballon_area_thresh, region_rect [2] / max(wl_list)), downscale_constraint, 1.0) max_central_width = np.inf if tgt_is_cjk and not src_is_cjk: if not src_is_cjk: if ballon_area / text_area > 2: if blkitem.blk.text: _, _, brw, brh = blkitem.blk.bounding_rect() Loading Loading @@ -844,7 +842,22 @@ class SceneTextManager(QObject): centroid[0] = int(abs_centroid[0] - mask_xyxy[0]) centroid[1] = int(abs_centroid[1] - mask_xyxy[1]) new_text, xywh = layout_text(mask, mask_xyxy, centroid, words, wl_list, delimiter, delimiter_len, blkitem.blk.angle, line_height, fmt.alignment, fmt.vertical, 0, padding, max_central_width) new_text, xywh, start_from_top, adjust_xy = layout_text( blkitem.blk, mask, mask_xyxy, centroid, words, wl_list, delimiter, delimiter_len, line_height, 0, padding, max_central_width, src_is_cjk=src_is_cjk, tgt_is_cjk=tgt_is_cjk ) # font size post adjustment post_resize_ratio = 1 Loading @@ -868,13 +881,10 @@ class SceneTextManager(QObject): blkitem.textCursor().clearSelection() blkitem.setFontSize(new_font_size) scale = blkitem.scale() if scale != 1 and not fmt.alignment == 0: xywh = (np.array(xywh, np.float64) * scale).astype(np.int32).tolist() if restore_charfmts: char_fmts = blkitem.get_char_fmts() pos_before = blkitem.pos() blkitem.set_size(xywh[2], xywh[3], set_layout_maxsize=True) blkitem.setPlainText(new_text) if len(self.pairwidget_list) > blkitem.idx: Loading @@ -882,6 +892,9 @@ class SceneTextManager(QObject): if restore_charfmts: self.restore_charfmts(blkitem, text, new_text, char_fmts) blkitem.squeezeBoundingRect() if start_from_top: blkitem.setPos(blkitem.pos().x(), pos_before.y() + adjust_xy[1]) blkitem.blk._bounding_rect[1] = int(blkitem.pos().y()) return True def restore_charfmts(self, blkitem: TextBlkItem, text: str, new_text: str, char_fmts: List[QTextCharFormat]): Loading Loading @@ -1120,5 +1133,5 @@ def get_text_size(fm: QFontMetrics, text: str) -> Tuple[int, int]: return br.width(), brt.height() def get_words_length_list(fm: QFontMetrics, words: List[str]) -> List[int]: return [fm.tightBoundingRect(word).width() for word in words] return [fm.horizontalAdvance(word) for word in words] ui/textitem.py +1 −1 Original line number Diff line number Diff line Loading @@ -908,7 +908,7 @@ class TextBlkItem(QGraphicsTextItem): if repaint: self.repaint_background() def set_size(self, w: float, h: float, set_layout_maxsize=False, set_blk_size=False): def set_size(self, w: float, h: float, set_layout_maxsize=False, set_blk_size=True): ''' rotation invariant ''' Loading utils/text_layout.py +146 −38 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from typing import List, Tuple import numpy as np from .imgproc_utils import rotate_image from .textblock import TextBlock, TextAlignment class Line: Loading Loading @@ -38,7 +39,23 @@ class Line: self.pos_x += self.spacing self.spacing = 0 def get_max_width(line: Line, delimiter_len, max_width, words_length, srcline_wlist, line_no: int, line_height, reference_src_lines: bool = False): if reference_src_lines: if line_no >= 0 and line_no < len(srcline_wlist): _max_width = min(srcline_wlist[line_no], max_width) else: _max_width = max_width # if line_no >= 0 and line_no < len(srcline_wlist): # _max_width = srcline_wlist[line_no] / sum(srcline_wlist) * words_length # else: # _max_width = np.inf # _max_width = max(srcline_wlist) / sum(srcline_wlist) * words_length # _max_width = _max_width + delimiter_len * (line.num_words + 1) + line_height * 0.66 max_width = min(max_width, _max_width) return max_width def layout_lines_aligncenter( blk: TextBlock, mask: np.ndarray, words: List[str], centroid: List[int], Loading @@ -48,20 +65,23 @@ def layout_lines_aligncenter( spacing: int = 0, delimiter: str = ' ', max_central_width: float = np.inf, word_break: bool = False)->List[Line]: word_break: bool = False, reference_src_lines = False, srcline_wlist=None, start_from_top=False )->List[Line]: centroid_x, centroid_y = centroid adjust_x = adjust_y = 0 # m = cv2.moments(mask) mask = 255 - mask # centroid_y = int(m['m01'] / m['m00']) # centroid_x = int(m['m10'] / m['m00']) border_thr = 240 # layout the central line, the center word is approximately aligned with the centroid of the mask num_words = len(words) len_left, len_right = [], [] wlst_left, wlst_right = [], [] sum_left, sum_right = 0, 0 words_length = sum(wl_list) if num_words > 1: wl_array = np.array(wl_list, dtype=np.float64) wl_cumsums = np.cumsum(wl_array) Loading @@ -85,7 +105,7 @@ def layout_lines_aligncenter( bh, bw = mask.shape[:2] central_line = Line(words[central_index], pos_x, pos_y, wl_list[central_index], spacing) line_bottom = pos_y + line_height while sum_left > 0 or sum_right > 0: while (sum_left > 0 or sum_right > 0) and not start_from_top: left_valid, right_valid = False, False if sum_left > 0: Loading @@ -93,14 +113,16 @@ def layout_lines_aligncenter( new_x_l = centroid_x - new_len_l // 2 new_r_l = new_x_l + new_len_l if (new_x_l > 0 and new_r_l < bw): if mask[pos_y: line_bottom, new_x_l].sum()==0 and mask[pos_y: line_bottom, new_r_l].sum() == 0: if mask[pos_y: line_bottom, new_x_l].mean() > border_thr and \ mask[pos_y: line_bottom, new_r_l].mean() > border_thr: left_valid = True if sum_right > 0: new_len_r = central_line.length + len_right[0] + delimiter_len new_x_r = centroid_x - new_len_r // 2 new_r_r = new_x_r + new_len_r if (new_x_r > 0 and new_r_r < bw): if mask[pos_y: line_bottom, new_x_r].sum()==0 and mask[pos_y: line_bottom, new_r_r].sum() == 0: if mask[pos_y: line_bottom, new_x_r].mean() > border_thr and \ mask[pos_y: line_bottom, new_r_r].mean() > border_thr: right_valid = True insert_left = False Loading @@ -120,17 +142,49 @@ def layout_lines_aligncenter( central_line.append_right(wlst_right.pop(0), len_right[0] + delimiter_len, delimiter) sum_right -= len_right.pop(0) central_line.pos_x = new_x_r if central_line.length > max_central_width: _max_width = get_max_width(central_line, delimiter_len, max_central_width, words_length, srcline_wlist, -1, line_height, reference_src_lines) if central_line.length > _max_width: break line_right_no = line_left_no = 0 if reference_src_lines: nl = len(srcline_wlist) if nl % 2 == 0: line_right_no = nl // 2 line_left_no = nl // 2 - 1 else: line_right_no = nl // 2 + 1 line_left_no = nl // 2 - 1 if not start_from_top: central_line.strip_spacing() lines = [central_line] else: lines = [] sum_right = sum(wl_list) sum_left = 0 wlst_right = words len_right = wl_list line_right_no = 0 # layout bottom half if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) pos_x = centroid_x - wl // 2 if start_from_top: pos_y = centroid_y - int(blk.bounding_rect()[3] / 2) else: pos_y = centroid_y + line_height // 2 top_mean = mask[pos_y, :].mean() x_mean = mask.mean(axis=1) base_mean = x_mean.max() / 2 if top_mean < base_mean: available_y = np.where( x_mean[pos_y:] > base_mean )[0] if len(available_y) > 0: adjust_y = min(available_y[0], line_height) pos_y = pos_y + adjust_y line_bottom = pos_y + line_height line = Line(w, pos_x, pos_y, wl, spacing) lines.append(line) Loading @@ -143,15 +197,16 @@ def layout_lines_aligncenter( right_x = new_x + new_len 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: elif mask[pos_y: line_bottom, new_x].mean() < border_thr or\ mask[pos_y: line_bottom, right_x].mean() < border_thr: line_valid = False else: line_valid = True if line_valid: line.append_right(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: _max_width = get_max_width(line, delimiter_len, max_central_width, words_length, srcline_wlist, line_right_no, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) Loading @@ -167,6 +222,7 @@ def layout_lines_aligncenter( line.strip_spacing() line = Line(w, pos_x, pos_y, wl, spacing) lines.append(line) line_right_no += 1 # layout top half if sum_left > 0: Loading @@ -185,15 +241,16 @@ def layout_lines_aligncenter( right_x = new_x + new_len 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: elif mask[pos_y: line_bottom, new_x].mean() < border_thr or\ mask[pos_y: line_bottom, right_x].mean() < border_thr: line_valid = False else: line_valid = True if line_valid: line.append_left(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: _max_width = get_max_width(line, delimiter_len, max_central_width, words_length, srcline_wlist, line_left_no, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if sum_left > 0: w, wl = wlst_left.pop(-1), len_left.pop(-1) Loading @@ -209,6 +266,7 @@ def layout_lines_aligncenter( line.strip_spacing() line = Line(w, pos_x, pos_y, wl, spacing) lines.insert(0, line) line_left_no -= 1 # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) Loading @@ -217,9 +275,10 @@ def layout_lines_aligncenter( # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) return lines return lines, (adjust_x, adjust_y) def layout_lines_alignleft( def layout_lines_alignside( blk: TextBlock, mask: np.ndarray, words: List[str], origin: List[int], Loading @@ -228,14 +287,21 @@ def layout_lines_alignleft( line_height: int, spacing: int = 0, delimiter: str = ' ', word_break: bool = False)->List[Line]: word_break: bool = False, max_width: int = np.inf, reference_src_lines = False, srcline_wlist=None, )->List[Line]: align_right = blk.fontformat.alignment == TextAlignment.Right ox, oy = origin bh, bw = mask.shape[:2] mask = 255 - mask num_words = len(words) blk_rect = blk.bounding_rect() blk_width = blk_rect[2] lines = [] words_length = sum(wl_list) if num_words > 0: sum_right = np.array(wl_list).sum() w, wl = words.pop(0), wl_list.pop(0) Loading @@ -244,25 +310,37 @@ def layout_lines_alignleft( sum_right -= wl line_bottom = oy + line_height pos_y = oy line_id = 0 while sum_right > 0: w, wl = words.pop(0), wl_list.pop(0) sum_right -= wl new_len = line.length + wl + delimiter_len new_r = ox + new_len if align_right: new_x = ox + blk_width - new_len else: new_x = ox + new_len line_valid = False if new_r < bw: if mask[pos_y: line_bottom, new_r].sum()==0: if new_x < bw and new_x > 0: in_ballon = np.any(mask[np.clip(pos_y, 0, bh - 1): np.clip(line_bottom, 0, bh), new_x] != 0) if in_ballon: line_valid = True _max_width = get_max_width(line, delimiter_len, max_width, words_length, srcline_wlist, line_id, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if line_valid: line.append_right(w, wl+delimiter_len, delimiter) else: pos_y = line_bottom line_bottom += line_height line = Line(w, ox, pos_y, wl) line_id += 1 lines.append(line) return lines return lines, (0, 0) def layout_text( blk: TextBlock, mask: np.ndarray, mask_xyxy: List, centroid: List, Loading @@ -270,17 +348,45 @@ def layout_text( wl_list: List[int], delimiter: str, delimiter_len: int, angle: float, line_height: int, alignment: int, vertical: bool, spacing: int = 0, padding: float = 0, max_central_width=np.inf) -> Tuple[str, List]: max_central_width=np.inf, src_is_cjk=False, tgt_is_cjk=False, reference_src_lines = False ) -> Tuple[str, List]: angle = blk.angle alignment = blk.alignment start_from_top = False srcline_wlist = None reference_src_lines = False if len(blk.lines) > 0 and not tgt_is_cjk: srcline_wlist = blk.normalizd_width_list(normalize=False) srcline_width = sum(srcline_wlist) tgtline_width = sum(wl_list) + delimiter_len * max(len(wl_list) - 1, 0) content_growth = tgtline_width / srcline_width if content_growth < 1 and max_central_width != np.inf: max_central_width = max_central_width * content_growth pass if content_growth < 1.1: reference_src_lines = True if alignment == TextAlignment.Center and \ len(srcline_wlist) > 1: if len(srcline_wlist) == 2: start_from_top = True else: nw = len(srcline_wlist) # nl = min(nw // 2, 2) nl = 1 sum_top = sum(srcline_wlist[:nl]) sum_btn = sum(srcline_wlist[-nl:]) start_from_top = sum_top / sum_btn > 1.2 and srcline_wlist[0] / max(srcline_wlist) > 0.9 pass num_words = len(words) if num_words == 0: return [] centroid_x, centroid_y = centroid center_x = mask_xyxy[0] + centroid_x Loading @@ -305,11 +411,13 @@ def layout_text( new_cx, new_cy = new_origin[0] + new_rel_cx, new_origin[1] + new_rel_cy centroid = [int(new_cx), int(new_cy)] if alignment == 1: lines = layout_lines_aligncenter(mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width) if alignment == TextAlignment.Center: lines, adjust_xy = layout_lines_aligncenter(blk, mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width, reference_src_lines=reference_src_lines, srcline_wlist=srcline_wlist, start_from_top=start_from_top) else: lines = layout_lines_alignleft(mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter) lines, adjust_xy = layout_lines_alignside(blk, mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width, reference_src_lines=reference_src_lines, srcline_wlist=srcline_wlist) concated_text = [] pos_x_lst, pos_right_lst = [], [] Loading @@ -334,4 +442,4 @@ def layout_text( abs_x = shifted_x abs_y = shifted_y return concated_text, [abs_x, abs_y, canvas_w, canvas_h] No newline at end of file return concated_text, [abs_x, abs_y, canvas_w, canvas_h], start_from_top, adjust_xy No newline at end of file utils/text_processing.py +1 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ def seg_eng(text: str) -> List[str]: append_left = cond_prev elif len_next > 0: append_right = cond_next elif len_prev: elif len_prev > 0: append_left = cond_prev if append_left: Loading Loading
ui/module_parse_widgets.py +0 −4 Original line number Diff line number Diff line Loading @@ -6,10 +6,6 @@ from utils.logger import logger as LOGGER from .custom_widget import ConfigComboBox, ParamComboBox, NoBorderPushBtn from utils.shared import CONFIG_FONTSIZE_CONTENT, CONFIG_COMBOBOX_MIDEAN, CONFIG_COMBOBOX_LONG, CONFIG_COMBOBOX_SHORT, CONFIG_COMBOBOX_HEIGHT from utils.config import pcfg import logging # Настройка логгера logging.basicConfig(level=logging.DEBUG) from qtpy.QtWidgets import QPlainTextEdit, QHBoxLayout, QVBoxLayout, QWidget, QLabel, QCheckBox, QLineEdit, QGridLayout, QPushButton from qtpy.QtCore import Qt, Signal Loading
ui/scenetext_manager.py +23 −10 Original line number Diff line number Diff line Loading @@ -693,7 +693,7 @@ class SceneTextManager(QObject): def onAutoLayoutTextblks(self): selected_blks = self.canvas.selected_text_items() old_html_lst, old_rect_lst, trans_widget_lst = [], [], [] selected_blks = [blk for blk in selected_blks if not blk.is_vertical] selected_blks = [blk for blk in selected_blks if not blk.fontformat.vertical] if len(selected_blks) > 0: for blkitem in selected_blks: old_html_lst.append(blkitem.toHtml()) Loading Loading @@ -768,8 +768,6 @@ class SceneTextManager(QObject): region_x, region_y, region_w, region_h = region_rect words, delimiter = seg_text(text, pcfg.module.translate_target) if len(words) == 0: return wl_list = get_words_length_list(QFontMetrics(blk_font), words) text_w, text_h = text_size_func(text) Loading @@ -796,7 +794,7 @@ class SceneTextManager(QObject): resize_ratio = np.clip(min(area_ratio / ballon_area_thresh, region_rect [2] / max(wl_list)), downscale_constraint, 1.0) max_central_width = np.inf if tgt_is_cjk and not src_is_cjk: if not src_is_cjk: if ballon_area / text_area > 2: if blkitem.blk.text: _, _, brw, brh = blkitem.blk.bounding_rect() Loading Loading @@ -844,7 +842,22 @@ class SceneTextManager(QObject): centroid[0] = int(abs_centroid[0] - mask_xyxy[0]) centroid[1] = int(abs_centroid[1] - mask_xyxy[1]) new_text, xywh = layout_text(mask, mask_xyxy, centroid, words, wl_list, delimiter, delimiter_len, blkitem.blk.angle, line_height, fmt.alignment, fmt.vertical, 0, padding, max_central_width) new_text, xywh, start_from_top, adjust_xy = layout_text( blkitem.blk, mask, mask_xyxy, centroid, words, wl_list, delimiter, delimiter_len, line_height, 0, padding, max_central_width, src_is_cjk=src_is_cjk, tgt_is_cjk=tgt_is_cjk ) # font size post adjustment post_resize_ratio = 1 Loading @@ -868,13 +881,10 @@ class SceneTextManager(QObject): blkitem.textCursor().clearSelection() blkitem.setFontSize(new_font_size) scale = blkitem.scale() if scale != 1 and not fmt.alignment == 0: xywh = (np.array(xywh, np.float64) * scale).astype(np.int32).tolist() if restore_charfmts: char_fmts = blkitem.get_char_fmts() pos_before = blkitem.pos() blkitem.set_size(xywh[2], xywh[3], set_layout_maxsize=True) blkitem.setPlainText(new_text) if len(self.pairwidget_list) > blkitem.idx: Loading @@ -882,6 +892,9 @@ class SceneTextManager(QObject): if restore_charfmts: self.restore_charfmts(blkitem, text, new_text, char_fmts) blkitem.squeezeBoundingRect() if start_from_top: blkitem.setPos(blkitem.pos().x(), pos_before.y() + adjust_xy[1]) blkitem.blk._bounding_rect[1] = int(blkitem.pos().y()) return True def restore_charfmts(self, blkitem: TextBlkItem, text: str, new_text: str, char_fmts: List[QTextCharFormat]): Loading Loading @@ -1120,5 +1133,5 @@ def get_text_size(fm: QFontMetrics, text: str) -> Tuple[int, int]: return br.width(), brt.height() def get_words_length_list(fm: QFontMetrics, words: List[str]) -> List[int]: return [fm.tightBoundingRect(word).width() for word in words] return [fm.horizontalAdvance(word) for word in words]
ui/textitem.py +1 −1 Original line number Diff line number Diff line Loading @@ -908,7 +908,7 @@ class TextBlkItem(QGraphicsTextItem): if repaint: self.repaint_background() def set_size(self, w: float, h: float, set_layout_maxsize=False, set_blk_size=False): def set_size(self, w: float, h: float, set_layout_maxsize=False, set_blk_size=True): ''' rotation invariant ''' Loading
utils/text_layout.py +146 −38 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from typing import List, Tuple import numpy as np from .imgproc_utils import rotate_image from .textblock import TextBlock, TextAlignment class Line: Loading Loading @@ -38,7 +39,23 @@ class Line: self.pos_x += self.spacing self.spacing = 0 def get_max_width(line: Line, delimiter_len, max_width, words_length, srcline_wlist, line_no: int, line_height, reference_src_lines: bool = False): if reference_src_lines: if line_no >= 0 and line_no < len(srcline_wlist): _max_width = min(srcline_wlist[line_no], max_width) else: _max_width = max_width # if line_no >= 0 and line_no < len(srcline_wlist): # _max_width = srcline_wlist[line_no] / sum(srcline_wlist) * words_length # else: # _max_width = np.inf # _max_width = max(srcline_wlist) / sum(srcline_wlist) * words_length # _max_width = _max_width + delimiter_len * (line.num_words + 1) + line_height * 0.66 max_width = min(max_width, _max_width) return max_width def layout_lines_aligncenter( blk: TextBlock, mask: np.ndarray, words: List[str], centroid: List[int], Loading @@ -48,20 +65,23 @@ def layout_lines_aligncenter( spacing: int = 0, delimiter: str = ' ', max_central_width: float = np.inf, word_break: bool = False)->List[Line]: word_break: bool = False, reference_src_lines = False, srcline_wlist=None, start_from_top=False )->List[Line]: centroid_x, centroid_y = centroid adjust_x = adjust_y = 0 # m = cv2.moments(mask) mask = 255 - mask # centroid_y = int(m['m01'] / m['m00']) # centroid_x = int(m['m10'] / m['m00']) border_thr = 240 # layout the central line, the center word is approximately aligned with the centroid of the mask num_words = len(words) len_left, len_right = [], [] wlst_left, wlst_right = [], [] sum_left, sum_right = 0, 0 words_length = sum(wl_list) if num_words > 1: wl_array = np.array(wl_list, dtype=np.float64) wl_cumsums = np.cumsum(wl_array) Loading @@ -85,7 +105,7 @@ def layout_lines_aligncenter( bh, bw = mask.shape[:2] central_line = Line(words[central_index], pos_x, pos_y, wl_list[central_index], spacing) line_bottom = pos_y + line_height while sum_left > 0 or sum_right > 0: while (sum_left > 0 or sum_right > 0) and not start_from_top: left_valid, right_valid = False, False if sum_left > 0: Loading @@ -93,14 +113,16 @@ def layout_lines_aligncenter( new_x_l = centroid_x - new_len_l // 2 new_r_l = new_x_l + new_len_l if (new_x_l > 0 and new_r_l < bw): if mask[pos_y: line_bottom, new_x_l].sum()==0 and mask[pos_y: line_bottom, new_r_l].sum() == 0: if mask[pos_y: line_bottom, new_x_l].mean() > border_thr and \ mask[pos_y: line_bottom, new_r_l].mean() > border_thr: left_valid = True if sum_right > 0: new_len_r = central_line.length + len_right[0] + delimiter_len new_x_r = centroid_x - new_len_r // 2 new_r_r = new_x_r + new_len_r if (new_x_r > 0 and new_r_r < bw): if mask[pos_y: line_bottom, new_x_r].sum()==0 and mask[pos_y: line_bottom, new_r_r].sum() == 0: if mask[pos_y: line_bottom, new_x_r].mean() > border_thr and \ mask[pos_y: line_bottom, new_r_r].mean() > border_thr: right_valid = True insert_left = False Loading @@ -120,17 +142,49 @@ def layout_lines_aligncenter( central_line.append_right(wlst_right.pop(0), len_right[0] + delimiter_len, delimiter) sum_right -= len_right.pop(0) central_line.pos_x = new_x_r if central_line.length > max_central_width: _max_width = get_max_width(central_line, delimiter_len, max_central_width, words_length, srcline_wlist, -1, line_height, reference_src_lines) if central_line.length > _max_width: break line_right_no = line_left_no = 0 if reference_src_lines: nl = len(srcline_wlist) if nl % 2 == 0: line_right_no = nl // 2 line_left_no = nl // 2 - 1 else: line_right_no = nl // 2 + 1 line_left_no = nl // 2 - 1 if not start_from_top: central_line.strip_spacing() lines = [central_line] else: lines = [] sum_right = sum(wl_list) sum_left = 0 wlst_right = words len_right = wl_list line_right_no = 0 # layout bottom half if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) pos_x = centroid_x - wl // 2 if start_from_top: pos_y = centroid_y - int(blk.bounding_rect()[3] / 2) else: pos_y = centroid_y + line_height // 2 top_mean = mask[pos_y, :].mean() x_mean = mask.mean(axis=1) base_mean = x_mean.max() / 2 if top_mean < base_mean: available_y = np.where( x_mean[pos_y:] > base_mean )[0] if len(available_y) > 0: adjust_y = min(available_y[0], line_height) pos_y = pos_y + adjust_y line_bottom = pos_y + line_height line = Line(w, pos_x, pos_y, wl, spacing) lines.append(line) Loading @@ -143,15 +197,16 @@ def layout_lines_aligncenter( right_x = new_x + new_len 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: elif mask[pos_y: line_bottom, new_x].mean() < border_thr or\ mask[pos_y: line_bottom, right_x].mean() < border_thr: line_valid = False else: line_valid = True if line_valid: line.append_right(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: _max_width = get_max_width(line, delimiter_len, max_central_width, words_length, srcline_wlist, line_right_no, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if sum_right > 0: w, wl = wlst_right.pop(0), len_right.pop(0) Loading @@ -167,6 +222,7 @@ def layout_lines_aligncenter( line.strip_spacing() line = Line(w, pos_x, pos_y, wl, spacing) lines.append(line) line_right_no += 1 # layout top half if sum_left > 0: Loading @@ -185,15 +241,16 @@ def layout_lines_aligncenter( right_x = new_x + new_len 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: elif mask[pos_y: line_bottom, new_x].mean() < border_thr or\ mask[pos_y: line_bottom, right_x].mean() < border_thr: line_valid = False else: line_valid = True if line_valid: line.append_left(w, wl+delimiter_len, delimiter) line.pos_x = new_x if new_len > max_central_width: _max_width = get_max_width(line, delimiter_len, max_central_width, words_length, srcline_wlist, line_left_no, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if sum_left > 0: w, wl = wlst_left.pop(-1), len_left.pop(-1) Loading @@ -209,6 +266,7 @@ def layout_lines_aligncenter( line.strip_spacing() line = Line(w, pos_x, pos_y, wl, spacing) lines.insert(0, line) line_left_no -= 1 # rbgmsk = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # cv2.circle(rbgmsk, (centroid_x, centroid_y), 10, (255, 0, 0)) Loading @@ -217,9 +275,10 @@ def layout_lines_aligncenter( # cv2.imshow('mask', rbgmsk) # cv2.waitKey(0) return lines return lines, (adjust_x, adjust_y) def layout_lines_alignleft( def layout_lines_alignside( blk: TextBlock, mask: np.ndarray, words: List[str], origin: List[int], Loading @@ -228,14 +287,21 @@ def layout_lines_alignleft( line_height: int, spacing: int = 0, delimiter: str = ' ', word_break: bool = False)->List[Line]: word_break: bool = False, max_width: int = np.inf, reference_src_lines = False, srcline_wlist=None, )->List[Line]: align_right = blk.fontformat.alignment == TextAlignment.Right ox, oy = origin bh, bw = mask.shape[:2] mask = 255 - mask num_words = len(words) blk_rect = blk.bounding_rect() blk_width = blk_rect[2] lines = [] words_length = sum(wl_list) if num_words > 0: sum_right = np.array(wl_list).sum() w, wl = words.pop(0), wl_list.pop(0) Loading @@ -244,25 +310,37 @@ def layout_lines_alignleft( sum_right -= wl line_bottom = oy + line_height pos_y = oy line_id = 0 while sum_right > 0: w, wl = words.pop(0), wl_list.pop(0) sum_right -= wl new_len = line.length + wl + delimiter_len new_r = ox + new_len if align_right: new_x = ox + blk_width - new_len else: new_x = ox + new_len line_valid = False if new_r < bw: if mask[pos_y: line_bottom, new_r].sum()==0: if new_x < bw and new_x > 0: in_ballon = np.any(mask[np.clip(pos_y, 0, bh - 1): np.clip(line_bottom, 0, bh), new_x] != 0) if in_ballon: line_valid = True _max_width = get_max_width(line, delimiter_len, max_width, words_length, srcline_wlist, line_id, line_height, reference_src_lines) if new_len > _max_width: line_valid = False if line_valid: line.append_right(w, wl+delimiter_len, delimiter) else: pos_y = line_bottom line_bottom += line_height line = Line(w, ox, pos_y, wl) line_id += 1 lines.append(line) return lines return lines, (0, 0) def layout_text( blk: TextBlock, mask: np.ndarray, mask_xyxy: List, centroid: List, Loading @@ -270,17 +348,45 @@ def layout_text( wl_list: List[int], delimiter: str, delimiter_len: int, angle: float, line_height: int, alignment: int, vertical: bool, spacing: int = 0, padding: float = 0, max_central_width=np.inf) -> Tuple[str, List]: max_central_width=np.inf, src_is_cjk=False, tgt_is_cjk=False, reference_src_lines = False ) -> Tuple[str, List]: angle = blk.angle alignment = blk.alignment start_from_top = False srcline_wlist = None reference_src_lines = False if len(blk.lines) > 0 and not tgt_is_cjk: srcline_wlist = blk.normalizd_width_list(normalize=False) srcline_width = sum(srcline_wlist) tgtline_width = sum(wl_list) + delimiter_len * max(len(wl_list) - 1, 0) content_growth = tgtline_width / srcline_width if content_growth < 1 and max_central_width != np.inf: max_central_width = max_central_width * content_growth pass if content_growth < 1.1: reference_src_lines = True if alignment == TextAlignment.Center and \ len(srcline_wlist) > 1: if len(srcline_wlist) == 2: start_from_top = True else: nw = len(srcline_wlist) # nl = min(nw // 2, 2) nl = 1 sum_top = sum(srcline_wlist[:nl]) sum_btn = sum(srcline_wlist[-nl:]) start_from_top = sum_top / sum_btn > 1.2 and srcline_wlist[0] / max(srcline_wlist) > 0.9 pass num_words = len(words) if num_words == 0: return [] centroid_x, centroid_y = centroid center_x = mask_xyxy[0] + centroid_x Loading @@ -305,11 +411,13 @@ def layout_text( new_cx, new_cy = new_origin[0] + new_rel_cx, new_origin[1] + new_rel_cy centroid = [int(new_cx), int(new_cy)] if alignment == 1: lines = layout_lines_aligncenter(mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width) if alignment == TextAlignment.Center: lines, adjust_xy = layout_lines_aligncenter(blk, mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width, reference_src_lines=reference_src_lines, srcline_wlist=srcline_wlist, start_from_top=start_from_top) else: lines = layout_lines_alignleft(mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter) lines, adjust_xy = layout_lines_alignside(blk, mask, words, centroid, wl_list, delimiter_len, line_height, spacing, delimiter, max_central_width, reference_src_lines=reference_src_lines, srcline_wlist=srcline_wlist) concated_text = [] pos_x_lst, pos_right_lst = [], [] Loading @@ -334,4 +442,4 @@ def layout_text( abs_x = shifted_x abs_y = shifted_y return concated_text, [abs_x, abs_y, canvas_w, canvas_h] No newline at end of file return concated_text, [abs_x, abs_y, canvas_w, canvas_h], start_from_top, adjust_xy No newline at end of file
utils/text_processing.py +1 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ def seg_eng(text: str) -> List[str]: append_left = cond_prev elif len_next > 0: append_right = cond_next elif len_prev: elif len_prev > 0: append_left = cond_prev if append_left: Loading