当前位置: 首页 > 科技观察

用Python去除PDF水印,你学会了吗?

时间:2023-03-17 18:12:50 科技观察

今天给大家介绍一下用Python去除PDF(图片)水印的方法。思路很简单,代码也很简洁。首先,让我们考虑一下Python如何去除图像的水印,然后在PDF上复用这个想法。这张图是我前几天整理的《数据结构和算法》的PDF截图,水印是公众号。从上图可以明显看出,为了不影响文字的阅读,水印的颜色一般比较浅。因此,我们可以利用色差这一特征来去除水印。即:用Python读取图片的颜色,将浅色部分变成白色。Python标准库PIL可以获取图片的颜色。系统自带Python2。Python3需要自己安装。我使用Python3.8。我需要执行以下命令来安装pipinstallpillow。安装完成后,读取图片,从PILimportImageimg=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)的任意组合都可以表示不同的颜色。接下来我们可以通过下面的代码foriinrange(width):forjinrange(height):pos=(i,j)print(img.getpixel(pos)[:3])读取图片的RGB各位置的颜色图片由四元组组成表示前三位是RGB,第四位是Alpha通道,我们不需要关心。使用RGB,我们可以对其进行修改。从图中可以看出,水印的RGB是#d9d9d9,用16进制表示,其实就是(217,217,217)。这三个色值越接近255,颜色越浅,当都变成255时,就变成了白色。所以只要RGB大于217,我们就可以用白色填充。即:RGB三位数之和大于等于651ifsum(img.getpixel(pos)[:3])>=651:img.putpixel(pos,(255,255,255))完整代码为如下:fromPILimportImageimg=Image.open('watermark_pic.png')width,height=img.sizeforiinrange(width):forjinrange(height):pos=(i,j)ifsum(img.getpixel(pos)[:3])>=651:img.putpixel(pos,(255,255,255))img.save('watermark_removed_pic.png')有了以上基础,去除PDF的水印就很简单了。思路是将PDF的每一页都转成图片,然后修改水印的RGB,最后输出图片。安装pymupdf库操作PDFpipinstallpymupdf读取PDF并转换图片importfitzdoc=fitz.open(《数据结构与算法手册@公众号Wacode.pdf》)forpageindoc:pix=page.get_pixmap()PDF一共480个pages,所以需要遍历每个页面,获取每个页面对应的图片pix。pix对象类似于我们上面看到的img对象,它的RGB是可以读取和修改的。page.get_pixmap()这个操作是不可逆的,即可以实现PDF到图片的转换,但是修改了图片的RGB后,不能应用到PDF,只能作为图片输出。修改水印RGB和之前一样,不同的是这里的RGB是没有Alpha通道的三元组,代码如下:fromitertoolsimportproductforposinproduct(range(pix.width),range(pix.height)):ifsum(pix.pixel(pos[0],pos[1]))>=651:pix.set_pixel(pos[0],pos[1],(255,255,255))完整代码如下:fromitertoolsimportproductimportfitzdoc=fitz.open("DataStructure和算法手册@公众号Code.pdf")page_no=0forpageindoc:pix=page.get_pixmap()forposinproduct(range(pix.width),range(pix.height)):ifsum(pix.pixel(pos[0],pos[1]))>=651:pix.set_pixel(pos[0],pos[1],(255,255,255))pix.pil_save(f"pdf_pics/page_{page_no}.png",dpi=(30000,30000))print(f'删除页面{page_no}已完成')page_no+=1这种解决方案有缺点。第一,输出不是PDF格式;二是输出图像比较模糊,后续需要优化。最好直接修改成PDF。完整代码回复关键词gp,找到great-programmer/python/python项目/去水印目录。PDF源文件位于great-programmer/DataStructuresandAlgorithms/目录中。本文转载自微信公众号“杜马”,可通过以下二维码关注。转载请联系杜马公众号。