如何用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()本身不支持自动换行,需要手动拆分文字并计算每行位置:
- 用
cv2.getTextSize()计算单行文字的宽度,根据ROI的可用宽度拆分文字为多行(建议预留10%的边距避免文字溢出)。 - 计算每行的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
相关产品推荐
相关产品推荐

