【Python实战】如何优雅地实现 PDF 去水印?

话接上篇,自动化处理 PDF 文档,完美实现 WPS 会员功能

小伙伴们更关心的是如何去除 PDF 中的水印~

今天,就来分享一个超简单的 PDF 去水印方法~

1. 原理介绍

在上一篇中,我们介绍了如何将 PDF 文档转换成图片,图片就是 RGB 三通道像素点的集合。

我们发现:水印的像素点和正常文字的像素点是有显著区别的。

如何查看水印的像素是多少呢?

最简单的方式是打开一个截图工具,聚焦到水印位置即可看到:

所以,水印的像素值有如下特点:

  • 像素分布在 180 - 250 (注:必要时,阈值需适当调整);
  • RGB三通道的像素值基本相同。

基于上述两个特点,我们就可以找到水印像素点的位置。

2. 代码实操

为了完美实现上述的两个判断,当然你可以写两层 for 循环遍历像素值进行判断,不过一旦图像尺寸太大,处理速度就令人抓狂了。

最简单的方式就是采用 numpy 数组进行操作:

import numpy as np
def judege_wm(img, low=180, high=250):
    # 通过像素判断
    low_bound = np.array([low, low, low])
    high_bound = np.array([high, high, high])
    mask = (img > low_bound) & (img < high_bound) & (np.abs(img-img.mean(-1, keepdims=True)).sum(-1, keepdims=True) < 10) # 要求rgb值相差不能太大
    img[mask] = 255
    return img

最后,我们来看下处理后的效果:

3. 整体流程

上述步骤,我们介绍了如何去除图片中的水印。

说好的 PDF 去水印呢?

来,参照下述流程走一遍:

关于如何实现:PDF转换成图片 以及 图片转换成PDF,上篇已经给出了详细教程:自动化处理 PDF 文档,完美实现 WPS 会员功能

写在最后

本文给大家带来了一种最简单的图片 & PDF 去水印方法,可以满足绝大部分白底黑字的文档场景。

如果背景图像纷繁复杂,本方法还无法完美解决。

欢迎有其他解决方案的小伙伴,评论区交流下啊~

如果本文对你有帮助,欢迎点赞收藏备用。

### 使用 Python 去除 PDF 文件中的水印 #### 安装所需库 为了去除 PDF 中的水印,需要安装 `PyMuPDF` (也称为 `fitz`) 和其他辅助库。可以通过 pip 来完成安装: ```bash pip install pymupdf opencv-python numpy ``` #### 加载并显示 PDF 页面图像 首先加载 PDF 文档,并将其转换为图像以便后续处理。 ```python import fitz # PyMuPDF import cv2 import numpy as np def pdf_page_to_image(pdf_path, page_num=0): doc = fitz.open(pdf_path) page = doc.load_page(page_num) pix = page.get_pixmap() img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.h, pix.w, -1) return img ``` 此函数会打开指定路径下的 PDF 文件,并提取第一页的内容作为 NumPy 数组返回[^1]。 #### 图像预处理与二值化 对于大多数情况来说,简单的阈值法能够有效地分离前景文字和背景水印。 ```python def preprocess_image(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV) kernel = np.ones((3, 3), np.uint8) cleaned = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) return cleaned ``` 这段代码先将彩色图片转成灰度图,再设定合适的阈值得到黑白二值图;最后使用形态学闭运算填充可能存在的断开字符[^3]。 #### 移除水印区域 基于上述得到的结果,定位并擦除疑似水印部分。 ```python def remove_watermark_from_image(cleaned_img, original_img): contours, _ = cv2.findContours(cleaned_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) mask = np.zeros_like(original_img[:, :, 0]) for contour in contours: area = cv2.contourArea(contour) if 100 < area < 5000: # 调整这个范围以匹配实际水印大小 x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(mask, (x, y), (x+w, y+h), 255, thickness=cv2.FILLED) result = cv2.inpaint(original_img, mask.astype(np.uint8), inpaintRadius=3, flags=cv2.INPAINT_TELEA) return result ``` 这里定义了一个掩模来标记要修复的位置,之后调用 OpenCV 的修补算法替换掉被遮挡的地方。 #### 将修改后的页面保存回 PDF 当所有页都经过处理后,需把它们重新组合成一个新的无水印版本。 ```python def save_images_as_pdf(images_list, output_filename='output.pdf'): doc = fitz.open() for image_array in images_list: height, width, channels = image_array.shape pixmap = fitz.Pixmap(fitz.csRGB, width, height, False) data = cv2.imencode('.png', image_array)[1].tobytes() pixmap.set_rect(0, 0, width, height, data) page = doc.new_page(width=width, height=height) page.insert_image(page.rect, stream=pixmap.tobytes()) doc.save(output_filename) ``` 该方法遍历给定列表里的每一幅图像数据,创建对应的 PDF 页面并将最终结果存储至磁盘上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值