Python和OpenCV

6
有没有Python原生支持从PDF中提取图片或创建某种对象来包含PDF中的图像,以便使用OpenCV进行访问?我查看了一些脚本将PDF的图像转储到我的目录中,但我更希望访问PDF并将数据(即图像)转储为一些可以用OpenCV访问的对象。我自己的探索没有产生任何结果,因此我想问一下。另外,添加一个使用PyMuPDF的示例,基于@Ghilas BELHADJ的示例。
import fitz
import cv2
import numpy as np
from tkinter import Tk
from tkinter.filedialog import askopenfilename


class AccessPDF:

    def __init__(self):
        self.filepath = ""
        self.doc = None

    def openPDF(self):
        Tk().withdraw()
        self.filepath = askopenfilename()
        self.doc = fitz.open(self.filepath)

    def pixel2np(self,pix):
        im = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n)
        im = np.ascontiguousarray(im[..., [2, 1, 0]])  # rgb to bgr
        return im

    def displayKey(self):  
        pixobj = self.doc.getPagePixmap(0, alpha=False)
        im = self.pixel2np(pixobj)
        cv2.imwrite("testimg.png",im)
        cv2.imshow("Key" im)

2
搜索 pdf2image - Kinght 金
我遇到了那个模块,但是我无法让它工作,由于时间紧迫,我选择不再追求弄清楚如何使用它。如果在使用OpenCV和图像PDF时有帮助,我会重新考虑。因此,我想问:它会对我有帮助吗?您是否推荐使用它而不是OpenCV? - Rob
1
我理解您的意思是,您想要提取PDF中嵌入的图像,而不是将整个PDF页面呈现为图像。您有一些样本PDF文件吗? - Dan Mašek
是的,我有一份扫描文件的PDF,我想使用tkinter抓取我的文件,然后显示第一页,它本身只是一个单独的图像。 - Rob
2个回答

11

编辑:我已根据@Dan Mašek的评论对代码进行了修改

您可以使用PyMuPDFNumpy实现此操作(在不编写中间对象到磁盘的情况下,加载 PDF 中嵌入的图像到 OpenCV)。

在这个例子中,我正在使用这个 pdf 文件

import fitz
import cv2
import numpy as np


def pix2np(pix):
    im = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n)
    im = np.ascontiguousarray(im[..., [2, 1, 0]])  # rgb to bgr
    return im


doc = fitz.open('NGM_2018_Media_Kit.pdf')

# entire page
# pix = doc.getPagePixmap(0, alpha=False)

# first page , 5th image, xref element
pix = fitz.Pixmap(doc, doc.getPageImageList(0)[4][0])  
im = pix2np(pix)

cv2.putText(im, 'Azul fellawen', (100, 100),
            cv2.FONT_HERSHEY_SIMPLEX, 1.,
            (18, 156, 243), 2, cv2.LINE_AA)
cv2.imwrite('sample_0.png', im)

enter image description here


1
很好。谢谢你指引我使用[Py]MuPDF,看起来它是解析和处理PDF文件最好的库。(在你回答之前,我尝试过PyPDF2,但那需要很多代码,并且获取最新版本的库似乎已经被放弃了 :( -- 你的更加优雅 :) ) - Dan Mašek
哇,这比我最初想的要更有帮助。现在检查一下openCV,我只需要使用cv2.imshow(im)对吗? - Rob
1
几乎就是这样 cv2.imshow('some_title',im); cv2.waitKey(0) - Ghilas BELHADJ
好的,谢谢。请问一下,我不熟悉numpy库,pix2np这段代码是做什么用的?我猜它把PyMuPDF的Pixmap对象转换成了什么东西? - Rob
1
pix2npPixmap对象转换为numpy.ndarray,这是cv2用于处理图像的默认格式。 - Ghilas BELHADJ

2
我从包含图像和文本的pdf中提取了图像。
您可以使用pix.writePNG()保存图像,或者使用cv2.imshow()显示它,哪个更适合您。
import fitz    #pymupdf
from cv2 import cv2
import numpy as np

def pix2np(pix):
    im = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, pix.n)
    im = np.ascontiguousarray(im[..., [2, 1, 0]])  # rgb to bgr
    return im

def convertPdf(filename):  
    doc = fitz.open(filename)
    #count = 0
    for i in range(len(doc)):
        for img in doc.getPageImageList(i):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)

            #if pix.n < 5:       # this is GRAY or RGB
            # To save it to the disk
            #pix.writePNG(f"p{count}.png")

            im = pix2np(pix)
            cv2.imshow("image",im)
            cv2.waitKey(0)
            #count += 1
            pix = None

if __name__ == "__main__":
    filename = "sample.pdf"
    convertPdf(filename)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接