使用PIL为图片添加水印[python]

使用PIL为图片添加水印[python]


问题描述

最近遇到有需要使用证件的情况,但是直接发送证件照片可能存在安全风险,所以考虑在手机上找个软件给证件添加水印(满屏水印那种,不是单个水印)。但是在应用商店下了几个软件,有可以使用的但是非VIP用户有次数限制,很是烦人。
所有决定自己用Python的PIL库搞一个小脚本处理它,同时证件照片在自己本地处理也比较放心,不用担心照片被app上传到服务器的风险。


代码实现

项目地址:https://github.com/MingruiWang2017/add_watermark.git

需要安装依赖:pip install pillow argparse

import os
import sys
import argparse
from PIL import Image, ImageDraw, ImageFont, ImageEnhance


def read_origin_photo(photo_path, photo_angle=0):
    """
    获取图像内容与尺寸

    photo_path:图片路径
    photo_angle: 图片旋转角度
    """
    origin_photo = Image.open(photo_path)
    origin_photo = origin_photo.convert('RGBA')
    origin_photo = origin_photo.rotate(photo_angle, expand=True)
    h, w = origin_photo.size
    return origin_photo, h, w

# def get_color(text_color):
#     r = int(text_color[1:3], base=16)    
#     g = int(text_color[3:5], base=16)    
#     b = int(text_color[5:7], base=16)
#     return r, g, b  


def make_text_picture(h, w, text, font_path, font_size=40, angle=-45, color=(0, 0, 0)):
    """
    制作水印图片

    h: 原图高度
    w: 原图宽度
    font_path:字体文件路径
    font_size:字体大小
    angle:字体旋转角度
    color:字体颜色
    """
    text_pic = Image.new('RGBA', (4 * h, 4 * w), (255, 255, 255, 255))
    fnt = ImageFont.truetype(font_path, size=font_size)

    text_d = ImageDraw.Draw(text_pic)

    # a, b 分别控制水印的列间距和行间距,默认为字体的2倍列距,4倍行距
    a, b = 2, 4
    for x in range(10, text_pic.size[0] - 10, a * font_size * len(text)):
        for y in range(10, text_pic.size[1] - 10, b * font_size):
            text_d.multiline_text((x, y), text, fill=color, font=fnt)

    # 旋转水印
    text_pic = text_pic.rotate(angle)
    # 截取水印部分图片
    text_pic = text_pic.crop((h, w, 3 * h, 3 * w))
    # text_pic.show()
    return text_pic


def combine(origin_photo, text_pic, alpha=0.2, out_name='out.jpg'):
    """
    为图片添加水印并保存
    origin_photo: 原图内容
    text_pic: 要添加的水印图片
    alpha:水印的不透明度
    out_name: 输出图片的文件名
    """
    # 合并水印图片和原图
    text_pic = text_pic.resize(origin_photo.size)
    out = Image.blend(origin_photo, text_pic, alpha)
    out = out.convert('RGB')
    # 增强图片对比度
    enhance = ImageEnhance.Contrast(out)
    out = enhance.enhance(1.0 / (1 - alpha))
    out_path = os.path.join('./out_images/', out_name)
    out.save(out_path)
    out.show()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('photo_path', help='图片路径,如:1.jpg或./images/1.jpg')
    parser.add_argument('text', help="要添加的水印内容")
    parser.add_argument('--photo_angle', dest='photo_angle', default=0,
                        help='原图片旋转角度,默认为0,不进行旋转')
    parser.add_argument('--new_image_name', dest='new_image_name', default=None,
                        help='输出图片的名称, 默认为"原图片名_with_watermark.jpg", 图片保存在out_images目录下')
    parser.add_argument('--font_path', dest='font_path', default=r"./fonts/STSONG.TTF",
                        help='要使用的字体路径,如 STSONG.TTF,windows可在C:\Windows\Fonts查找字体')
    parser.add_argument('--text_angle', dest='text_angle', default=-45,
                        help='水印的旋转角度,0为水平,-90位从上向下垂直, 90为从下向上垂直,默认-45')
    parser.add_argument('--text_color', dest='text_color', default='#000000',
                        help="水印颜色,默认#000000(黑色)")
    parser.add_argument('--text_size', dest='text_size',
                        default=40, help='水印字体的大小, 默认40')
    parser.add_argument('--text_alpha', dest='text_alpha',
                        default=0.2, help='水印的不透明度,建议0.2~0.3,默认0.2')
    args = parser.parse_args()

    photo_path = args.photo_path
    text = args.text
    if not photo_path or not text:
        print('必须指定图片路径和水印文字')
        sys.exit(-1)
    
    photo_angle = int(args.photo_angle)
    font_path = args.font_path
    text_size = int(args.text_size)
    text_angle = int(args.text_angle)

    origin_photo, h, w = read_origin_photo(photo_path, photo_angle)
    text_pic = make_text_picture(h, w, text, font_path,
                                 font_size=text_size, angle=text_angle, color=args.text_color)
    new_image_name = args.new_image_name
    photo_name = os.path.split(photo_path)[-1].split('.')[0]  # 获取图片名称
    if new_image_name is None:
        new_image_name = photo_name + '_with_watermark.jpg'
    combine(origin_photo, text_pic, alpha=float(args.text_alpha),
            out_name=new_image_name)


