如何用Python3去除流程图/决策树图像中的形状并保留文本?
去除流程图矩形框、保留文本的Python方案
嘿,这个问题我之前做OCR预处理的时候踩过类似的坑——流程图里的矩形框确实会严重干扰文本区域检测,分享几个我亲测有效的Python处理思路:
方法一:OpenCV轮廓检测+矩形过滤
这个方法的核心是识别出图像中的矩形轮廓,然后将其填充为背景色,只留下文本。步骤很清晰:
- 图像灰度化、二值化(把文本和背景区分开)
- 检测所有轮廓,过滤掉符合矩形特征的轮廓(比如顶点数、面积、宽高比)
- 将这些矩形轮廓填充为背景色,保留文本
代码示例:
import cv2 import numpy as np def remove_flowchart_boxes(image_path): # 读取图像 img = cv2.imread(image_path) # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化(自适应阈值适合光照不均的情况;如果是白底黑框黑字,可能需要反色) binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 检测轮廓 contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历轮廓,过滤矩形 for cnt in contours: # 计算轮廓的近似多边形 epsilon = 0.02 * cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, epsilon, True) # 判断是否为矩形:4个顶点,且面积、宽高比符合流程图框的特征 area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) aspect_ratio = w / float(h) # 参数需根据你的图像调整:面积太小的是文本,太大的可能不是框 if len(approx) == 4 and area > 1000 and 0.5 < aspect_ratio < 2: # 将矩形填充为背景色(假设背景是白色,用255;深色背景改成0) cv2.drawContours(img, [cnt], -1, (255, 255, 255), thickness=cv2.FILLED) # 保存处理后的图像 cv2.imwrite("cleaned_image.jpg", img) return img # 调用示例 remove_flowchart_boxes("flowchart.png")
方法二:颜色分割+图像修复
如果你的流程图框是固定颜色(比如蓝色、黑色),可以先把框的颜色区域提取出来,再用OpenCV的图像修复功能填补这些区域,保留文本:
import cv2 import numpy as np def remove_colored_boxes(image_path): img = cv2.imread(image_path) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义框的颜色范围(这里以蓝色为例,需用取色工具获取自己图像的HSV值) lower_blue = np.array([90, 50, 50]) upper_blue = np.array([130, 255, 255]) # 生成颜色掩码 mask = cv2.inRange(hsv, lower_blue, upper_blue) # 膨胀掩码,确保框的边缘都被覆盖 kernel = np.ones((3,3), np.uint8) mask = cv2.dilate(mask, kernel, iterations=1) # 用图像修复填补框的区域 cleaned_img = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA) cv2.imwrite("cleaned_image_color.jpg", cleaned_img) return cleaned_img
方法三:结合OCR文本区域检测
如果上面的方法效果不好,可以先让OCR工具(比如Tesseract)检测出文本区域,然后只保留这些区域,把其他区域(框)置为背景:
import cv2 import pytesseract from pytesseract import Output def keep_only_text_regions(image_path): img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 用Tesseract检测文本区域 d = pytesseract.image_to_data(gray, output_type=Output.DICT) n_boxes = len(d['text']) # 创建全白背景 cleaned_img = np.ones_like(img) * 255 # 遍历每个检测到的文本框,把原图对应区域复制到新图像 for i in range(n_boxes): if int(d['conf'][i]) > 60: # 只保留置信度高的文本区域 (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i]) cleaned_img[y:y+h, x:x+w] = img[y:y+h, x:x+w] cv2.imwrite("cleaned_image_ocr.jpg", cleaned_img) return cleaned_img
小提示
- 不同的流程图参数不一样,比如轮廓过滤的面积阈值、颜色范围,你需要根据自己的图像调整;
- 如果框是虚线,建议先做一次形态学膨胀,把虚线变成实线再检测;
- 二值化的时候如果文本和框颜色接近,可以尝试调整阈值或者用边缘检测辅助。
内容的提问来源于stack exchange,提问作者Bade
相关产品推荐
相关产品推荐

