【问题标题】:Feed all images from PDF file to OpenCV将 PDF 文件中的所有图像馈送到 OpenCV
【发布时间】:2022-01-05 03:23:29
【问题描述】:

目标:将文档扫描仪上的论文扫描成一个 PDF 文件,然后通过 OpenCV 进行处理。

预期的结果是这样的程序:

  1. 从 PDF 文件中提取一个图像作为二进制文件。
  2. 将其转换为 OpenCV 的Mat。
  3. 像image processing、line detection 等一样对待垫子。
  4. 重复下一张图片。

【问题讨论】:

  • 您可能已经注意到了反对票。也许这个问题的措辞有点不同。我认为可以“提出问题”然后自己回答以构建规范的问题+答案,过去类似的问题措辞不佳或没有得到有用的答案。我不知道这种情况需要什么。

标签: python image opencv pdf mupdf


【解决方案1】:

程序使用PyMuPDF包从PDF文件中提取图像:

  1. 以内容管理器的身份打开 PDF 文件: with fitz.Document(file) as doc。
  2. 通过Set Comprehensions获取一组图像XREFs。更多细节在注释中。
  3. 循环遍历一组外部参照。
  4. 在每次迭代中:
  5. Extract 包含一张带有image_dict = doc.extract_image(xref) 的图像的字典。另一种方法是create a Pixmap。
  6. 现在“image”键保存图像数据,可用作图像文件内容,“bpc”键保存the number of bits per component。
  7. 每个组件的位数用于计算 NumPy 数组元素的类型为np.dtype(f'u{image_dict["bpc"] // 8}'),其中f'u{image_dict["bpc"] // 8}' 是Array-protocol type strings,如 'u1'、'u2' 这是 NumPy 数据类型为一字节和两字节无符号整数。请参阅注释。
  8. 通过平均 NumPy 函数 frombuffer 创建 NumPy 数组,类型如上所述。
  9. OpenCV 函数imdecode 将数组转换为OpenCV 的Mat。
  10. 通过 OpenCV 的 imshow() 在屏幕上显示 Mat。
  11. 转到下一张图片。
import fitz
import numpy as np
import cv2

# file path you want to extract images from
file = "test.pdf"

with fitz.Document(file) as doc:
    for xref in {xref[0] for page in doc for xref in page.get_images(False) if xref[1] == 0}:
        # dictionary with image
        image_dict = doc.extract_image(xref)
        # image as OpenCV's Mat
        i = cv2.imdecode(np.frombuffer(image_dict["image"],
                                       np.dtype(f'u{image_dict["bpc"] // 8}')
                                       ),
                         cv2.IMREAD_GRAYSCALE)
        cv2.imshow("OpenCV", i)
        cv2.waitKey(0)

注意事项:

  1. Set Comprehensions 包含两个循环和一个条件。第一个循环for page in doc 遍历PDF 文档中的页面,第二个循环for xref in page.get_images(False) 遍历图像'XREF located on the page。条件 if xref[1] == 0 切断“pseudo-images”(“模板蒙版”),其特殊目的是定义其他图像的透明度。是的,alpha-channel(透明度)被破坏。很可能在扫描纸的情况下,图像不包含“模板蒙版”,所以它可能是矫枉过正。
  2. 可能使用该集合是多余的,因为源自文档扫描仪的 PDF 文件仅包含唯一图像,但理论上可以引用多页中的一个图像。
  3. 通过平均“bpc”来确定 NumPy 数据类型是程序中非常危险的部分。如果每个组件的位数小于 8,则会声明零字节数据类型,因此我认为程序会出错。我认为在大多数情况下使用数据类型 numpy.uint8 就足够了。

【讨论】:

    猜你喜欢
    • 2016-11-17
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 2021-12-28
    相关资源
    最近更新 更多