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

如何用OpenCV2移除图像文字并精准居中替换(含漫画ROI场景)

OpenCV 文字移除与替换的实现方案

一、图像文字移除的通用流程

不管mask是否连通,文字移除可以按以下通用步骤处理:

  • 预处理mask:如果mask内的文字区域分散不连通,先做形态学闭操作(cv2.morphologyEx(mask, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)))),把分散的文字块合并成连续区域,能大幅提升cv2.inpaint的修复效果。
  • 图像修复:用cv2.inpaint(src, mask, 3, cv2.INPAINT_TELEA)处理原图和修复后的mask,TELEA算法对文字类的修复表现更稳定。
  • ROI还原:如果已经裁剪出文字ROI,修复完成后把处理好的ROI放回原图对应位置即可。

二、精准获取ROI的中心与尺寸

你写的midpoint函数是可行的,但前提是能拿到ROI区域的准确边界(左上角(x1,y1)和右下角(x2,y2))。如果因为mask不连通无法直接获取边界,可以用更精准的轮廓检测法:

import cv2
import numpy as np

# 对mask提取轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 合并所有轮廓的点集
all_contour_points = np.vstack(contours)
# 获取所有文字区域的最小外接矩形
min_rect = cv2.minAreaRect(all_contour_points)
# 解析矩形的中心、宽高
(x_mid, y_mid), (w, h), _ = min_rect
# 转成整数坐标
x_mid, y_mid, w, h = int(x_mid), int(y_mid), int(w), int(h)

如果已经完成ROI裁剪,直接从ROI的shape就能拿到尺寸:h, w = roi.shape[:2],中心坐标则是原图中ROI左上角x + w//2,左上角y + h//2,这种方法比midpoint更直接,只要ROI裁剪准确就不会有误差。

三、文字居中与自动换行实现

cv2.putText()本身不支持自动换行,需要手动拆分文字并计算每行位置:

  1. 用cv2.getTextSize()计算单行文字的宽度,根据ROI的可用宽度拆分文字为多行(建议预留10%的边距避免文字溢出)。
  2. 计算每行的x坐标实现水平居中,通过总行高与ROI高度的差值计算起始y坐标,实现垂直居中。

示例代码(针对ROI区域的换行居中):

def draw_centered_text(roi, text, font=cv2.FONT_HERSHEY_SIMPLEX, font_scale=1, color=(0,0,0), thickness=2, line_spacing=1.2):
    h, w = roi.shape[:2]
    # 获取单个字符的高度
    (_, text_h), _ = cv2.getTextSize("测试", font, font_scale, thickness)
    line_h = int(text_h * line_spacing)
    
    # 拆分文字为多行
    words = text.split()
    lines = []
    current_line = []
    current_w = 0
    word_gap = 5  # 单词间间距
    for word in words:
        word_w = cv2.getTextSize(word, font, font_scale, thickness)[0][0]
        if current_w + word_w + word_gap <= w * 0.9:  # 预留10%边距
            current_w += word_w + word_gap
            current_line.append(word)
        else:
            lines.append(' '.join(current_line))
            current_line = [word]
            current_w = word_w
    if current_line:
        lines.append(' '.join(current_line))
    
    # 计算垂直居中的起始y坐标
    total_h = len(lines) * line_h
    start_y = (h - total_h) // 2 + text_h
    
    # 逐行绘制文字
    for i, line in enumerate(lines):
        line_w = cv2.getTextSize(line, font, font_scale, thickness)[0][0]
        x = (w - line_w) // 2
        y = start_y + i * line_h
        cv2.putText(roi, line, (x, y), font, font_scale, color, thickness)
    return roi

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:00:30