Python识别含图片PDF页面异常:小样本正常大PDF全页误判求助
问题
我拿到一份1535页的辖区街道文档合集PDF,想通过提取含图片的首页(摘要页)缩小数据处理范围。用PyMuPDF(fitz)写了检测含图片页面的代码,在自制的20页测试PDF里运行正常,但真实PDF所有页面都被判定为含图片。
测试代码:
import fitz pdf = fitz.Document("sample2.pdf") page_images = [] for i in range(len(pdf)): images = pdf.get_page_images(i) hasimage = False if len(images) == 0 else True # print(f"{i}: {hasimage}: {images}") if hasimage: page_images.append(i) print(f"page_has_image: {page_images}") print(f"total_page_has_image: {len(page_images)}") print(f"total_pages: {len(pdf)}")
测试PDF结果(符合预期):
page_has_image: [0, 8, 17] total_page_has_image: 3 total_pages: 20
真实PDF异常结果:
page_has_image: [0, 1, 2, 3, ..., 1532, 1533, 1534] total_page_has_image: 1535 total_pages: 1535
需要准确识别真实PDF中含图片的页面列表。
原因分析
真实PDF大概率包含大量视觉上不易察觉的图片元素:
- 页眉/页脚的小logo、分隔线
- 隐形的背景图或水印
- PDF生成过程中产生的冗余光栅元素
PyMuPDF的get_page_images会返回所有嵌入的图片资源,不管尺寸大小或可见性,导致全页被误判。
解决方法
1. 过滤小尺寸图片
通过设置像素尺寸阈值,只保留真正的大尺寸摘要图,过滤掉小图标:
import fitz pdf = fitz.Document("sample2.pdf") page_images = [] # 根据实际摘要图大小调整阈值,示例为100x100像素 MIN_IMG_WIDTH = 100 MIN_IMG_HEIGHT = 100 for page_idx in range(len(pdf)): has_valid_img = False # 获取当前页面所有图片引用 img_refs = pdf.get_page_images(page_idx) for img in img_refs: xref = img[0] # 加载图片获取尺寸 pix = fitz.Pixmap(pdf, xref) if pix.width >= MIN_IMG_WIDTH and pix.height >= MIN_IMG_HEIGHT: has_valid_img = True pix = None # 释放内存 break if has_valid_img: page_images.append(page_idx) print(f"page_has_image: {page_images}") print(f"total_page_has_image: {len(page_images)}") print(f"total_pages: {len(pdf)}")
2. 结合文本特征双重验证
因为目标是街道文档的首页(摘要页),这类页面通常有特定文本特征(比如含“街道”“摘要”关键词,或文本量远少于正文页),可以结合文本检测提高准确性:
import fitz pdf = fitz.Document("sample2.pdf") page_images = [] MIN_IMG_WIDTH = 100 MIN_IMG_HEIGHT = 100 # 根据文档内容调整关键词 TARGET_KEYWORDS = ["街道", "概况", "摘要"] # 首页文本量通常较少,设置长度阈值 MAX_TEXT_LENGTH = 500 for page_idx in range(len(pdf)): page = pdf[page_idx] # 检查大尺寸图片 has_valid_img = False img_refs = page.get_images() for img in img_refs: xref = img[0] pix = fitz.Pixmap(pdf, xref) if pix.width >= MIN_IMG_WIDTH and pix.height >= MIN_IMG_HEIGHT: has_valid_img = True pix = None break # 检查文本特征 page_text = page.get_text().strip() has_target_keyword = any(kw in page_text for kw in TARGET_KEYWORDS) is_short_text = len(page_text) < MAX_TEXT_LENGTH # 满足图片+任一文本特征则判定为目标页 if has_valid_img and (has_target_keyword or is_short_text): page_images.append(page_idx) print(f"page_has_image: {page_images}")
3. 换用pdfplumber工具
如果PyMuPDF的检测逻辑仍有问题,可以尝试用pdfplumber,它对PDF元素的识别更精细:
import pdfplumber pdf = pdfplumber.open("sample2.pdf") page_images = [] MIN_IMG_WIDTH = 100 MIN_IMG_HEIGHT = 100 for page_idx, page in enumerate(pdf.pages): has_valid_img = False # pdfplumber直接返回图片的尺寸属性 for img in page.images: if img["width"] >= MIN_IMG_WIDTH and img["height"] >= MIN_IMG_HEIGHT: has_valid_img = True break if has_valid_img: page_images.append(page_idx) print(f"page_has_image: {page_images}") pdf.close()
内容的提问来源于stack exchange,提问作者Alfian Khusnul
相关产品推荐
相关产品推荐