使用方法

可以通过python add_text.py --help命令查看帮助文档,其中add_text.py是脚本的名称,可以按自己喜好更换。
在windows环境下测试使用,字体文件可以从windows字体库中选择,位置为C:\Windows\Fonts

D:\code>python add_text.py --help                                                              
usage: add_watermark.py [-h] [--photo_angle PHOTO_ANGLE] [--new_image_name NEW_IMAGE_NAME] [--font_path FONT_PATH]
                        [--text_angle TEXT_ANGLE] [--text_color TEXT_COLOR] [--text_size TEXT_SIZE] [--text_alpha TEXT_ALPHA]
                        photo_path text

positional arguments:
  photo_path            图片路径,如:1.jpg或./images/1.jpg
  text                  要添加的水印内容

options:
  -h, --help            show this help message and exit
  --photo_angle PHOTO_ANGLE
                        原图片旋转角度,默认为0,不进行旋转
  --new_image_name NEW_IMAGE_NAME
                        输出图片的名称, 默认为"原图片名_with_watermark.jpg", 图片保存在out_images目录下
  --font_path FONT_PATH
                        要使用的字体路径,如 STSONG.TTF,windows可在C:\Windows\Fonts查找字体
  --text_angle TEXT_ANGLE
                        水印的旋转角度,0为水平,-90位从上向下垂直, 90为从下向上垂直,默认-45
  --text_color TEXT_COLOR
                        水印颜色,默认#000000(黑色)
  --text_size TEXT_SIZE
                        水印字体的大小, 默认40
  --text_alpha TEXT_ALPHA
                        水印的不透明度,建议0.2~0.3,默认0.2

使用效果

以下命令基于github项目目录结构执行,如果只是复制了上面的脚本,需要修改脚本中的字体路径和图片输出路径。

建议直接clone git仓库进行操作或测试。

原图:
在这里插入图片描述
添加水印:python add_watermark.py ./images/1.jpg "房东的猫"
在这里插入图片描述
结果显示图片的对比度会出现下降。不过放在证件上问题不大。

更换字体和颜色:
python add_watermark.py --new_image_name="2.jpg" --text_color="#0000FF" --font_path="./fonts/简卡通.TTF" --text_alpha=0.1 ./images/1.jpg "寄 没有地址的信"
在这里插入图片描述

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在图片添加数字水印,可以使用PythonPIL库(Python Imaging Library),具体步骤如下: 1.导入PIL库 ```python from PIL import Image, ImageDraw, ImageFont ``` 2.打开图片 ```python im = Image.open('image.jpg') ``` 3.创建字体对象 ```python font = ImageFont.truetype('arial.ttf', size=20) ``` 4.创建Draw对象 ```python draw = ImageDraw.Draw(im) ``` 5.添加水印 ```python draw.text((0, 0), '123', fill=(255, 0, 0), font=font) ``` 6.保存图片 ```python im.save('watermark.jpg') ``` 为了检测数字水印是否被修改或删除,可以使用数字水印算法。一种常见的数字水印算法是LSB(Least Significant Bit)算法,即将数字水印嵌入到图片的最低有效位中。具体步骤如下: 1.将数字水印转换为二进制序列 ```python watermark = '123' watermark_binary = ''.join(format(ord(c), '08b') for c in watermark) ``` 2.打开图片 ```python im = Image.open('watermark.jpg') ``` 3.将图片转换为像素矩阵 ```python pixels = im.load() width, height = im.size ``` 4.将数字水印嵌入到最低有效位中 ```python index = 0 for y in range(height): for x in range(width): r, g, b = pixels[x, y] if index < len(watermark_binary): r_binary = format(r, '08b') r_binary = r_binary[:-1] + watermark_binary[index] r = int(r_binary, 2) pixels[x, y] = (r, g, b) index += 1 else: break else: continue break ``` 5.保存图片 ```python im.save('watermark_modified.jpg') ``` 6.检测数字水印是否被修改或删除 ```python im_modified = Image.open('watermark_modified.jpg') pixels_modified = im_modified.load() width_modified, height_modified = im_modified.size index = 0 watermark_binary_modified = '' for y in range(height_modified): for x in range(width_modified): r_modified, g_modified, b_modified = pixels_modified[x, y] r_binary_modified = format(r_modified, '08b') watermark_binary_modified += r_binary_modified[-1] index += 1 if index == len(watermark_binary): break else: continue break watermark_modified = ''.join(chr(int(watermark_binary_modified[i:i+8], 2)) for i in range(0, len(watermark_binary_modified), 8)) if watermark == watermark_modified: print('数字水印未被修改或删除') else: print('数字水印已被修改或删除') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值