You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python网页漫画OCR文本定位与翻译替换的技术求助

漫画OCR翻译项目:文本位置识别与翻译文本写入解决方案

一、解决文本位置识别(从单字符到整气泡/整行)

当前pytesseract仅识别单个字符,核心问题是未配置合适的OCR模式及做针对性图像预处理。

1. 图像预处理(OpenCV)

漫画图像背景复杂,先通过降噪和二值化突出文本区域:

import cv2

# 读取漫画图片
img = cv2.imread("comic_page.png")
# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯模糊降噪
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 自适应二值化(适配明暗不均的气泡,黑色文本转白色,背景转黑色)
thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)

2. 调整pytesseract配置,识别整行/整块文本

默认pytesseract会拆分字符,通过--psm参数指定文本模式,比如用--psm 6(假设文本是单一均匀块)或--psm 7(单行文本),结合--oem 3使用默认引擎:

import pytesseract

# 自定义OCR配置
custom_config = r"--oem 3 --psm 6"
# 获取结构化文本数据(含位置、置信度)
ocr_data = pytesseract.image_to_data(thresh, output_type=pytesseract.Output.DICT, config=custom_config)

# 过滤有效文本框(置信度>60,排除无效识别)
valid_boxes = []
for i in range(len(ocr_data["text"])):
    conf = int(ocr_data["conf"][i])
    text = ocr_data["text"][i].strip()
    if conf > 60 and text:
        x, y, w, h = ocr_data["left"][i], ocr_data["top"][i], ocr_data["width"][i], ocr_data["height"][i]
        valid_boxes.append({"text": text, "x": x, "y": y, "w": w, "h": h})

3. 进阶:先识别对话气泡,再识别内部文本

如果整行识别仍不准,先通过OpenCV检测气泡轮廓(漫画气泡多为封闭形状),再在气泡内部做OCR:

# 查找气泡轮廓(只保留外层轮廓)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

bubble_boxes = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    # 过滤过小的噪点轮廓
    if area > 500:
        x, y, w, h = cv2.boundingRect(cnt)
        # 提取气泡区域的ROI
        bubble_roi = thresh[y:y+h, x:x+w]
        # 在气泡内识别文本
        bubble_text = pytesseract.image_to_string(bubble_roi, config=custom_config).strip()
        if bubble_text:
            bubble_boxes.append({"text": bubble_text, "x": x, "y": y, "w": w, "h": h})

二、基于位置写入翻译文本(用Pillow处理排版)

OpenCV的文本绘制功能有限,用Pillow可更好处理多行文本、字体适配和原文本覆盖:

1. 覆盖原文本区域并写入翻译内容

from PIL import Image, ImageDraw, ImageFont
import textwrap

# 打开图片
img_pil = Image.open("comic_page.png")
draw = ImageDraw.Draw(img_pil)

# 假设已完成翻译,得到translated_text,以及气泡/文本框信息box
translated_text = "Esempio di testo tradotto in italiano"
box = bubble_boxes[0]  # 取第一个气泡示例

# 选择支持意大利语的字体(需确保字体文件存在,比如Arial Unicode MS)
font_path = "arial.ttf"
font_size = 20
font = ImageFont.truetype(font_path, font_size)

# 调整字体大小,确保文本宽度不超过气泡宽度(留10px边距)
while font.getsize(translated_text)[0] > box["w"] - 10:
    font_size -= 1
    font = ImageFont.truetype(font_path, font_size)

# 拆分长文本为多行(适配气泡高度)
wrapped_lines = textwrap.wrap(translated_text, width=int(box["w"] / (font_size * 0.6)))
line_height = font.getsize("A")[1]
total_text_height = len(wrapped_lines) * line_height

# 先画白色矩形覆盖原文本区域(完全覆盖气泡内部)
draw.rectangle([box["x"], box["y"], box["x"]+box["w"], box["y"]+box["h"]], fill="white")

# 计算文本起始位置(居中对齐,适配漫画排版)
start_x = box["x"] + (box["w"] - font.getsize(wrapped_lines[0])[0]) // 2
start_y = box["y"] + (box["h"] - total_text_height) // 2

# 逐行写入翻译文本
current_y = start_y
for line in wrapped_lines:
    line_width = font.getsize(line)[0]
    line_x = box["x"] + (box["w"] - line_width) // 2
    draw.text((line_x, current_y), line, font=font, fill="black")
    current_y += line_height

# 保存处理后的图片
img_pil.save("translated_comic_page.png")

三、关键注意事项

  • 确保pytesseract安装了原漫画语言的训练包(比如原文本是中文,需安装中文包),否则OCR识别准确率会极低。
  • 字体选择要支持意大利语特殊字符(比如à、è、ì、ò、ù),避免乱码。
  • 不同漫画的气泡样式不同,可能需要调整二值化参数、轮廓过滤的面积阈值,适配你的漫画风格。

内容的提问来源于stack exchange,提问作者Flairell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:45:29