Added improvements
This commit is contained in:
@@ -11,8 +11,8 @@ Strategy:
|
||||
2. Detect the original font size from the OCR bounding boxes.
|
||||
3. Dynamically wrap and scale down the translated text if it exceeds the bubble dimensions.
|
||||
4. Render the translated text centered inside the bubble bounding box.
|
||||
5. Uses uniform line heights to prevent accent collisions.
|
||||
6. Adds a white stroke to the text to cover any residual original characters.
|
||||
5. Uses uniform line heights (ascent + descent) to prevent Catalan accent collisions (È, À).
|
||||
6. Adds a dynamic white stroke to the text to cover any residual original characters.
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -25,26 +25,19 @@ from typing import Dict, List, Tuple, Optional, Set, Any
|
||||
# ============================================================
|
||||
# CONFIG — edit these paths to match your setup
|
||||
# ============================================================
|
||||
IMAGE_PATH = "003.jpg"
|
||||
BUBBLES_PATH = "bubbles.json"
|
||||
TRANSLATIONS_PATH = "output_003.txt"
|
||||
OUTPUT_PATH = "translated_page_003.png"
|
||||
IMAGE_PATH = "004.png"
|
||||
BUBBLES_PATH = "bubbles_004.json"
|
||||
TRANSLATIONS_PATH = "output_004.txt"
|
||||
OUTPUT_PATH = "translated_page_004.png"
|
||||
|
||||
# Font candidates — first one that loads wins
|
||||
# Font candidates — Prioritizes Laffayette for Catalan, with safe fallbacks
|
||||
FONT_CANDIDATES = [
|
||||
"fonts/animeace2_reg.ttf",
|
||||
"fonts/ComicNeue-Bold.ttf",
|
||||
# Mac fallbacks
|
||||
"/System/Library/Fonts/Supplemental/Comic Sans MS Bold.ttf",
|
||||
"/System/Library/Fonts/Supplemental/Arial Bold.ttf",
|
||||
# Windows fallbacks
|
||||
"C:\\Windows\\Fonts\\comicbd.ttf",
|
||||
"C:\\Windows\\Fonts\\arialbd.ttf",
|
||||
# Linux fallbacks
|
||||
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
|
||||
]
|
||||
|
||||
DEFAULT_FONT_SIZE = 24
|
||||
MIN_FONT_SIZE = 12
|
||||
DEFAULT_FONT_SIZE = 18
|
||||
MIN_FONT_SIZE = 8
|
||||
QUAD_PAD = 4 # extra pixels added around each quad before white-fill
|
||||
|
||||
# ============================================================
|
||||
@@ -105,9 +98,7 @@ def parse_translations(filepath: str) -> Dict[int, str]:
|
||||
return translations
|
||||
|
||||
def parse_bubbles(filepath: str):
|
||||
"""
|
||||
Returns the full JSON data.
|
||||
"""
|
||||
"""Returns the full JSON data."""
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
return data
|
||||
@@ -205,7 +196,7 @@ def fit_text_dynamically(
|
||||
|
||||
wrapped_lines = textwrap.wrap(text, width=chars_per_line)
|
||||
|
||||
# Use uniform font metrics for height instead of per-line bounding boxes
|
||||
# Use uniform font metrics for height to protect accents like È
|
||||
line_spacing = max(2, int(font_size * 0.15))
|
||||
if hasattr(font, 'getmetrics'):
|
||||
ascent, descent = font.getmetrics()
|
||||
@@ -246,7 +237,7 @@ def render_text(
|
||||
):
|
||||
"""
|
||||
Draws the translated text centered in the line_union_bbox of each bubble.
|
||||
Adds a white stroke (outline) to cover any residual original characters.
|
||||
Adds a dynamic white stroke (outline) to cover any residual original characters.
|
||||
"""
|
||||
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
|
||||
pil_img = Image.fromarray(image_rgb)
|
||||
@@ -280,7 +271,7 @@ def render_text(
|
||||
target_size = get_original_font_size(val)
|
||||
wrapped_lines, font, line_spacing, final_size = fit_text_dynamically(text, font_path, bw, bh, target_size)
|
||||
|
||||
# Use uniform typographic line height for rendering
|
||||
# Use uniform typographic line height for rendering to protect accents
|
||||
if hasattr(font, 'getmetrics'):
|
||||
ascent, descent = font.getmetrics()
|
||||
line_h = ascent + descent
|
||||
@@ -290,6 +281,8 @@ def render_text(
|
||||
total_text_height = (line_h * len(wrapped_lines)) + (line_spacing * max(0, len(wrapped_lines) - 1))
|
||||
|
||||
current_y = by + (bh - total_text_height) // 2
|
||||
|
||||
# Dynamic outline thickness based on the final scaled font size
|
||||
outline_thickness = max(2, int(final_size * 0.10))
|
||||
|
||||
for i, line in enumerate(wrapped_lines):
|
||||
@@ -301,6 +294,7 @@ def render_text(
|
||||
|
||||
current_x = bx + (bw - lw) // 2
|
||||
|
||||
# Draw text with white stroke for artifact coverage
|
||||
draw.text(
|
||||
(current_x, current_y),
|
||||
line,
|
||||
|
||||
Reference in New Issue
Block a user