使用 Python 去除 PDF 水印:一步一步的实现(二)

您所在的位置:网站首页 怎么去除pdf上的水印文字 使用 Python 去除 PDF 水印:一步一步的实现(二)

使用 Python 去除 PDF 水印:一步一步的实现(二)

2024-07-14 07:14| 来源: 网络整理| 查看: 265

前言

在日常工作中,我们经常会遇到带有水印的 PDF 文件。水印可能会影响文档的可读性或者在打印时造成不便。为了自动化地去除 PDF 文件中的水印,我们可以使用 Python 及其强大的库,如 PyMuPDF、Pillow 和 OpenCV。本文将详细介绍如何实现这一过程。

所需库

首先,我们需要安装以下 Python 库:

PyMuPDF:用于处理 PDF 文件。Pillow:用于图像处理。OpenCV:用于图像操作。

使用以下命令安装这些库:

pip install pymupdf pillow opencv-python-headless 实现步骤 导入必要的库

我们首先导入所需的库:

import fitz # PyMuPDF from PIL import Image import numpy as np import cv2 import os import concurrent.futures 定义去除水印的函数

接下来,我们定义一个函数来去除图像中的水印。该函数利用颜色范围创建掩码,并将掩码区域设置为白色:

def remove_watermark(image, lower_bound, upper_bound): """去除水印""" # 将 PIL 图像转换为 OpenCV 格式 open_cv_image = np.array(image) open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR) # 创建掩码,查找在指定颜色范围内的像素 mask = cv2.inRange(open_cv_image, lower_bound, upper_bound) # 使用膨胀和侵蚀操作优化掩码 kernel = np.ones((3, 3), np.uint8) mask = cv2.dilate(mask, kernel, iterations=1) mask = cv2.erode(mask, kernel, iterations=1) # 将掩码范围内的像素设为白色 open_cv_image[mask != 0] = [255, 255, 255] # 将图像转换回 PIL 格式 return Image.fromarray(cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2RGB)) 处理单页 PDF 的函数

我们需要一个函数来处理 PDF 文件的每一页,将其转换为图像,去除水印后保存为 PNG 文件:

def process_page(pdf_path, page_num, output_folder, mat, lower_bound, upper_bound): """处理单页""" try: # 打开 PDF 文件并加载特定页 pdf = fitz.open(pdf_path) page = pdf.load_page(page_num) pixmap = page.get_pixmap(matrix=mat) img = Image.frombytes("RGB", [pixmap.width, pixmap.height], pixmap.samples) # 调用 remove_watermark 函数去除水印 img = remove_watermark(img, lower_bound, upper_bound) # 将处理后的图像保存为 PNG 文件 img_path = os.path.join(output_folder, f"{page_num}.png") img.save(img_path, format="PNG") print(f"第{page_num}页水印去除完成") pdf.close() except fitz.FileDataError: print(f"无法读取第{page_num}页的数据。") except fitz.PDFPageError: print(f"第{page_num}页无法加载。") except Exception as e: print(f"处理第{page_num}页时出错: {e}") 主函数

主函数 remove_pdf 负责管理整个 PDF 的处理过程,包括创建输出文件夹、并行处理每一页以及将处理后的图像合并回 PDF:

def remove_pdf(pdf_file, output_folder, output_pdf_path, dpi=1800, lower_bound=(168, 168, 168), upper_bound=(172, 172, 172)): """去除 PDF 水印的主函数""" if not os.path.exists(pdf_file): print(f"文件 {pdf_file} 未找到。") return if not pdf_file.lower().endswith('.pdf'): print(f"文件 {pdf_file} 不是 PDF 文件。") return if not os.path.exists(output_folder): os.makedirs(output_folder) zoom = dpi / 72 mat = fitz.Matrix(zoom, zoom) try: pdf = fitz.open(pdf_file) total_pages = len(pdf) pdf.close() with concurrent.futures.ThreadPoolExecutor() as executor: futures = [ executor.submit(process_page, pdf_file, page_num, output_folder, mat, lower_bound, upper_bound) for page_num in range(total_pages) ] for future in concurrent.futures.as_completed(futures): try: future.result() except Exception as e: print(f"处理过程中发生错误: {e}") image_files = [os.path.join(output_folder, f"{page_num}.png") for page_num in range(total_pages)] image_list = [Image.open(img_file).convert("RGB") for img_file in image_files] if image_list: image_list[0].save(output_pdf_path, save_all=True, append_images=image_list[1:]) print(f"处理后的PDF文件保存为: {output_pdf_path}") else: print("没有处理好的图片可以合并为PDF。") except FileNotFoundError: print(f"文件 {pdf_file} 未找到。") except fitz.FileDataError: print(f"无法读取文件数据 {pdf_file}。") except Exception as e: print(f"处理PDF文件时出错: {e}") 主程序入口

在主程序中,我们从用户获取输入路径、输出路径以及水印颜色的上下界,然后调用 remove_pdf 函数:

