如何解决OpenCV修复倾斜文本时的矩形裁剪偏差问题?
问题描述
我用Python对图像执行OCR,获取每个单词的坐标后进行掩膜和修复操作,但图像顶部的文本修复效果始终不佳。排查后发现,OpenCV只能以水平/垂直的轴对齐矩形裁剪文本,导致裁剪区域错误——但用相同坐标在图像编辑工具里却能得到正确的边界框,这种偏差直接影响了修复结果,请问该怎么改进?
当前代码:
textCoordinates = runOcr(img) for i in textCoordinates: tl[1], br[1], tl[0], br[0] = i.coordinates # 修正原代码语法错误 smImg = img[tl[1]:br[1], tl[0]:br[0]] inpaintedImg = inpaintAlgo(smImg) # 该函数负责检测、生成掩膜并执行修复
问题核心
你的OCR工具返回的应该是带旋转角度的文本边界框(非轴对齐矩形),但当前代码直接用轴对齐的矩形裁剪,会把文本周围的多余背景或者部分倾斜文本排除在外,尤其是顶部可能存在倾斜的文本,导致修复用的局部图像不准确,最终修复效果差。
改进方案
方案1:基于旋转矩形的精准裁剪与修复
如果OCR返回的坐标包含旋转角度、中心坐标、宽高,或者能提取出四个角点计算出旋转参数,可以先把文本区域转正后再处理,修复完成后再旋转回原角度:
import cv2 import numpy as np textCoordinates = runOcr(img) for i in textCoordinates: # 假设i.coordinates返回四个角点,格式为[(x1,y1), (x2,y2), (x3,y3), (x4,y4)] pts = np.array(i.coordinates, dtype=np.float32) # 计算旋转矩形的核心参数:中心、宽高、角度 rect = cv2.minAreaRect(pts) center, size, angle = rect width, height = int(size[0]), int(size[1]) # 生成旋转矩阵,将文本区域转正 rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) rotated_img = cv2.warpAffine(img, rotation_matrix, (img.shape[1], img.shape[0]), flags=cv2.INTER_CUBIC) # 裁剪转正后的文本区域 rotated_tl = (int(center[0] - width/2), int(center[1] - height/2)) rotated_br = (int(center[0] + width/2), int(center[1] + height/2)) cropped_img = rotated_img[rotated_tl[1]:rotated_br[1], rotated_tl[0]:rotated_br[0]] # 执行修复操作 inpainted_cropped = inpaintAlgo(cropped_img) # 将修复后的区域放回旋转后的图像 rotated_img[rotated_tl[1]:rotated_br[1], rotated_tl[0]:rotated_br[0]] = inpainted_cropped # 旋转回原角度,更新原图 inverse_rotation_matrix = cv2.getRotationMatrix2D(center, -angle, 1.0) img = cv2.warpAffine(rotated_img, inverse_rotation_matrix, (img.shape[1], img.shape[0]), flags=cv2.INTER_CUBIC)
方案2:直接生成多边形掩膜进行修复
不需要裁剪图像,直接用OCR返回的四个角点生成精确的多边形掩膜,然后对原图执行inpaint操作:
import cv2 import numpy as np textCoordinates = runOcr(img) mask = np.zeros(img.shape[:2], dtype=np.uint8) # 创建全黑初始掩膜 for i in textCoordinates: # 假设i.coordinates返回四个角点,格式为[(x1,y1), (x2,y2), (x3,y3), (x4,y4)] pts = np.array(i.coordinates, dtype=np.int32) pts = pts.reshape((-1, 1, 2)) # 在掩膜上填充文本区域为白色(255),标记需要修复的区域 cv2.fillPoly(mask, [pts], 255) # 直接对原图执行inpaint,使用精确的多边形掩膜 inpainted_img = cv2.inpaint(img, mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)
注意事项
- 确认OCR返回的坐标格式:不同OCR工具(如Tesseract、EasyOCR)返回的坐标格式不同,有的是四个角点,有的是轴对齐矩形加角度,需要根据实际情况调整参数提取逻辑。
- 如果你的
inpaintAlgo函数依赖局部图像的上下文信息,方案1更合适;如果只需要精准覆盖文本区域,方案2的执行效率更高。
内容的提问来源于stack exchange,提问作者Arnav Mehta
相关产品推荐
相关产品推荐

