Python图像处理:批量添加水印的优雅实现与进阶技巧

您所在的位置:网站首页 怎么给空间图片加水印文字显示 Python图像处理:批量添加水印的优雅实现与进阶技巧

Python图像处理:批量添加水印的优雅实现与进阶技巧

2024-07-05 04:42:45| 来源: 网络整理| 查看: 265

1. 简介

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

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

2. PIL库概述

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

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

在这里插入图片描述

3. PIL库中涉及的类 模块或类说明image模块用于图像处理ImageDraw2D图像对象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 水印透明度(0—1之间的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}')

这将允许同时处理多个图片,提高处理速度。

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

如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

1️⃣零基础入门 ① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。 在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~ 在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈! 在这里插入图片描述

2️⃣国内外Python书籍、文档 ① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集 ①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦! 在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿! 在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味! 在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。 在这里插入图片描述 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