Python计算机视觉项目:如何检测报纸图片中的图形以实现图文分离?
报纸图片中图形检测的Python实现方法
1. 传统计算机视觉方法(快速上手,无需训练)
这类方法依赖图像的纹理、边缘、连通域特征区分文本与图形,适合排版规整的报纸场景。
核心步骤:
- 预处理:先将图片转灰度、降噪,统一尺寸。用OpenCV的
cv2.cvtColor()转灰度,cv2.GaussianBlur()做高斯降噪。 - 纹理/边缘区分:文本区域高频纹理多,图形区域相对平滑。可通过Canny边缘检测突出文本边缘,再结合连通域分析过滤:文本是小面积连通域(单个字符),图形是大面积连通域。
- 形态学优化:用膨胀、腐蚀操作填补图形区域的小缺口,或清除文本区域的杂点。
代码示例:
import cv2 import numpy as np # 读取并预处理图片 img = cv2.imread("paper.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) # 边缘检测 edges = cv2.Canny(blur, 50, 150) # 提取连通域并过滤图形区域 contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) mask = np.zeros_like(gray) # 阈值根据图片实际尺寸调整(单个字符面积通常小于2000) for cnt in contours: if cv2.contourArea(cnt) > 2000: cv2.drawContours(mask, [cnt], -1, 255, -1) # 提取图形区域 graph_regions = cv2.bitwise_and(img, img, mask=mask) cv2.imwrite("extracted_graphs.jpg", graph_regions)
2. 深度学习方法(复杂场景下准确率更高)
针对排版混乱、倾斜文本、不规则图形的报纸,预训练分割模型的效果更稳定。
推荐方案:
- Mask R-CNN:直接检测并分割图片中的物体,用COCO预训练权重,微调少量报纸数据即可区分文本与图形。
- U-Net:做二分类语义分割,将图片分为“文本”“图形”两类,需准备少量标注好的报纸数据集训练。
代码示例(Detectron2实现Mask R-CNN快速检测):
from detectron2 import model_zoo from detectron2.engine import DefaultPredictor from detectron2.config import get_cfg import cv2 cfg = get_cfg() cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")) cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # 置信度阈值 predictor = DefaultPredictor(cfg) img = cv2.imread("paper.jpg") outputs = predictor(img) # 过滤非文本区域(COCO中79是text类别) mask = np.zeros(img.shape[:2], dtype=np.uint8) for i in range(len(outputs["instances"])): if outputs["instances"].pred_classes[i] != 79: instance_mask = outputs["instances"].pred_masks[i].cpu().numpy() mask[instance_mask] = 255 graph_regions = cv2.bitwise_and(img, img, mask=mask) cv2.imwrite("deep_learning_graphs.jpg", graph_regions)
3. OCR辅助方法(快速验证)
先用OCR识别所有文本区域,未被识别的区域即为图形,适合快速验证思路。
代码示例:
import cv2 import pytesseract from pytesseract import Output img = cv2.imread("paper.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 获取高置信度文本的 bounding box d = pytesseract.image_to_data(gray, output_type=Output.DICT) mask = np.ones(gray.shape, dtype=np.uint8) * 255 for i in range(len(d['text'])): if int(d['conf'][i]) > 60: x, y, w, h = d['left'][i], d['top'][i], d['width'][i], d['height'][i] cv2.rectangle(mask, (x, y), (x+w, y+h), 0, -1) # 提取图形区域 graph_mask = cv2.bitwise_not(mask) graph_regions = cv2.bitwise_and(img, img, mask=graph_mask) cv2.imwrite("ocr_based_graphs.jpg", graph_regions)
选择建议
- 规整报纸优先用传统CV方法,速度快、无需训练;
- 复杂场景(老报纸、不规则排版)选深度学习模型,准确率更高;
- 快速验证思路可先试OCR辅助法,代码量少易实现。
内容的提问来源于stack exchange,提问作者Hamid Khellaf
相关产品推荐
相关产品推荐

