You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:34:58