Python图像处理实战:使用PIL库批量添加水印的完整指南【第27篇—python:Seaborn】

这篇具有很好参考价值的文章主要介绍了Python图像处理实战:使用PIL库批量添加水印的完整指南【第27篇—python:Seaborn】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 简介

在日常图像处理中,为图片添加水印是一项常见任务。有多种方法和工具可供选择,而今天我们将专注于使用Python语言结合PIL库批量添加水印。

需要注意的是,所选用的图片格式不应为JPG或JPEG,因为这两种格式的图片不支持透明度设置。

2. PIL库概述

先前的文章已经详细介绍过PIL库,这里不再赘述。

  • PIL是Python的图像处理库,支持多种文件格式。
  • PIL提供强大的图像和图形处理功能,包括缩放、裁剪、叠加以及添加线条、文字等操作。
  • 安装PIL库可使用以下命令:
pip install Pillow

Python图像处理实战:使用PIL库批量添加水印的完整指南【第27篇—python:Seaborn】,Python领域开发技术应用技术,python,图像处理,开发语言,PIL库,添加水印

3. PIL库中涉及的类

模块或类 说明
image模块 用于图像处理
ImageDraw 2D图像对象
ImageFont 字体存储
ImageEnhance 图像增强

4. 实现原理

本文的主要目标是批量为某个文件夹下的图片添加水印,实现原理如下:

  • 设置水印内容;
  • 使用Image对象的open()方法打开原始图片;
  • 使用Image对象的new()方法创建存储水印图片的对象;
  • 使用ImageDraw.Draw对象的text()方法绘制水印文字;
  • 使用ImageEnhance中Brightness的enhance()方法设置水印透明度。

5. 实现过程

5.1 原始图片

设定原始图片的存储目录,例如:

F:\python_study\image\image01

5.2 导入相关模块

导入所需的PIL模块或类:

from PIL imort Image, ImageDraw, ImageFont, ImageEnhance
import os

5.3 初始化数据

通过用户手动输入相关信息,如图片存储路径、水印文字、水印位置、水印透明度等:

class WatermarkText():
    def __init__(self):
        super(WatermarkText, self).__init__()
        self.image_path = input('图片路径:')
        self.watermark_text = input('水印文字:')
        self.position_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):'))
        self.opacity = float(input('水印透明度(0—1之间的1位小数):'))

5.4 水印字体设置

选择系统字体库中的字体:

self.font = ImageFont.truetype("cambriab.ttf", size=35)

5.5 打开原始图片并创建存储对象

打开原始图片并转换为RGBA:

image = Image.open(img).convert('RGBA')

创建绘制对象:

new_img = Image.new('RGBA', image.size, (255, 255, 255, 0))
image_draw = ImageDraw.Draw(new_img)

5.6 计算图片和水印的大小

计算图片大小:

w, h = image.size

计算文字大小:

w1 = self.font.getsize(self.watermark_text)[0]
h1 = self.font.getsize(self.watermark_text)[1]

5.7 选择性设置水印文字

通过if语句实现:

if self.position_flag == 1:  # 左上角
    location = (0, 0)
elif self.position_flag == 2:  # 左下角
    location = (0, h - h1)
elif self.position_flag == 3:  # 右上角
    location = (w - w1, 0)
elif self.position_flag == 4:  # 右下角
    location = (w - w1, h - h1)
elif self.position_flag == 5:  # 居中
    location = (h/2, h/2)

5.8 绘制文字并设置透明度

绘制文字:

image_draw.text(location, self.watermark_text, font=self.font, fill="blue")

设置透明度:

transparent = new_img.split()[3]
transparent = ImageEnhance.Brightness(transparent).enhance(self.opacity)
new_img.putalpha(transparent)

Image.alpha_composite(image, new_img).save(img)

5.9 遍历获取图片文件并调用绘制方法

watermark_text = WatermarkText()
try:
    file_list = os.listdir(watermark_text.image_path)
    for i in range(0, len(file_list)):
        filepath = os.path.join(watermark_text.image_path, file_list[i])
        if os.path.isfile(filepath):
            filetype = os.path.splitext(filepath)[1]
            if filetype == '.png':
                watermark_text.add_text_watermark(filepath)
            else:
                print("图片格式有误,请使用png格式图片")
    print('批量添加水印完成')
except:
    print('输入的文件路径有误,请检查~~')

6. 完整源码


from PIL import

 Image, ImageDraw, ImageFont, ImageEnhance
import os

