Python去除图片水印实现方法详解
什么是图片水印
图片水印是指在图片上添加一些透明的文字或图形等信息,用于防止图片被盗用或侵权。通常情况下,图片水印是不影响图片整体的美观和观感的,但在某些情况下,图片水印却成了一个麻烦的问题,比如用于识别某个公司的某个品牌,或者一些恶意水印侵犯了用户的隐私,这时我们就需要用代码的方式对图片进行去除水印处理。
Python去除图片水印的实现方法
预处理
图片是由像素点组成的,可以通过像素点的rgb值来识别水印图片。我们可以通过安装Pillow库来对图片进行预处理,用以下代码读取图片:
from PIL import Image
img = Image.open('image.jpg').convert('RGBA')
识别水印位置
一旦我们得到了图片的rgba值,我们可以通过对比图像各个区域颜色的变化,找到水印的位置。一个简单的方法是对图片进行高斯模糊处理,然后和原图进行对比,得到一个掩码,从而识别出水印的位置。
import cv2
import numpy as np
img = cv2.imread('image.jpg')
# 高斯模糊处理
img_blur = cv2.GaussianBlur(img, (25,25), 0)
# 对比原图得到掩码
img_diff = cv2.absdiff(img, img_blur)
mask = cv2.cvtColor(img_diff, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
去除水印
有了水印的位置信息,我们可以通过修改像素的rgb值,来达到去除水印的效果。在去除水印时,我们可以通过以下两种方法:
方法一:用图片中不包含水印的区域来填充水印位置
for y in range(img.shape[0]):
for x in range(img.shape[1]):
if mask[y][x] != 0:
img[y][x] = [0,0,0,0]
img_blur2 = cv2.GaussianBlur(img, (25,25), 0)
img = np.where(np.expand_dims(mask, axis=-1) == 255, img_blur2, img)
方法二:用邻近像素来填充水印位置
for y in range(img.shape[0]):
for x in range(img.shape[1]):
if mask[y][x] != 0:
if y - 1 >= 0 and mask[y - 1][x] == 0:
img[y][x] = img[y - 1][x]
elif y + 1 < img.shape[0] and mask[y + 1][x] == 0:
img[y][x] = img[y + 1][x]
elif x - 1 >= 0 and mask[y][x - 1] == 0:
img[y][x] = img[y][x - 1]
elif x + 1 < img.shape[1] and mask[y][x + 1] == 0:
img[y][x] = img[y][x + 1]
img = cv2.GaussianBlur(img, (25,25), 0)
示例说明
示例一:去除单个图片的水印
from PIL import Image
import cv2
import numpy as np
# 读取图片
img = Image.open('image.jpg').convert('RGBA')
img.save('image.png')
img = cv2.imread('image.png')
# 高斯模糊处理
img_blur = cv2.GaussianBlur(img, (25,25), 0)
# 对比原图得到掩码
img_diff = cv2.absdiff(img, img_blur)
mask = cv2.cvtColor(img_diff, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# 用邻近像素来填充水印位置
for y in range(img.shape[0]):
for x in range(img.shape[1]):
if mask[y][x] != 0:
if y - 1 >= 0 and mask[y - 1][x] == 0:
img[y][x] = img[y - 1][x]
elif y + 1 < img.shape[0] and mask[y + 1][x] == 0:
img[y][x] = img[y + 1][x]
elif x - 1 >= 0 and mask[y][x - 1] == 0:
img[y][x] = img[y][x - 1]
elif x + 1 < img.shape[1] and mask[y][x + 1] == 0:
img[y][x] = img[y][x + 1]
img = cv2.GaussianBlur(img, (25,25), 0)
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
img.save('image_without_watermark.jpg')
示例二:批量去除图片水印
import os
from PIL import Image
import cv2
import numpy as np
# 获取指定路径下所有jpg图片列表
def get_img_list(dir_path):
img_list = []
for filename in os.listdir(dir_path):
if filename.endswith('.jpg'):
img_list.append(os.path.join(dir_path, filename))
return img_list
# 批量去除水印并保存
def batch_remove_watermark(img_list):
for img_path in img_list:
img = Image.open(img_path).convert('RGBA')
img.save('temp.png')
img = cv2.imread('temp.png')
# 高斯模糊处理
img_blur = cv2.GaussianBlur(img, (25,25), 0)
# 对比原图得到掩码
img_diff = cv2.absdiff(img, img_blur)
mask = cv2.cvtColor(img_diff, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# 用邻近像素来填充水印位置
for y in range(img.shape[0]):
for x in range(img.shape[1]):
if mask[y][x] != 0:
if y - 1 >= 0 and mask[y - 1][x] == 0:
img[y][x] = img[y - 1][x]
elif y + 1 < img.shape[0] and mask[y + 1][x] == 0:
img[y][x] = img[y + 1][x]
elif x - 1 >= 0 and mask[y][x - 1] == 0:
img[y][x] = img[y][x - 1]
elif x + 1 < img.shape[1] and mask[y][x + 1] == 0:
img[y][x] = img[y][x + 1]
img = cv2.GaussianBlur(img, (25,25), 0)
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
img.save(os.path.join('output', os.path.basename(img_path)))
os.remove('temp.png')
# 测试
img_list = get_img_list('input')
if not os.path.exists('output'):
os.makedirs('output')
batch_remove_watermark(img_list)