Python去除图片水印:OpenCV与PIL两种实战方案
本文详细介绍利用Python去除文档图片中灰色水印的两种方法。首先通过OpenCV结合Numpy进行亮度/对比度线性回归调整,并限制像素区间;其次使用PIL库配合itertools遍历像素,将高亮度值直接替换为白色。两种方法均针对白底黑字灰水印场景,代码简洁且效果直观,适合技术参考。
图片水印类型繁多,本文首先聚焦于最简单的一种场景进行处理。

此类水印通常出现在带有白色背景的文档图片中,表现为灰色字体,而需要保留的正文字体为黑色。
针对这种情况,通常可以通过简单的亮度或对比度调整来消除水印,并适当降低整体亮度以补偿视觉差异[1]。参考现有方案,去除水印的方法有多种,其核心原理相似,此处首先介绍基于OpenCV的实现方式。
OpenCV + Numpy
该方法依赖两个主要库:cv2和numpy。cv2是基于OpenCV的图像处理库,支持腐蚀、膨胀等操作;Numpy则是处理矩阵和维度运算的强大工具。
函数简介
首先介绍cv2中的三个基本函数及其用法。
img = cv2.imread('test.png')
cv2.imshow('test.png',img)
cv2.waitKey(0)
cv2.imwrite('test_2.png', img)
对于Numpy,需要用到np.clip(),这是一个截取函数,用于筛选数组中大于或小于特定值的元素,并将其重置为固定值。
np.clip(a, a_min, a_max, out=None):
具体使用示例如下:

如上所示,数组x中的所有数值被限制在0到5的范围内。介绍这些基础函数的目的是为了后续处理做准备,请继续往下看。
色彩转换
回到本文初衷,即去除文档图片中的水印。
在上图中选取了三个关键点,分别对应白色背景、黑色文字以及灰色水印的像素位置。
我们的目标是将水印颜色转换为白色背景色,即将图像中RGB值为[217,217,217]的像素点转换为[255,255,255]。
需要注意的是,[217,217,217]并非固定值,而是一个范围。为了方便调整,我选取了部分像素点并进行了线性回归分析。
目的是对图片整体颜色进行变换,尽量保持原有黑色字体不变,同时确保水印部分的像素值≥255,随后通过np.clip()限定区间,将所有相关像素统一变为[255,255,255]。

说干就干
import cv2
import numpy as np
img = cv2.imread('test.png')
new = np.clip(1.4057577998008846*img-38.33089999653017, 0, 255).astype(np.uint8)
cv2.imwrite('removed.png', new)
以下是调整后的效果对比(左侧为转换前,右侧为转换后)。

左:转换前 右:转换后
处理效果良好,表明对于此类文档图片水印,仅需几行Python代码即可轻松去除。
然而,通过线性回归改变整体图片颜色,也会轻微影响原有黑色文本的颜色。
那么,能否采取更直接的方式,仅改变水印颜色呢?
可以尝试这种方法。
PIL + itertools
PIL是另一个Python图像处理库,其Image模块涵盖了图像基础操作的大部分功能。
itertools 此前被誉为零差评的Python内置库。其中itertools.product用于生成多个列表和迭代器的笛卡尔积。
原理与之前相同,即将图像中[217,217,217]的像素点转换为[255,255,255]。
采取更直接的方式,即对像素值总和约为600(217+217+217)以上的像素点,直接修改为[255,255,255]。
from itertools import product
from PIL import Image
img = Image.open('test.png')
width, height = img.size
for pos in product(range(width), range(height)):
if sum(img.getpixel(pos)[:3]) > 600:
img.putpixel(pos, (255,255,255))
img.save('removed_1.png')
运行结果对比如下。

左:转换前 右:转换后
与第一种方法相比,肉眼观察并未发现明显差异。
用户可根据喜好选择任意一种方法。
至此,关于运用Python去除图片水印的介绍到此结束。如需了解更多相关内容,请搜索本站过往文章或继续浏览后续文章,感谢大家的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









