如何使用Python与OpenCV识别PDF中带四角黑块的分隔页面
问题分析
- 核心逻辑错误:
cv2.TM_SQDIFF_NORMED是平方差匹配,数值越小匹配度越高,你代码中用max_val >= 阈值的判断逻辑完全相反,这是全文档无匹配的主要原因 - 匹配范围不合理:全页面搜索模板容易引入无关区域干扰,你需要的特征固定出现在页面四个角,只需限定四个角落区域匹配即可
- 缺少预处理:没有对PDF渲染的灰度图做二值化,不同页面的灰度差异、背景杂讯会严重影响匹配准确率
- 单匹配点校验不足:你只做了单次全图匹配,没有校验四个角是否同时存在方块,很容易出现误判
可行解决方案
修改后代码如下:
import cv2 import numpy as np import fitz # 配置参数 filename = 'test.pdf' template = cv2.imread('template.png', 0) w, h = template.shape[::-1] # 二值化模板,消除灰度差异影响 _, template_bin = cv2.threshold(template, 127, 255, cv2.THRESH_BINARY) # 匹配阈值(SQDIFF_NORMED下数值越小匹配度越高,建议0.1~0.3之间调整) MATCH_THRESHOLD = 0.2 # 角落搜索范围,取页面边角的n像素正方形区域,根据你的方块大小调整 SEARCH_SIZE = max(w, h) + 10 pdf_doc = fitz.open(filename) separator_pages = [] for index, page in enumerate(pdf_doc.pages()): # 渲染PDF页面,可调整dpi提升渲染清晰度 pix = page.get_pixmap(alpha=0, dpi=150) im = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n) img_bgr = np.ascontiguousarray(im[..., [2, 1, 0]], dtype=np.uint8) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) # 页面二值化,突出黑色方块特征 _, img_bin = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY) page_h, page_w = img_bin.shape # 提取四个角落的搜索区域 roi_list = [ img_bin[0:SEARCH_SIZE, 0:SEARCH_SIZE], # 左上角 img_bin[0:SEARCH_SIZE, page_w-SEARCH_SIZE:page_w], # 右上角 img_bin[page_h-SEARCH_SIZE:page_h, 0:SEARCH_SIZE], # 左下角 img_bin[page_h-SEARCH_SIZE:page_h, page_w-SEARCH_SIZE:page_w] # 右下角 ] match_count = 0 for roi in roi_list: res = cv2.matchTemplate(roi, template_bin, cv2.TM_SQDIFF_NORMED) min_val, _, _, _ = cv2.minMaxLoc(res) if min_val < MATCH_THRESHOLD: match_count +=1 # 四个角都匹配到则判定为分隔页 if match_count == 4: separator_pages.append(index) print(f"分隔页索引:{index}") print(f"所有分隔页索引:{separator_pages}")
参数调整说明
- 若出现漏匹配,可适当调大
MATCH_THRESHOLD,或提高get_pixmap的dpi参数 - 若出现误匹配,可适当调小
MATCH_THRESHOLD,或调大SEARCH_SIZE保证搜索范围覆盖边角方块 - 二值化阈值
cv2.threshold的第二个参数可根据实际页面背景亮度调整,背景越亮数值越高
内容的提问来源于stack exchange,提问作者Andrea Di Stefano
相关产品推荐
相关产品推荐

