python去除水印
去除原理
学过计算机的小伙伴们都知道 ,计算机中用 RGB 代表红绿蓝,用 (255, 0, 0) 表示红色,(0, 255, 0) 表示绿色,
(0, 0, 255) 表示蓝色,(255, 255, 255) 表示白色,(0, 0, 0) 表示黑色,
去水印的原理就是将水印的颜色变成白色(255, 255, 255)。
首先获取图片宽和高,用 itertools 模块获取宽和高的笛卡尔积作为像素点。
每个像素点的颜色都由 前三位的 RGB 和 第四位的 Alpha 通道构成。Alpha 通道不需要,只要 RGB 数据。
本文用到的库文件
""" 安装模块 pillow pymupdf pymupdf 可以用 python 访问扩展名为*.pdf、.xps、.oxps、.epub、.cbz或*.fb2的文件。 还支持了许多流行的图像格式,包括多页TIFF图像。 """ from PIL import Image from itertools import product import fitz import os import re import fnmatch
图片去水印
首先需要通过微信图片截取,确定水印颜色
def remove_img(): """ 去除图片水印 :return: """ # image_file = input("请输入图片地址:") image_file = "water.png" img = Image.open(image_file) width, height = img.size """ product 用于求多个可迭代对象的笛卡尔积(Cartesian Product),它跟嵌套的 for 循环等价.即: product(A, B) 和 ((x,y) for x in A for y in B)的效果是一样的。 >>> A = [1, 2, 3] >>> B = [100, 200] >>> for item in product(A, B): ... print(item) (1, 100) (1, 200) (2, 100) (2, 200) (3, 100) (3, 200) """ for pos in product(range(width), range(height)): rgb = img.getpixel(pos)[:3] # 得到图片RGB """ 通过微信图片截取 可以看到水印的 RGB 是 (220, 220, 220),这里用 RGB 的和超过 660 就判定是水印点,此时将像素颜色替换为白色。最后保存图片 """ if sum(rgb) >= 660: img.putpixel(pos, (255, 255, 255)) img.save('eliminate_water.png')
pdf去水印
PDF 去水印的原理和图片去水印的原理大致相同,
用 PyMuPDF 打开 pdf 文件后,将 pdf 的每一页都转换为图片 pixmap,
pixmap 有它自己的 RGB,只需要将 pdf 水印中的 RGB 改为(255, 255, 255) 最后保存为图片。
def remove_pdf(): """ PDF 去水印的原理和图片去水印的原理大致相同, 用 PyMuPDF 打开 pdf 文件后,将 pdf 的每一页都转换为图片 pixmap, pixmap 有它自己的 RGB,只需要将 pdf 水印中的 RGB 改为(255, 255, 255) 最后保存为图片。 :return: """ page_num = 0 pdf_file = "water.pdf" # 用作提取pdf图片 pdf = fitz.open(pdf_file); # 获得当前路径 cwd = os.getcwd() print(cwd) for page in pdf: rotate = int(0) # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。 # 此处若是不做设置,默认图片大小为:792X612, dpi=72 zoom_x = 2 # (1.33333333-->1056x816) (2-->1584x1224) zoom_y = 2 # 设置缩放和旋转系数 mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate) pixmap = page.getPixmap(matrix=mat, alpha=False) for pos in product(range(pixmap.width), range(pixmap.height)): rgb = pixmap.pixel(pos[0], pos[1]) if sum(rgb) >= 660: pixmap.setPixel(pos[0], pos[1], (255, 255, 255)) pixmap.writePNG(f"{cwd}/water_{page_num}.png") print(f"第{page_num}水印去除完成") page_num = page_num + 1
图片转 pdf
图片转 pdf 需要注意的是图片的排序,
用 PyMuPDF 模块打开图片后将图片用 convertToPDF() 函数转成单页的 pdf。插入到新的 pdf 文件中。
def pic_ConvertPdf(): """ 图片转 pdf 需要注意的是图片的排序, 用 PyMuPDF 模块打开图片后将图片用 convertToPDF() 函数转成单页的 pdf。插入到新的 pdf 文件中。 :return: """ pic_dir = os.getcwd() pdf = fitz.open() # pa = re.compile(r'([0-9]+).png') # 过滤符合的图片文件 list_files = [name for name in os.listdir(os.curdir) if fnmatch.fnmatchcase(name, "water_[0-9]*.png")] # 按数字排序 img_files = sorted(list_files, key=lambda x:int((x.split('.')[0]).split('_')[1]), reverse=False) # print(img_files) for file in img_files: # os.listdir返回指定的文件夹包含的文件或文件夹的名字的列表 print(f"打开{file}开始转换pdf") imgdoc = fitz.open(pic_dir + '/' + file) pdfbytes = imgdoc.convertToPDF() imgpdf = fitz.open("pdf", pdfbytes) pdf.insertPDF(imgpdf) pdf.save("eliminate_water.pdf") pdf.close() print(f"pdf水印去除完成,保存为eliminate_water.pdf")
到目前为止水印终于消除了。
可以有一个遗憾,通过此方式消除水印pdf的信息结构损坏了,不能复制文字了。