序言
最近在做一个关于PDF文档识别的项目,需要将PDF转化为图片再识别,这里使用了PyMuPDF库完成。这里记录一下使用过程。
安装
直接在终端中运行一下命令:
pip install PyMuPDF==1.18.4 -i https://pypi.tuna.tsinghua.edu.cn/simple/
指定版本1.18.4 ,最新版的下面代码有一些函数不支持。
安装完成后直接使用一下代码,更换一下pdf目录地址和输出保存的地址即可:
import os
import fitz # fitz就是pip install PyMuPDF
def pyMuPDF_fitz(pdfPath, imagePath):
global count
# print("imagePath=" + pdfPath)
pdfDoc = fitz.open(pdfPath)
for pg in range(pdfDoc.pageCount):
page = pdfDoc[pg]
rotate = int(0)
# 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
# 此处若是不做设置,默认图片大小为:792X612, dpi=96
zoom_x = 1.33333333 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 1.33333333
mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
try:
pix = page.getPixmap(matrix=mat, alpha=False)
except:
print("imagePath=" + pdfPath)
continue
if not os.path.exists(imagePath): # 判断存放图片的文件夹是否存在
os.makedirs(imagePath) # 若图片文件夹不存在就创建
pix.writePNG(imagePath + '/' + 'images_%s.png' % count) # 将图片写入指定的文件夹内
count +=1
if __name__ == "__main__":
# 1、PDF地址
pdfPath = r'G:\OCR合同材料\XOCR222'
# 2、需要储存图片的目录
imagePath = './imgs_B'
count = 0
for name in os.listdir(pdfPath):
pyMuPDF_fitz(os.path.join(pdfPath,name), imagePath)
提取的图片,以png形式保存:
提取PDF文件中的数字签名图片
有一些PDF上会存在一些数字签名的图片,例如一些印章等等。也可以将其提取出来:
# 安装第三方类库pymupdf:pip install pymupdf
import fitz
import time
import re
import os
# 使用正则表达式查找PDF中的图片
def pdf2pic(path, pic_path):
'''
# 从pdf中提取图片
:param path: pdf的路径
:param pic_path: 图片保存的路径
:return:
'''
t0 = time.perf_counter()
# 使用正则表达式来查找图片
checkXO = r"/Type(?= */XObject)"
checkIM = r"/Subtype(?= */Image)"
# 打印PDF的相关信息
# 打开pdf
doc = fitz.open(path)
# 图片计数
imgcount = 0
lenXREF = doc._getXrefLength()
# 打印PDF的信息
print("文件名:{}, 页数: {}, 对象: {}".format(path, len(doc), lenXREF - 1))
# 遍历PDF中的对象,遇到是图像才进行下一步,不然就continue
# 遍历每一个对象
for i in range(1, lenXREF):
# 定义对象字符串
text = doc._getXrefString(i)
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)
# 根据pdf的路径生成图片的名称
new_name = "{}.png".format(imgcount)
# 将图像存为png格式
# 如果pix.n<5,可以直接存为PNG
if pix.n < 5:
pix.writePNG(os.path.join(pic_path, new_name))
# 否则先转换CMYK
else:
pix0 = fitz.Pixmap(fitz.csRGB, pix)
pix0.writePNG(os.path.join(pic_path, new_name))
pix0 = None
# 释放资源
pix = None
t1 = time.perf_counter()
print("运行时间:{}s".format(t1 - t0))
print("提取了{}张图片".format(imgcount))
# 输入pdf路径,即可运行
if __name__=='__main__':
# pdf路径
path = r'imgs_B_pdf/查树良_15233565680_130323199507174618_承揽协议_普通_13.pdf'
pic_path = r'E:\PycharmProjects\Date_OCR\imgs_B'
# 创建保存图片的文件夹
if os.path.exists(pic_path):
print("文件夹已存在,请重新创建新文件夹!")
raise SystemExit
else:
os.mkdir(pic_path)
m = pdf2pic(path, pic_path)
从pdf中提取出的印章等数字签名信息:
删除PDF中的图片
因为有一些印章覆盖会影响识别效果,也可以把图片删除,从新保留为新的pdf,保留了原图层的文字。
# 安装第三方类库pymupdf:pip install pymupdf
import fitz
import time
import re
import os
# 使用正则表达式查找PDF中的图片
def pdf2pic(path):
'''
# 从pdf中提取图片
:param path: pdf的路径
:param pic_path: 图片保存的路径
:return:
'''
t0 = time.perf_counter()
# 使用正则表达式来查找图片
checkXO = r"/Type(?= */XObject)"
checkIM = r"/Subtype(?= */Image)"
# 打开pdf
doc = fitz.open(path)
lenXREF = doc._getXrefLength()
# 打印PDF的信息
print("文件名:{}, 页数: {}, 对象: {}".format(path, len(doc), lenXREF - 1))
# 遍历PDF中的对象,遇到是图像才进行下一步,不然就continue
# 遍历每一个对象
for i in range(1, lenXREF):
# 定义对象字符串
text = doc._getXrefString(i)
isXObject = re.search(checkXO, text)
# 使用正则表达式查看是否是图片
isImage = re.search(checkIM, text)
# 如果不是对象也不是图片,则continue
if not isXObject or not isImage:
continue
doc._deleteObject(i) # 删除图片
doc.save("test.pdf") # 重新保存
# 输入pdf路径,即可运行
if __name__=='__main__':
# pdf路径
path = r'E:\PycharmProjects\OCR_contract_date\test\咨询协议_普通_19.pdf'
m = pdf2pic(path)