本文目录导读:

我来为您介绍几种在Python中实现图片加水印的方法,包含完整的案例代码。
使用PIL/Pillow添加文字水印
基础文字水印
from PIL import Image, ImageDraw, ImageFont
import os
def add_text_watermark(input_image_path, output_image_path, watermark_text,
position='bottom-right', opacity=0.5):
"""
添加文字水印
"""
# 打开图片
original = Image.open(input_image_path).convert('RGBA')
# 创建水印图层
watermark_layer = Image.new('RGBA', original.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark_layer)
# 设置字体(Windows系统路径)
try:
font = ImageFont.truetype("arial.ttf", 36)
except:
font = ImageFont.load_default()
# 获取文字大小
text_bbox = draw.textbbox((0, 0), watermark_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# 计算位置
image_width, image_height = original.size
if position == 'top-left':
x, y = 10, 10
elif position == 'top-right':
x, y = image_width - text_width - 10, 10
elif position == 'bottom-left':
x, y = 10, image_height - text_height - 10
elif position == 'bottom-right':
x, y = image_width - text_width - 10, image_height - text_height - 10
elif position == 'center':
x, y = (image_width - text_width) // 2, (image_height - text_height) // 2
else:
x, y = 10, 10
# 添加文字水印(白色文字,透明度可调)
alpha = int(255 * opacity)
draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255, alpha))
# 合并图层
watermarked = Image.alpha_composite(original, watermark_layer)
# 保存结果
watermarked = watermarked.convert('RGB')
watermarked.save(output_image_path, quality=95)
print(f"水印添加完成!输出文件:{output_image_path}")
# 使用示例
add_text_watermark(
input_image_path="input.jpg",
output_image_path="output_text_watermark.jpg",
watermark_text="© 2024 My Watermark",
position="bottom-right",
opacity=0.6
)
添加图片/Logo水印
from PIL import Image
import os
def add_image_watermark(input_image_path, watermark_image_path, output_image_path,
position='bottom-right', scale=0.2, opacity=0.7):
"""
添加图片水印
"""
# 打开原图和水印图片
original = Image.open(input_image_path).convert('RGBA')
watermark = Image.open(watermark_image_path).convert('RGBA')
# 调整水印大小(根据原图比例)
image_width, image_height = original.size
watermark_width, watermark_height = watermark.size
# 按比例缩放水印
new_watermark_width = int(image_width * scale)
new_watermark_height = int(watermark_height * (new_watermark_width / watermark_width))
watermark = watermark.resize((new_watermark_width, new_watermark_height), Image.LANCZOS)
# 调整透明度
if opacity < 1.0:
alpha = watermark.split()[3]
alpha = alpha.point(lambda p: p * opacity)
watermark.putalpha(alpha)
# 计算位置
wm_width, wm_height = watermark.size
if position == 'top-left':
x, y = 10, 10
elif position == 'top-right':
x, y = image_width - wm_width - 10, 10
elif position == 'bottom-left':
x, y = 10, image_height - wm_height - 10
elif position == 'bottom-right':
x, y = image_width - wm_width - 10, image_height - wm_height - 10
elif position == 'center':
x, y = (image_width - wm_width) // 2, (image_height - wm_height) // 2
else:
x, y = 10, image_height - wm_height - 10
# 创建图层并合并
watermark_layer = Image.new('RGBA', original.size, (0, 0, 0, 0))
watermark_layer.paste(watermark, (x, y), watermark)
watermarked = Image.alpha_composite(original, watermark_layer)
# 保存结果
watermarked = watermarked.convert('RGB')
watermarked.save(output_image_path, quality=95)
print(f"水印添加完成!输出文件:{output_image_path}")
# 使用示例
add_image_watermark(
input_image_path="input.jpg",
watermark_image_path="logo.png",
output_image_path="output_image_watermark.jpg",
position="bottom-right",
scale=0.15,
opacity=0.6
)
平铺水印(覆盖整张图片)
from PIL import Image, ImageDraw, ImageFont
import math
def add_tiled_watermark(input_image_path, output_image_path, watermark_text,
opacity=0.3, angle=30):
"""
添加平铺水印
"""
# 打开图片
original = Image.open(input_image_path).convert('RGBA')
image_width, image_height = original.size
# 创建水印瓦片
try:
font = ImageFont.truetype("arial.ttf", 24)
except:
font = ImageFont.load_default()
# 获取文字大小
text_bbox = ImageDraw.Draw(original).textbbox((0, 0), watermark_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# 创建单个水印
tile_size = max(text_width, text_height) * 3
tile = Image.new('RGBA', (tile_size, tile_size), (0, 0, 0, 0))
draw = ImageDraw.Draw(tile)
# 在瓦片中心绘制文字
tile_center_x = tile_size // 2
tile_center_y = tile_size // 2
draw.text((tile_center_x - text_width // 2,
tile_center_y - text_height // 2),
watermark_text, font=font,
fill=(255, 255, 255, int(255 * opacity)))
# 旋转水印
tile = tile.rotate(angle, expand=True, fillcolor=(0, 0, 0, 0))
# 创建平铺图层
tiled_layer = Image.new('RGBA', original.size, (0, 0, 0, 0))
# 计算需要平铺的数量
tile_width, tile_height = tile.size
cols = math.ceil(image_width / tile_width) + 1
rows = math.ceil(image_height / tile_height) + 1
# 平铺水印
for row in range(rows):
for col in range(cols):
x = col * tile_width
y = row * tile_height
tiled_layer.paste(tile, (x, y), tile)
# 合并图层
watermarked = Image.alpha_composite(original, tiled_layer)
# 保存结果
watermarked = watermarked.convert('RGB')
watermarked.save(output_image_path, quality=95)
print(f"平铺水印添加完成!输出文件:{output_image_path}")
# 使用示例
add_tiled_watermark(
input_image_path="input.jpg",
output_image_path="output_tiled_watermark.jpg",
watermark_text="CONFIDENTIAL",
opacity=0.2,
angle=45
)
批量处理多个图片
import os
from PIL import Image, ImageDraw, ImageFont
from concurrent.futures import ThreadPoolExecutor
import glob
def batch_add_watermark(input_dir, output_dir, watermark_text,
font_size=36, opacity=0.5, max_workers=4):
"""
批量添加水印
"""
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 获取所有图片文件
image_files = []
for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
image_files.extend(glob.glob(os.path.join(input_dir, ext)))
print(f"找到 {len(image_files)} 张图片")
# 批量处理函数
def process_single_image(image_path):
try:
# 生成输出文件名
filename = os.path.basename(image_path)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_watermarked{ext}")
# 添加水印
add_text_watermark(image_path, output_path, watermark_text,
position='bottom-right', opacity=opacity)
return f"处理完成: {filename}"
except Exception as e:
return f"处理失败: {filename}, 错误: {str(e)}"
# 使用线程池并行处理
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = executor.map(process_single_image, image_files)
for result in results:
print(result)
print("批量处理完成!")
# 使用示例
batch_add_watermark(
input_dir="./input_images/",
output_dir="./output_images/",
watermark_text="© 2024 My Watermark",
font_size=36,
opacity=0.5
)
使用OpenCV添加水印
import cv2
import numpy as np
def add_watermark_opencv(input_image_path, output_image_path, watermark_text):
"""
使用OpenCV添加水印
"""
# 读取图片
img = cv2.imread(input_image_path)
height, width = img.shape[:2]
# 设置字体参数
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 2
font_thickness = 3
font_color = (255, 255, 255) # 白色
# 获取文字大小
text_size = cv2.getTextSize(watermark_text, font, font_scale, font_thickness)[0]
text_x = width - text_size[0] - 10
text_y = height - 10
# 创建透明图层
overlay = img.copy()
# 添加文字背景
cv2.rectangle(overlay,
(text_x - 5, text_y - text_size[1] - 5),
(text_x + text_size[0] + 5, text_y + 5),
(0, 0, 0),
-1) # 填充黑色背景
# 添加水印文字
cv2.putText(overlay, watermark_text, (text_x, text_y),
font, font_scale, font_color, font_thickness)
# 混合图层(透明度)
alpha = 0.6
result = cv2.addWeighted(overlay, alpha, img, 1 - alpha, 0)
# 保存结果
cv2.imwrite(output_image_path, result)
print(f"OpenCV水印添加完成!输出文件:{output_image_path}")
# 使用示例
add_watermark_opencv(
input_image_path="input.jpg",
output_image_path="output_opencv_watermark.jpg",
watermark_text="OpenCV Watermark"
)
安装依赖
pip install Pillow opencv-python-headless
完整使用示例
def main():
# 示例1:文字水印
add_text_watermark(
"input.jpg",
"text_watermark.jpg",
"© 2024 Example",
position="bottom-right",
opacity=0.5
)
# 示例2:图片水印
add_image_watermark(
"input.jpg",
"logo.png",
"image_watermark.jpg",
position="bottom-left",
scale=0.2,
opacity=0.7
)
# 示例3:平铺水印
add_tiled_watermark(
"input.jpg",
"tiled_watermark.jpg",
"SAMPLE",
opacity=0.2,
angle=30
)
# 示例4:批量处理
batch_add_watermark(
"./input/",
"./output/",
"© 2024 Batch",
opacity=0.4
)
if __name__ == "__main__":
main()
注意事项
- 图片格式:支持常见的JPG、PNG、BMP等格式
- 中文水印:如果使用中文,需要指定中文字体文件路径
- 性能考虑:处理大图片时建议适当调整图片大小
- 版权保护:水印不能完全防止盗图,但可以起到一定威慑作用
这些案例涵盖了常见的加水印需求,您可以根据具体场景选择合适的方法。