社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用Python去除PDF水印

Python爱好者社区 • 3 年前 • 452 次点击  

今天介绍下用 Python 去除 PDF (图片)的水印。思路很简单,代码也很简洁。

首先来考虑 Python 如何去除图片的水印,然后再将思路复用到 PDF 上面。

这张图片是前几天整理《数据结构和算法》PDF里的一个截图,带着公众号的水印。

从上图可以明显看到,为了不影响阅读正文,水印颜色一般比较浅。因此,我们可以利用颜色差这个特征来去掉水印。即:用 Python 读取图片的颜色,并将浅颜色部分变白。

Python 标准库 PIL 可以获取图片的颜色,Python2 是系统自带的,Python3 需要自己安装,我用的 Python 3.8,需要执行以下命令安装

pip install pillow

安装完成,读取图片,并获取图片的尺寸(宽度和高度)

from PIL import Image

img = Image.open('watermark_pic.png')
width, height = img.size

进行下一步之前,先简单介绍下计算机里关于颜色的知识。光学三原色是红绿蓝(RGB),也就是说它们是不可分解的三种基本颜色,其他颜色都可以通过这三种颜色混合而成,三种颜色等比例混合就是白色,没有光就是黑色。

在计算机中,可以用三个字节表示 RGB 颜色,1个字节能表示的最大数值是 255, 所以,(255, 0, 0)代表红色,(0, 255, 0)代表绿色,(0, 0, 255)代表蓝色。相应地,(255, 255, 255)代表白色,(0, 0, 0)代表黑色。从(0, 0, 0) ~ (255, 255, 255) 之间的任意组合都可以代表一个不同的颜色。

接下来我们可以通过下面代码读取图片的 RGB

for i in range(width):
    for j in range(height):
        pos = (i, j)
        print(img.getpixel(pos)[:3])

图片每个位置颜色由四元组表示,前三位分别是 RGB,第四位是 Alpha 通道,我们不需要关心。

有了 RGB ,我们就可以对其修改。

从图中可以发现,水印的 RGB 是 #d9d9d9,这里是用十六进制表示的,其实就是(217, 217, 217)

这三个颜色值都越靠近 255,颜色就越淡,当它们都变成 255,也就成了白色。所以只要 RGB 都大于 217 的位置,我们都可以给它填成白色。即:RGB 三位数之和大于等于 651。

if sum(img.getpixel(pos)[:3]) >= 651:
    img.putpixel(pos, (255255255))

完整代码如下:

from PIL import Image

img = Image.open('watermark_pic.png')
width, height = img.size

for i in range(width):
    for j in range(height):
        pos = (i, j)
        if sum(img.getpixel(pos)[:3]) >= 651:
            img.putpixel(pos, (255255255))

img.save('watermark_removed_pic.png')

有了上面的基础,去除 PDF 的水印就简单了,思路是将每页 PDF 转成图片,然后修改水印的 RGB,最后输出图片即可。

安装 pymupdf 库,用来来操作 PDF




    
pip install pymupdf

读取 PDF,并转图片

import fitz


doc = fitz.open("数据结构和算法手册@公众号渡码.pdf")

for page in doc:
    pix = page.get_pixmap()

该 PDF 共 480 页,所以需要遍历每一页,并获取每一页对应的图片pixpix对象类似于我们上面看到的img对象,可以读取、修改它的 RGB。

page.get_pixmap() 这个操作是不可逆的,即能够实现从 PDF 到图片的转换,但修改图片 RGB 后无法应用到 PDF 上,只能输出为图片。

修改水印 RGB 跟刚才一样,区别是这里的 RGB 是一个三元组,没有 Alpha 通道,代码如下:

from itertools import product

for pos in product(range(pix.width), range(pix.height)):
    if sum(pix.pixel(pos[0], pos[1])) >= 651:
        pix.set_pixel(pos[0], pos[1], (255255255))

完整代码如下:

from itertools import product
import fitz


doc = fitz.open("数据结构和算法手册@公众号渡码.pdf")

page_no = 0
for page in doc:
    pix = page.get_pixmap()

    for pos in product(range(pix.width), range(pix.height)):
        if sum(pix.pixel(pos[0], pos[1])) >= 651:
            pix.set_pixel(pos[0], pos[1], (255255255))

    pix.pil_save(f"pdf_pics/page_{page_no}.png", dpi=(3000030000))

    print(f'第 {page_no} 页去除完成')
    page_no += 1

这种方案是有缺点的,第一,输出并非 PDF 格式;第二,输出的图片比较模糊,后续还有待优化,最好是能直接修改 PDF。

后续继续分享 Python 基础以及使用工具,欢迎关注。

重磅!Python交流已成立


公众号运营至今,离不开小伙伴们的支持。
为了给小伙伴们提供一个互相交流的技术平台,特地开通了Python交流群。
群里有不少技术大神,不时会分享一些技术要点,更有一些资源收藏爱好者不时分享一些优质的学习资料。(免费,不卖课!)
需要进群的朋友,可长按扫描下方二维码。


▲长按扫码

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/123267
 
452 次点击