Python实现为PDF大文件批量去除水印
作者:力语 发布时间:2023-04-14 19:59:04
导入
在阅读过程中如果遇到一些带有水印的资料是比较烦心的,如下图所示,水印以及类似的内容会影响我们的阅读体验,而市面上去水印的功能有多要收费且很不方便,那么,如何通过Python来对这类图片水印进行去除呢?
适用场景:本教程适合批量去除文件量较大的PDF文档内的图片水印。
使用软件:Python
;
需安装第三方库:PIL
,fitz
,pymupdf
pip install PIL
pip install fitz
pip install pymupdf
不说废话,先把代码贴在前面。
from PIL import Image
import fitz
import os
def replace_color(img_path):
new_color = (255, 255, 255, 255)
for filename in os.listdir(img_path):
image = Image.open(os.path.join(img_path, filename))
new_pixels = [new_color if pixel == (220,220,220) else pixel for pixel in image.getdata()]
new_image = Image.new(image.mode, image.size)
new_image.putdata(new_pixels)
new_image.save(os.path.join(img_path, filename))
def convert_pdf_to_images(img_path,doc):
for i, page in enumerate(doc):
pix = page.getPixmap(matrix=fitz.Matrix(2, 2))
img_output_path = os.path.join(img_path, f"{i+1:04d}.jpg")
pix.writePNG(img_output_path)
def creat_file(img_path):
if not os.path.exists(img_path):
os.makedirs(img_path)
else:
for root, dirs, files in os.walk(img_path, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
def convert_images_to_pdf(img_path, output_path):
image_list = []
for filename in os.listdir(img_path):
image_list.append(Image.open(os.path.join(img_path, filename)))
image_list[0].save(output_path, save_all=True, append_images=image_list[1:])
def delete_watermark(file_path):
folder_path = os.path.dirname(file_path)
file_name = os.path.basename(file_path)
output_path = os.path.join(folder_path, 'new_'+file_name)
img_path = os.path.join(folder_path, f"img_{os.path.splitext(file_name)[0]}")
creat_file(img_path)
convert_pdf_to_images(img_path, doc=fitz.open(file_path))
replace_color(img_path)
convert_images_to_pdf(img_path, output_path)
if __name__ == "__main__":
delete_watermark('E:\...\example.pdf')
正文
为了不影响阅读体验,一般水印都是由灰色或红色等与正文内容明显不同的颜色构成的。因此,要去除此类水印只需要判断出它是哪种颜色,然后将此颜色替换为背景色即可。
以上面图片中的水印为例,我们通过对水印部分进行取色可以看到,水印的 RGB 值为 (128, 130, 133),背景色为白色( RGB为 (255, 255, 255) ),那么我们只需要将 RGB 值为 (128, 130, 133) 的像素值替换为 (255, 255, 255) 即可实现图像水印的去除。
博主使用的取色工具为 Snipaste,也可以用 PS 等其它工具对水印取色。
首先需要将 PDF 中的一页信息提取出来,我们使用的是 fitz 库。
# 将 PDF 文件分解为图片
def convert_pdf_to_images(img_path,doc)
for i, page in enumerate(doc):
pix = page.getPixmap(matrix=fitz.Matrix(2, 2))
img_output_path = os.path.join(img_path, f"{i+1}.jpg")
pix.writePNG(img_output_path)
然后再对图片中的特定颜色进行替换
def replace_color(pixel, old_color, new_color):
if pixel in old_color:
return new_color
else:
return pixel
old_color = (128, 130, 133)
new_color = (255, 255, 255)
# 遍历输入文件夹中的所有.jpg文件并进行颜色替换
for filename in os.listdir(input_folder):
if filename.endswith('.jpg') or filename.endswith('.png'):
# 打开图片并获取像素数据
image = Image.open(os.path.join(input_folder, filename))
pixels = list(image.getdata())
# 遍历像素数据并进行颜色替换
new_pixels = [replace_color(pixel, old_color, new_color) for pixel in pixels]
# 将修改后的像素数据保存到新文件夹中
new_image = Image.new(image.mode, image.size)
new_image.putdata(new_pixels)
new_image.save(os.path.join(output_folder, filename))
最后再将图片拼接起来则得到去水印后的 PDF
def convert_images_to_pdf(img_path, output_path):
image_list = []
for filename in sorted(os.listdir(img_path), key=lambda x: int(x.split('.')[0])):
image_list.append(Image.open(os.path.join(img_path, filename)))
image_list[0].save(output_path, save_all=True, append_images=image_list[1:])
将以上三个步骤合并,即可得到我们的最终代码
from PIL import Image
import fitz
import os
def replace_color(img_path):
new_color = (255, 255, 255, 255)
for filename in os.listdir(img_path):
image = Image.open(os.path.join(img_path, filename))
new_pixels = [new_color if pixel == (220,220,220) else pixel for pixel in image.getdata()]
new_image = Image.new(image.mode, image.size)
new_image.putdata(new_pixels)
new_image.save(os.path.join(img_path, filename))
def convert_pdf_to_images(img_path,doc):
for i, page in enumerate(doc):
pix = page.getPixmap(matrix=fitz.Matrix(2, 2))
img_output_path = os.path.join(img_path, f"{i+1:04d}.jpg")
pix.writePNG(img_output_path)
def creat_file(img_path):
if not os.path.exists(img_path):
os.makedirs(img_path)
else:
for root, dirs, files in os.walk(img_path, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
def convert_images_to_pdf(img_path, output_path):
image_list = []
for filename in os.listdir(img_path):
image_list.append(Image.open(os.path.join(img_path, filename)))
image_list[0].save(output_path, save_all=True, append_images=image_list[1:])
def delete_watermark(file_path):
folder_path = os.path.dirname(file_path)
file_name = os.path.basename(file_path)
output_path = os.path.join(folder_path, 'new_'+file_name)
img_path = os.path.join(folder_path, f"img_{os.path.splitext(file_name)[0]}")
creat_file(img_path)
convert_pdf_to_images(img_path, doc=fitz.open(file_path))
replace_color(img_path)
convert_images_to_pdf(img_path, output_path)
if __name__ == "__main__":
delete_watermark('E:\...\example.pdf')
只需要对水印和背景进行取色,然后更改相应代码即可实现全自动 Python 去水印功能。
由于水印颜色并不总是某一个RGB值,而是一个范围,所以也可以使用 218<pixel[0]<244 and 218<pixel[1]<244 and 218<pixel[2]<244:
替换 pixel == (220,220,220)
。
上述程序在运行过程中会根据文件名,产生一个"img_[文件名]"文件夹用于存放图片,以及产生一个去除水印后的"new_[文件名].pdf"文件。
若不需要查看单张图片的效果,也可以直接运行如下代码,在等待一段时间后会直接生成去除水印后的 PDF。
import fitz
with fitz.open('example.pdf') as doc:
for page in doc:
pix = page.getPixmap(matrix=fitz.Matrix(2, 2))
pix = pix.applyFunction(lambda r,g,b: (255, 255, 255) if (r,g,b) == (220, 220, 220) else (r,g,b))
new_page = fitz.new_page(width=pix.width, height=pix.height)
new_page.insert_image(fitz.Rect(0, 0, pix.width, pix.height), pixmap=pix)
new_doc.save("new_example.pdf")
不过该方法生成的 PDF 文件会远大于原始文件,若是介意这点可继续用前一种方法。关于为什么该方法生成的文件变大这点,笔者目前也不清楚,如果有知道原因的朋友可以留下评论。
对于特别大的文件,可能导致 MemoryError,这时可以尝试先将图片分组,每组图片生成 pdf 文件后,再将多个 pdf 文件合并。
from PyPDF2 import PdfFileMerger
def convert_images_to_pdf2(img_path, pdf_path, output_path, num_group=10):
image_list = []
creat_file(pdf_path)
pdf_file = []
for i, filename in enumerate(os.listdir(img_path)):
img = Image.open(os.path.join(img_path, filename))
image_list.append(img)
if (i + 1) % num_group == 0:
split_pdf_path = os.path.join(pdf_path, f"{len(pdf_file)+1:04d}.pdf")
image_list[0].save(split_pdf_path, save_all=True, append_images=image_list[1:])
pdf_file.append(split_pdf_path)
image_list = []
pdfs = [os.path.join(pdf_path, f) for f in os.listdir(pdf_path)]
merger = PdfFileMerger()
for pdf in pdfs:
merger.append(pdf)
merger.write(os.path.join(pdf_path, output_path))
merger.close()
来源:https://blog.csdn.net/woaiwulima/article/details/130737111
猜你喜欢
- 前言你可能不需要经常处理分数,但当你需要时,Python的Fraction类会给你很大的帮助。本文将给大家详细介绍关于利用标准库fracti
- 最近在做python的web开发(原谅我的多变,好东西总想都学着。。。node.js也是),不过过程中总遇到些问题,不管是web.py还是d
- <%@ Page Language="C#" AutoEventWireup="true" C
- Pytorch:dtype不一致RuntimeError: Expected object of scalar type Double bu
- 一,PHP脚本与动态页面。 PHP脚本是一种服务器端脚本程序,可通过嵌入等方 法与HTML文件混合,也可以类,函数封
- 我从11岁开始编程,并且一直都很喜欢技术和编程。这些是我一直以来获得的经验教训。作为一个程序员,你可能需要这样的忠告。我更希望每个人在获取这
- 类的参数定义将conda环境设置为ai,conda activate ai这个文件的由来:由于在yolov1的pytorch实现的损失函数中
- 创作思路:主要还是想尝试做点稍微不同于整天为迎合客户而做的东西.然后闲时就开始构思,比如坐车,走路什么的.看到有一些复古手机的相关图,就想到
- 这篇文章主要介绍了IOS苹果AppStore内购付款的服务器端php验证方法(使用thinkphp)。AppStore内购在app中支付的过
- 本文实例讲述了php查询whois信息的方法。分享给大家供大家参考。具体如下:这里使用php通过查询whois信息的网站列表进行查询func
- 作者:AngelGavin 出处:CSDN一般问题什么是 XML?可扩展标记语言 (XML) 是 Web 上的数据通用语言。它使
- 写在前面 最近和几个小伙伴们在写字节跳动第五届青训营后端组的大作业。虽然昨天已经提交了项目,但有很多地方值得总结一下,比如这一篇,
- 很多人错误地认为ASP是简单、低效的代名词,认为ASP是低能的,不足挂齿的,也很简单,一学就会,一琢磨就精通。有人讲ASP不安全,写ASP的
- 说到这个话题,我们有个产品叫群组,为什么人们需要群组?简单说,群组就是个圈子,是有共同爱好和话题的人群聚在一起讨论、分享的地方。这个产品的诞
- 前言在我们的日常开发中, 常用的中间件有很多, 今天来讲一下怎么集成限流中间件, 它可以很好地用限制并发访问数来保护系统服务, 避免系统服务
- 多值运动,也就是对于某个对象来说,不仅仅只是其中一个属性值在变化,而是好多个,比如宽,高,字体,透明度等等同时变化当然了,多值运动会产生一个
- 如果有空格就用%20代替,如果有其它字符就用%ASCII代替,如果有汉字等四个字节的字符,就用两个%ASCII来代替。不过有时候我们也需要将
- 开源的MySQL并不能取代非共享的私有数据库在企业中的应用,于是这些开源数据库的支持者们想把解决Web应用程序开发工具的可扩展性问题看作是获
- 相对于Firefox2来说,Firefox3除了采用全新的Gecko 1.9引擎外,在性能、稳定性和安全性方面进行许多改进,在我们最关心的对
- 感谢 Dawn CSS Reset 的尝试和建议。针对字体的写法,觉得需要说明一下:body,button, input, select,