if __name__ == "__main__": pdf_path = input("请输入 PDF 地址:") output_path = input("请输入保存处理后的图片的文件夹地址:") output_pdf_path = input("请输入保存处理后的 PDF 地址:") lower_bound = tuple(map(int, input("请输入水印颜色的下界(例如:168,168,168):").split(','))) upper_bound = tuple(map(int, input("请输入水印颜色的上界(例如:172,172,172):").split(','))) remove_pdf(pdf_path, output_path, output_pdf_path, lower_bound=lower_bound, upper_bound=upper_bound) 代码解析

以下是本文中使用的完整代码,添加了中文注释,帮助理解每个步骤的功能:

import fitz # PyMuPDF from PIL import Image import numpy as np import cv2 import os import concurrent.futures def remove_watermark(image, lower_bound, upper_bound): """去除水印""" # 将 PIL 图像转换为 OpenCV 格式 open_cv_image = np.array(image) open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR) # 创建掩码,查找在指定颜色范围内的像素 mask = cv2.inRange(open_cv_image, lower_bound, upper_bound) # 使用膨胀和侵蚀操作优化掩码 kernel = np.ones((3, 3), np.uint8) mask = cv2.dilate(mask, kernel, iterations=1) mask = cv2.erode(mask, kernel, iterations=1) # 将掩码范围内的像素设为白色 open_cv_image[mask != 0] = [255, 255, 255] # 将图像转换回 PIL 格式 return Image.fromarray(cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2RGB)) def process_page(pdf_path, page_num, output_folder, mat, lower_bound, upper_bound): """处理单页""" try: # 打开 PDF 文件并加载特定页 pdf = fitz.open(pdf_path) page = pdf.load_page(page_num) pixmap = page.get_pixmap(matrix=mat) img = Image.frombytes("RGB", [pixmap.width, pixmap.height], pixmap.samples) # 调用 remove_watermark 函数去除水印 img = remove_watermark(img, lower_bound, upper_bound) # 将处理后的图像保存为 PNG 文件 img_path = os.path.join(output_folder, f"{page_num}.png") img.save(img_path, format="PNG") print(f"第{page_num}页水印去除完成") pdf.close() except fitz.FileDataError: print(f"无法读取第{page_num}页的数据。") except fitz.PDFPageError: print(f"第{page_num}页无法加载。") except Exception as e: print(f"处理第{page_num}页时出错: {e}") def remove_pdf(pdf_file, output_folder, output_pdf_path, dpi=1800, lower_bound=(168, 168, 168), upper_bound=(172, 172, 172)): """去除 PDF 水印的主函数""" if not os.path.exists(pdf_file): print(f"文件 {pdf_file} 未找到。") return if not pdf_file.lower().endswith('.pdf'): print(f"文件 {pdf_file} 不是 PDF 文件。") return if not os.path.exists(output_folder): os.makedirs(output_folder) zoom = dpi / 72 mat = fitz.Matrix(zoom, zoom) try: pdf = fitz.open(pdf_file) total_pages = len(pdf) pdf.close() with concurrent.futures.ThreadPoolExecutor() as executor: futures = [ executor.submit(process_page, pdf_file, page_num, output_folder, mat, lower_bound, upper_bound) for page_num in range(total_pages) ] for future in concurrent.futures.as_completed(futures): try: future.result() except Exception as e: print(f"处理过程中发生错误: {e}") image_files = [os.path.join(output_folder, f"{page_num}.png") for page_num in range(total_pages)] image_list = [Image.open(img_file).convert("RGB") for img_file in image_files] if image_list: image_list[0].save(output_pdf_path, save_all=True, append_images=image_list[1:]) print(f"处理后的PDF文件保存为: {output_pdf_path}") else: print("没有处理好的图片可以合并为PDF。") except FileNotFoundError: print(f"文件 {pdf_file} 未找到。") except fitz.FileDataError: print(f"无法读取文件数据 {pdf_file}。") except Exception as e: print(f"处理PDF文件时出错: {e}") if __name__ == "__main__": pdf_path = input("请输入 PDF 地址:") output_path = input("请输入保存处理后的图片的文件夹地址:") output_pdf_path = input("请输入保存处理后的 PDF 地址:") lower_bound = tuple(map(int, input("请输入水印颜色的下界(例如:168,168,168):").split(','))) upper_bound = tuple(map(int, input("请输入水印颜色的上界(例如:172,172,172):").split(','))) remove_pdf(pdf_path, output_path, output_pdf_path, lower_bound=lower_bound, upper_bound=upper_bound)

通过上面的代码,我们可以实现自动去除 PDF 水印的功能。如果你在实现过程中遇到问题或有更好的改进建议,欢迎在评论区分享。让我们一起学习进步!

对比前后 去除前

去除后

总结

本文介绍了如何使用 Python 去除 PDF 文件中的水印。我们通过结合使用 PyMuPDF、Pillow 和 OpenCV 库,实现了从 PDF 提取页面、处理图像并去除水印的完整流程。该方法自动化程度高,适用于批量处理带有水印的 PDF 文件。希望这篇文章能对你有所帮助!

如果你在实现过程中遇到问题或有更好的改进建议,欢迎在评论区分享。让我们一起学习进步!

 参考资料 PyMuPDF 官方文档:链接OpenCV 官方文档:链接Python 官方文档:链接


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3