Python利用fitz库提取pdf中的图片(针对多种类型pdf)


参考: https://blog.csdn.net/qq_15969343/article/details/81673302

一. 安装fitz

安装:需要安装fitz和PyMuPDF,否则会报如下错误:ModuleNotFoundError: No module named ‘frontend’

pip install fitz PyMuPDF

二. pdf文件格式问题

2.1 pdf文件存在多种格式

pdf文件的格式有好几种,用Adobe Acroba打开比较正常的论文,如下所示:在这里插入图片描述

这种类型的pdf文件可以比较正常地提取里面的图片。

还有这种类型的,如下图所示:
在这里插入图片描述

2.2 分析问题

这种类型pdf文件,提取图片的时候往往会将整个页面当作图片提取出来。

  • 利用fitz库读取文件
import fitz
file = 'test.pdf'
doc = fitz.open(file)
  • 获取doc的对象数
nums = doc._getXrefLength()
  • 遍历每一个对象,定义对象的字符串并打印出来看看是啥玩意儿
for i in range(1, nums):
	# 定义对象字符串
	text = doc._getXrefString(i)
	print(i, text)
	

部分结果如下图所示:
在这里插入图片描述

  • text是一个字符串,如果是图像,它会包含"/Subtype /Image"和"/Type /XObject"。所以,可以用来匹配图像。

但是,对于2.1节第二种pdf文件,text如下所示:
在这里插入图片描述

  • 虽然提取到图片,但是这其实是把整张页面作为图片提取出来了,我们并不需要页面图片。

  • 通过观察,可以看到,对于这种页面图片,它的宽和高分别是2550和3300,所以可以加入条件去筛选掉这种对象。

  • 同时还有可能提取到类似图标的图像,这种类型的对象text里包含"thumbnail"字符串,也可以筛选掉。

for i in range(1, nums):
    # 定义对象字符串
    text = doc._getXrefString(i)
    print(i, text)
    if ('Width 2550' in text) and ('Height 3300' in text) or ('thumbnail' in text):
        continue
        

接下来就是保存图像了,整体代码见第三部分。

三. 代码

import fitz
import re
import os


def pdf2pic(path, pic_path):
    '''
    # 从pdf中提取图片
    :param path: pdf的路径
    :param pic_path: 图片保存的路径
    :return:
    '''
    # 打开pdf
    doc = fitz.open(path)
    nums = doc._getXrefLength()
    imgcount = 0 # 图像计数
   
    # 遍历每一个对象
    for i in range(1, nums):
        text = doc._getXrefString(i)
        # print(i, text)
        # 过滤无用图片
        if ('Width 2550' in text) and ('Height 3300' in text) or ('thumbnail' in text):
            continue
            
	    # 使用正则表达式来查找图片
	    checkXO = r"/Type(?= */XObject)"
	    checkIM = r"/Subtype(?= */Image)"
	    
        isXObject = re.search(checkXO, text)
        isImage = re.search(checkIM, text)
        
        # 不符合条件, continue
        if not isXObject or not isImage:
            continue
		imgcount += 1

        # 生成图像
        pix = fitz.Pixmap(doc, i)
		
		# 保存图像名
        img_name = "img{}.png".format(imgcount)
        
        # 如果pix.n<5,可以直接存为PNG
        if pix.n < 5:
            try:
                pix.writePNG(os.path.join(pic_path, img_name))
                pix = None
            except:
                pix0 = fitz.Pixmap(fitz.csRGB, pix)
                pix0.writePNG(os.path.join(pic_path, img_name))
                pix0 = None

if __name__ == '__main__':
    # pdf路径
    path = r'test.pdf'
	
	# 保存的图片路径
    pic_path = 'img'
    
    pdf2pic(path, pic_path)

其他问题:可能提取到的图片尺寸非常小,也可以通过正则表达式提取图像尺寸,设置条件,筛选掉太小的图片。

结束。

  • 18
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值