class WatermarkText():
    def __init__(self):
        super(WatermarkText, self).__init__()
        self.image_path = input('图片路径:')
        self.watermark_text = input('水印文字:')
        self.position_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):'))
        self.opacity = float(input('水印透明度(0—1之间的1位小数):'))

        # 设置字体
        self.font = ImageFont.truetype("cambriab.ttf", size=35)

    # 文字水印
    def add_text_watermark(self, img):
        global location
        image = Image.open(img).convert('RGBA') 
        new_img = Image.new('RGBA', image.size, (255, 255, 255, 0)) 
        image_draw = ImageDraw.Draw(new_img) 
        w, h = image.size  # 图片大小
        w1 = self.font.getsize(self.watermark_text)[0]  # 字体宽度
        h1 = self.font.getsize(self.watermark_text)[1]  # 字体高度

        # 设置水印文字位置
        if self.position_flag == 1:  # 左上角
            location = (0, 0)
        elif self.position_flag == 2:  # 左下角
            location = (0, h - h1)
        elif self.position_flag == 3:  # 右上角
            location = (w - w1, 0)
        elif self.position_flag == 4:  # 右下角
            location = (w - w1, h - h1)
        elif self.position_flag == 5:  # 居中
            location = (h/2, h/2)
        # 绘制文字
        image_draw.text(location, self.watermark_text, font=self.font, fill="blue")

        # 设置透明度
        transparent = new_img.split()[3]
        transparent = ImageEnhance.Brightness(transparent).enhance(self.opacity)
        new_img.putalpha(transparent)

        Image.alpha_composite(image, new_img).save(img)

if __name__ == "__main__":
    watermark_text = WatermarkText()
    try:
        file_list = os.listdir(watermark_text.image_path) 
        for i in range(0, len(file_list)): 
            filepath = os.path.join(watermark_text.image_path, file_list[i])
            if os.path.isfile(filepath): 
                filetype = os.path.splitext(filepath)[1] 
                if filetype == '.png': 
                    watermark_text.add_text_watermark(filepath) 
                else:
                    print("图片格式有误,请使用png格式图片")
        print('批量添加水印完成')
    except:
        print('输入的文件路径有误,请检查~~')

7. 效果展示

运行过程:

D:\Python37\python.exe F:/python_study/python_project/watermark_text.py
图片路径:F:\python_study\image\image01
水印文字:
水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):1
水印透明度(01之间的1位小数):0.5
F:/python_study/python_project/watermark_text.py:32: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
  w1 = self.font.getsize(self.watermark_text)[0]  # 获取字体宽度
F:/python_study/python_project/watermark_text.py:33: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
  h1 = self.font.getsize(self.watermark_text)[1]  # 获取字体高度
批量添加水印完成

8. 改进与建议

8.1 参数输入方式优化

在初始化数据的部分,我们可以考虑通过命令行参数或配置文件的方式输入相关信息,以提高用户体验。例如使用argparse库来解析命令行参数。

import argparse

class WatermarkText():
    def __init__(self):
        parser = argparse.ArgumentParser(description='Add watermark to images.')
        parser.add_argument('--image_path', type=str, help='Path to the image directory.')
        parser.add_argument('--watermark_text', type=str, help='Text for watermark.')
        parser.add_argument('--position_flag', type=int, help='Position flag for watermark (1: top-left, 2: bottom-left, 3: top-right, 4: bottom-right, 5: center).')
        parser.add_argument('--opacity', type=float, help='Opacity for watermark (0-1 with 1 decimal place).')
        
        args = parser.parse_args()

        self.image_path = args.image_path or input('Image path: ')
        self.watermark_text = args.watermark_text or input('Watermark text: ')
        self.position_flag = args.position_flag or int(input('Watermark position (1: top-left, 2: bottom-left, 3: top-right, 4: bottom-right, 5: center): '))
        self.opacity = args.opacity or float(input('Watermark opacity (0-1 with 1 decimal place): '))

8.2 异常处理改进

在处理异常的部分,我们可以更具体地捕获异常类型,并提供更友好的提示信息。

try:
    # existing code...
except FileNotFoundError:
    print('Error: The specified image directory does not exist.')
except PermissionError:
    print('Error: Permission denied to access the specified image directory.')
except Exception as e:
    print(f'An unexpected error occurred: {e}')

8.3 代码结构优化

可以考虑将一些功能模块化,提高代码的可读性和维护性。例如,将文字水印的添加功能独立成一个方法。

class WatermarkText():
    # existing code...

    def add_text_watermark(self, img):
        # existing code...

8.4 日志记录

考虑在程序中添加日志记录,记录关键步骤和出错信息,以便于排查问题。

import logging

logging.basicConfig(level=logging.INFO)

class WatermarkText():
    # existing code...

    def add_text_watermark(self, img):
        try:
            # existing code...
            logging.info(f'Successfully added watermark to {img}')
        except Exception as e:
            logging.error(f'Error adding watermark to {img}: {e}')

8.5 扩展功能

在程序中可以考虑添加更多功能,比如支持不同的水印颜色、字体大小等选项,以使程序更加灵活。

这些改进和建议将有助于提高程序的稳定性、易用性和可维护性。

当然,我们将继续改进和完善你的代码。在这一部分,我们会考虑一些进一步的优化和改进。

9. 优化图片格式检查

在处理图片文件时,可以优化检查图片格式的方式。使用os.path.splitext得到的文件扩展名可能包含大写字母,为了确保匹配,可以将文件扩展名转换为小写。

if filetype.lower() == '.png':
    watermark_text.add_text_watermark(filepath)
else:
    print("Error: Image format is not supported. Please use PNG format.")

10. 增加用户交互性

可以考虑在程序中增加更多用户交互性,比如在成功添加水印后询问用户是否继续添加水印。

