如何用Python案例实现图片加水印?

wen python案例 6

本文目录导读:

如何用Python案例实现图片加水印?

  1. 方法一:使用PIL/Pillow添加文字水印
  2. 方法二:添加图片/Logo水印
  3. 方法三:平铺水印(覆盖整张图片)
  4. 方法四:批量处理多个图片
  5. 方法五:使用OpenCV添加水印
  6. 安装依赖
  7. 完整使用示例
  8. 注意事项

我来为您介绍几种在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()

注意事项

  1. 图片格式:支持常见的JPG、PNG、BMP等格式
  2. 中文水印:如果使用中文,需要指定中文字体文件路径
  3. 性能考虑:处理大图片时建议适当调整图片大小
  4. 版权保护:水印不能完全防止盗图,但可以起到一定威慑作用

这些案例涵盖了常见的加水印需求,您可以根据具体场景选择合适的方法。

抱歉,评论功能暂时关闭!