from PIL import Image, ImageFont, ImageDraw, ImageEnhance, ImageChops
import cv2
import math
import numpy as np
def crop_image(im):
"""裁剪图片边缘空白"""
bg = Image.new(mode="RGBA", size=im.size)
bbox = ImageChops.difference(im, bg).getbbox()
if bbox:
return im.crop(bbox)
return im
def set_opacity(im, opacity):
"""设置水印透明度"""
assert 0 <= opacity <= 1
alpha = im.split()[3]
alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
im.putalpha(alpha)
return im
def get_mark_img(text, color="#8B8B1B", size=30, opacity=0.15):
"""生成水印图片"""
width = len(text) * size
mark = Image.new(mode="RGBA", size=(width, size + 20))
draw_table = ImageDraw.Draw(im=mark)
draw_table.text(
xy=(0, 0),
text=text,
fill=color,
font=ImageFont.truetype("./bird.ttf", size=size),
)
del draw_table
mark = crop_image(mark) # 裁剪空白
set_opacity(mark, opacity) # 透明度
return mark
# 读取OpenCV图像
img = cv2.imread("test.jpg")
# OpenCV转PIL格式
im = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 生成水印图标
mark = get_mark_img("我是水印", "#FFFFFF", 30, 0.5)
# 将水印图标扩展并旋转生成水印大图
w, h = im.size
c = int(math.sqrt(w**2 + h**2))
mark2 = Image.new(mode="RGBA", size=(c, c))
y, idx = 0, 0
mark_w, mark_h = mark.size
space = 100 # 水印文字间隔
angle = 45 # 水印文字角度
while y < c:
x = -int((mark_w + space) * 0.5 * idx)
idx = (idx + 1) % 2
while x < c:
mark2.paste(mark, (x, y))
x = x + mark_w + space
y = y + mark_h + space
# 将水印大图旋转一定角度
mark2 = mark2.rotate(angle)
# 在原图上添加水印大图
if im.mode != "RGBA":
im = im.convert("RGBA")
im.paste(mark2, (int((w - c) / 2), int((h - c) / 2)), mask=mark2.split()[3])
# PIL转OpenCV
img = cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR)
# 保存图像
cv2.imwrite("result.jpg", img)
实现效果如下:
完整代码链接