while True:
    try:
        # existing code...

        print('Watermark added successfully.')
        
        another = input('Do you want to add watermark to another image? (yes/no): ').lower()
        if another != 'yes':
            break
    except Exception as e:
        logging.error(f'Error: {e}')

这样,用户可以选择是否继续添加水印,提高程序的交互性。

11. 多线程处理

如果你需要处理大量图片,可以考虑使用多线程来加速处理过程。这可以通过concurrent.futures模块实现。

from concurrent.futures import ThreadPoolExecutor

# existing code...

if __name__ == "__main__":
    watermark_text = WatermarkText()
    try:
        file_list = os.listdir(watermark_text.image_path) 

        with ThreadPoolExecutor() as executor:
            executor.map(watermark_text.add_text_watermark, [os.path.join(watermark_text.image_path, file) for file in file_list])

        print('Batch watermarking completed.')
    except Exception as e:
        logging.error(f'Error: {e}')

这将允许同时处理多个图片,提高处理速度。文章来源地址https://www.toymoban.com/news/detail-794218.html

12. 其他优化建议

  • 考虑支持更多图片格式,而不仅限于PNG。你可以使用Pillow库中的Image.register_open()方法注册其他格式的图片打开器。
  • 如果水印文字较长,可以考虑自动调整文字大小,以适应图片。

到了这里,关于Python图像处理实战:使用PIL库批量添加水印的完整指南【第27篇—python:Seaborn】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十一 简单给视频添加水印图片效果

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十一 简单给视频添加水印图片效果 一、简单介绍 二、简单给视频添加水印图片效果实现原理 三、简单给视频添加水印图片效果案例实现简单步骤 四、注意事项 Python是一种跨平台的计算机程序设计语

    2024年04月25日
    浏览(74)
  • PIL、OpenCV、numpy处理图像格式的相互转化方式

    OpenCV读取图像后返回的是一个代表图像的NumPy数组,采用的格式是 H×W×C,通道顺序为BGR 使用matplotlib绘图时,可以读取tesnor和numpy数据类型,图片通道顺序为RGB,且尺寸为(H,W,C)。 使用np.array(image)和np.asarray(image)可以将 PIL Image 图像转换成 numpy 数组。 使用Image.fromarray(np.uint8(i

    2024年02月07日
    浏览(44)
  • 图像处理库(Opencv, Matplotlib, PIL)以及三者之间的转换

    opencv的基本图像类型可以和numpy数组相互转化,因此可以直接调用 torch.from_numpy(img) 将图像转换成 tensor 读取: img=cv2.imread(path) OpenCV读取图像后返回的是一个代表图像的 numpy.ndarray ,采用的格式是 (H,W,C) ,通道顺序为 BGR , 取值范围 [0,255] , dtype=uint8 。 显示: cv2.imshow(name,img) 保存

    2024年02月14日
    浏览(47)
  • 【图像处理】python | 给图像添加噪声 | random_noise

    首先,我们看一下random_noise的构造: floating-point image是浮点图的意思。**kwargs是参数的意思,对这部分我也作一定的学习(之前不懂),改天写一个博客记录一下。它的作用:把多个参数打包。 1.image: 输入的图像是n维数组,会转换为浮点型 2.mode: 除了高斯型,还

    2024年02月01日
    浏览(43)
  • 图像处理(1):用Python实现彩色图像转为灰度图像的两种方法以及批量将图片转为灰度图

    用Python实现彩色图像转为灰度图像的两种方法介绍 这篇文章给大家主要介绍使用 Python 将彩色图像转为灰度图像的两种方法,以及用 Python 批量将图片转为灰度图的方法,供大家参考: 使用Python中的cv2库,它自带彩色转灰度的方法,并且代码非常简单。 先读取一张彩色图片,然

    2024年02月11日
    浏览(50)
  • 图像处理:随机添加椒盐噪声和高斯噪声Python

    目录 图像处理:随机添加椒盐噪声和高斯噪声Python 1.常见的图像噪声 (1)高斯噪声 (2) 椒盐噪声 2.生成图像噪声 (1)高斯噪声 (2) 椒盐噪声(速度慢) (3) 椒盐噪声(快速版) 3. Demo测试         图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。在噪

    2024年02月02日
    浏览(45)
  • python图像处理实战(一)—图像基础

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 目录 一、前言 二、认识图像  三、用到的库  (1)Numpy

    2024年02月09日
    浏览(46)
  • python图像处理实战(三)—图像几何变换

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 前言       图像几何变换就是在不改变图像像素值的前提

    2024年02月11日
    浏览(58)
  • python图像处理实战(二)—图像几何变换

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 前言       图像几何变换就是在不改变图像像素值的前提

    2024年02月09日
    浏览(61)
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之六 简单图像倾斜校正处理效果

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之六 简单图像倾斜校正处理效果 一、简单介绍 二、简单图像倾斜校正处理效果实现原理 三、简单图像倾斜校正处理效果案例实现简单步骤 四、注意事项 Python是一种跨平台的计算机程序设计语言。是一种面向对

    2024年04月13日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包