PDF转图片:ImageMagick与pdf2image的使用

在进行计算机视觉任务时,经常需要将PDF文件转换成图片格式,如JPEG或PNG。本文将探讨使用shell脚本或Python代码将PDF页面光栅化的方法。选择合适的分辨率对于提高训练和推理速度至关重要,应选择尽可能低的分辨率以减小文件大小,同时不影响准确性。命令行工具ImageMagickPython库pdf2image允许指定每英寸点数(DPI),直接调整用于检测特征的图像质量。

选择合适的分辨率

在将PDF转换为图片时,选择最佳分辨率可以提高训练和推理速度。理想情况下,选择尽可能低的分辨率以减少文件大小,同时不影响准确性。例如,对于边界框检测(例如定位页面上的文本块或数学公式),150-300 DPI通常就足够了。对于分类整个页面(例如识别包含图表或图形的整个页面),50-150 DPI的较低分辨率通常就足够了。

使用ImageMagick将PDF转换为图片

ImageMagick是一个强大的命令行图像处理工具。以下是如何在shell脚本中使用它将目录中的PDF转换为图片的方法:

#!/bin/bash # 将当前目录中的所有PDF转换为PNG图片 for file in *.pdf; do magick -density 300 "$file" "${file%.pdf}.png" done

以上配置值的信息如下:

  • Density: 设置渲染的DPI。在PDF转换时必须指定。较高的值(例如300)提供更好的质量但文件大小更大。
  • Resize: 调整输出图像的大小。当需要特定大小的图像或在高密度渲染后减小文件大小时使用。
  • Colorspace: 将图像转换为特定的色彩空间。当需要灰度图像或确保颜色一致性时使用。
  • Depth: 设置输出图像的位深度。用于减小文件大小或匹配CV模型的特定要求。
  • Background Color: 设置透明区域的背景颜色。用于将带有透明度的PDF转换为没有alpha通道的格式。
  • Merge Layers: 合并所有图层到白色背景上。用于处理多层PDF或当想要确保白色背景时。
  • Quality: 设置有损格式的输出图像质量。这个标志不影响PNG文件,PNG是无损的。用于JPEG输出。

结合选项的例子:

#!/bin/bash for file in *.pdf; do magick -density 150 -resize 1000x -colorspace GRAY -depth 8 -background white -flatten "$file" "${file%.pdf}.png" done

此命令将执行以下操作:

  • 以150 DPI渲染PDF
  • 调整为1000px宽度(保持纵横比)
  • 转换为灰度
  • 设置8位色深
  • 确保白色背景
  • 输出为PNG(无损)

对于JPEG输出,可能会使用:

#!/bin/bash for file in *.pdf; do magick -density 150 -resize 1000x -colorspace sRGB -quality 90 "$file" "${file%.pdf}.jpg" done

使用pdf2image将PDF转换为图片

一旦准备好了训练集,通常需要为推理执行相同的任务:用户将有PDF文档,而训练模型需要光栅图像作为输入。pdf2image是一个Python库,用于处理PDF文件,与Roboflow的推理SDK配合得很好。需要使用选择的包管理器安装该包:

pip install pdf2image

以下是一个简单的脚本,它将当前工作目录中的所有PDF文件转换为每个页面的单独PNG文件:

import os from pdf2image import convert_from_path def convert_pdfs_to_pngs(directory, dpi=150): pdf_files = [f for f in os.listdir(directory) if f.lower().endswith('.pdf')] for pdf_file in pdf_files: pdf_path = os.path.join(directory, pdf_file) pdf_name = os.path.splitext(pdf_file)[0] pages = convert_from_path(pdf_path, dpi=dpi) for page_num, page in enumerate(pages, start=1): image_name = f"{pdf_name}_page_{page_num:03d}.png" image_path = os.path.join(directory, image_name) page.save(image_path, 'PNG') print(f"Saved: {image_name}") if __name__ == "__main__": current_directory = os.getcwd() convert_pdfs_to_pngs(current_directory)

此脚本适用于许多用例,但请注意,转换的吞吐量可能会受到输入/输出操作速度的限制。

使用asyncio提高吞吐量

对于HTTP请求处理程序中的PDF处理或更大规模的批处理过程,可以利用asyncio来优化IO绑定操作。以下是一个使用pdf2image和asyncio提高吞吐量的例子:

#!/usr/bin/env python import os import asyncio from pdf2image import convert_from_path from concurrent.futures import ProcessPoolExecutor async def convert_pdf_to_pngs(pdf_path, dpi=150): pdf_name = os.path.splitext(os.path.basename(pdf_path))[0] loop = asyncio.get_event_loop() with ProcessPoolExecutor() as pool: pages = await loop.run_in_executor(pool, convert_from_path, pdf_path, dpi) tasks = [] for page_num, page in enumerate(pages, start=1): image_name = f"{pdf_name}_page_{page_num:03d}.png" image_path = os.path.join(os.path.dirname(pdf_path), image_name) task = asyncio.create_task(save_image(page, image_path)) tasks.append(task) await asyncio.gather(*tasks) print(f"Converted: {pdf_name}") async def save_image(page, image_path): loop = asyncio.get_event_loop() await loop.run_in_executor(None, page.save, image_path, 'PNG') async def convert_pdfs_to_pngs(directory, dpi=150): pdf_files = [f for f in os.listdir(directory) if f.lower().endswith('.pdf')] tasks = [] for pdf_file in pdf_files: pdf_path = os.path.join(directory, pdf_file) task = asyncio.create_task(convert_pdf_to_pngs(pdf_path, dpi)) tasks.append(task) await asyncio.gather(*tasks) if __name__ == "__main__": current_directory = os.getcwd() asyncio.run(convert_pdfs_to_pngs(current_directory))

这种基于asyncio的方法显著提高了性能,通过并发处理多个PDF和页面,非常适合服务器进程和更大的数据集。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485