Python实例题:图片批量处理工具

目录

Python实例题

题目

问题描述

解题思路

关键代码框架

难点分析

Python实例题

题目

图片批量处理工具

问题描述

开发一个 Python 工具,实现以下功能:

  • 遍历指定文件夹下的所有图片文件(支持常见格式如 jpg、png、webp)
  • 对每张图片执行以下处理流程:
    • 尺寸缩放(按比例或固定尺寸)
    • 添加水印(文字或图片水印)
    • 格式转换(如将所有图片转为 png)
  • 使用多线程加速处理过程
  • 显示处理进度和耗时统计
  • 支持错误处理(如损坏图片跳过、权限问题提示)
  • 生成处理日志文件

解题思路

  • 使用ospathlib进行文件遍历
  • 利用PIL(Pillow)库进行图像处理
  • 通过concurrent.futures.ThreadPoolExecutor实现多线程
  • tqdm库显示进度条
  • 设计日志系统记录处理详情
  • 采用面向对象设计封装不同功能模块

关键代码框架

import os
import time
import logging
from PIL import Image, ImageDraw, ImageFont
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
from pathlib import Path# 配置日志系统
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',handlers=[logging.FileHandler("image_processor.log"),logging.StreamHandler()]
)class ImageProcessor:def __init__(self, source_dir, target_dir, max_workers=5):self.source_dir = Path(source_dir)self.target_dir = Path(target_dir)self.target_dir.mkdir(exist_ok=True, parents=True)self.max_workers = max_workersself.supported_formats = ['.jpg', '.jpeg', '.png', '.webp', '.bmp']self.processed_count = 0self.error_count = 0self.start_time = Nonedef get_image_files(self):"""获取所有图片文件路径"""image_files = []for ext in self.supported_formats:image_files.extend(self.source_dir.glob(f"**/*{ext}"))return image_filesdef resize_image(self, img, target_size=(800, 600), keep_ratio=True):"""调整图片尺寸"""if keep_ratio:img.thumbnail(target_size, Image.LANCZOS)else:img = img.resize(target_size, Image.LANCZOS)return imgdef add_text_watermark(self, img, text, position=(10, 10), font_size=16):"""添加文字水印"""draw = ImageDraw.Draw(img)font = ImageFont.truetype("simhei.ttf", font_size)  # 需要中文字体文件draw.text(position, text, fill=(255, 255, 255, 128), font=font)return imgdef add_image_watermark(self, img, watermark_path, opacity=0.5):"""添加图片水印"""try:watermark = Image.open(watermark_path).convert("RGBA")watermark = watermark.resize((100, 100), Image.LANCZOS)img = img.convert("RGBA")# 水印位置(右下角)pos = (img.width - watermark.width - 10, img.height - watermark.height - 10)transparent = Image.new('RGBA', img.size, (0, 0, 0, 0))transparent.paste(img, (0, 0))transparent.paste(watermark, pos, watermark)# 调整透明度alpha = int(255 * opacity)watermark = watermark.copy()watermark.putalpha(alpha)transparent.paste(watermark, pos, watermark)return transparent.convert("RGB")except Exception as e:logging.warning(f"添加图片水印失败: {e}")return imgdef process_image(self, image_path):"""处理单张图片"""try:# 构建目标文件路径relative_path = image_path.relative_to(self.source_dir)target_path = self.target_dir / relative_pathtarget_path.parent.mkdir(exist_ok=True, parents=True)# 打开图片img = Image.open(image_path)logging.info(f"处理图片: {image_path}")# 执行处理流程img = self.resize_image(img, target_size=(1000, 800))img = self.add_text_watermark(img, "版权所有 © 2025")img = self.add_image_watermark(img, "watermark.png")  # 需要存在水印图片# 转换格式并保存target_ext = ".png"  # 统一转为png格式target_path = target_path.with_suffix(target_ext)img.save(target_path, quality=95)self.processed_count += 1return Trueexcept Exception as e:logging.error(f"处理图片失败 {image_path}: {e}")self.error_count += 1return Falsedef run(self):"""启动批量处理"""self.start_time = time.time()image_files = self.get_image_files()logging.info(f"发现 {len(image_files)} 张图片待处理")if not image_files:logging.warning("未找到可处理的图片文件")return# 使用线程池处理with ThreadPoolExecutor(max_workers=self.max_workers) as executor:results = list(tqdm(executor.map(self.process_image, image_files),total=len(image_files),desc="处理进度",unit="图片"))# 统计结果end_time = time.time()elapsed = end_time - self.start_timelogging.info(f"处理完成!共处理 {self.processed_count} 张图片,"f"失败 {self.error_count} 张,耗时 {elapsed:.2f} 秒")print(f"处理完成!总耗时: {elapsed:.2f} 秒")print(f"成功处理: {self.processed_count} 张,失败: {self.error_count} 张")# 使用示例
if __name__ == "__main__":processor = ImageProcessor(source_dir="input_images",target_dir="output_images",max_workers=8)processor.run()

难点分析

  • 多线程同步问题:需要确保processed_count等共享变量的线程安全
  • 中文字体支持:添加中文水印时需要指定正确的字体文件路径
  • 内存管理:大尺寸图片处理时可能导致内存溢出,需配合Image.LOAD_TRUNCATED_IMAGES等参数
  • 异常处理:需要处理文件权限、图片损坏、格式不支持等多种异常情况
  • 性能优化:可通过调整线程数、使用生成器分批处理大文件等方式优化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85319.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85319.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超图superMap iObjects for Java的Jar使用中遇到的问题

一、 cannot open shared object file: No such file or directory 1. 问题 2. 解决方法 (1)检查有没有配置环境变量 PATH (2)创建软连接 ln -s (3)将主机 /usr/lib64 目录中的libgomp.so.1 复制到 /pla…

常见的蓝牙5.0抗干扰技术和算法

常见的蓝牙5.0抗干扰技术和算法: 跳频扩频(Frequency Hopping Spread Spectrum, FHSS) 通过在不同的频率通道上快速切换数据传输,减少与固定频率干扰源的冲突。 直接序列扩频(Direct Sequence Spread Spectrum, DSSS&…

牛客与Moka深化合作,升级AI面试对接,引领招聘变革

近日,AI 招聘平台牛客与国内领先的人力资源全模块平台 Moka 宣布完成 AI 面试产品的全新对接升级。此次升级实现了从 Moka 到牛客的一键互绑,并打通了简历出题、风险点提问、优势技能挖掘等核心功能,为企业提供更加高效智能的面试体验。 这一…

Vue 3 路由跳转全面指南(Composition API + <script setup>)

一、前言:为什么要学习 Vue Router? 在单页面应用(SPA)开发中,路由管理是核心功能之一。Vue Router 作为 Vue.js 官方推荐的路由解决方案,与 Vue.js 深度集成,提供了以下重要功能: 页面无刷新跳转&#x…

JavaScript基础-常用的键盘事件

一、前言 在网页开发中,用户交互 是非常重要的一环。除了鼠标操作之外,键盘事件也是前端开发中最常见的交互方式之一。 JavaScript 提供了多个用于监听和处理键盘输入的事件,例如 keydown、keyup 和 keypress。掌握这些事件可以帮助我们实现…

解决 Android 项目下载依赖缺失导致的问题

解决 Android 项目下载依赖缺失导致的问题 在项目根目录下的 build.gradle 文件中增加下面的代码: buildscript {repositories {...maven {url "https://maven.aliyun.com/repository/jcenter"}maven {url "https://maven.aliyun.com/repository/c…

Clang Code Model: Error: The clangbackend executable “D:\Soft\Qt5.12.12\Tool

Qt Creator->菜单->帮助->关于插件->C>去掉ClangCodeModel勾选->重启Qt Creator 参考:【问题解决】Qt Creator 报错:Clang Code Model: Error: The clangbackend executable_qt clang code model-CSDN博客

高频面试之12 HBase

12 HBase 文章目录 12 HBase12.1 HBase存储结构12.2 HBase的写流程12.3 HBase的读流程12.6 HBase的合并12.7 RowKey设计原则12.8 RowKey如何设计12.9 HBase二级索引原理 12.1 HBase存储结构 架构角色: 1)Master 实现类为HMaster,负责监控集群…

Vue3 + TypeScript + Element Plus 表格实例null检查方法

代码分析&#xff1a; // 表格实例对象 const tableRef ref<ElTableExtendedInstance | null>(null); // 表格列配置列表 const columnConfigs ref<IColumnConfig[]>([{ prop: "index", label: "序号", width: 60 },{ prop: "batchNo&…

Neo4j常见语法-unwind

unwind的用法&#xff08;UNWIND 是一个强大的操作符&#xff0c;用于将集合&#xff08;列表、数组&#xff09;展开为多行数据。它类似于关系型数据库中的 UNNEST 或 LATERAL JOIN&#xff0c;是 Cypher 查询中处理集合数据的核心工具&#xff09; &#xff08;1&#xff09;…

JavaEE-Spring-IoCDI

Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场 景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说, 还是⽐较抽象. ⽤⼀句更具体的话来概括Spring, 那就是: Spring 是包含了众多⼯具⽅法的 IoC 容器 容器是⽤来容纳…

CppCon 2017 学习:10 Core Guidelines You Need to Start Using Now

C.45: 不要定义一个仅仅初始化成员变量的默认构造函数&#xff0c;而是使用类内成员初始化器 如果你有一个默认构造函数&#xff0c;它的唯一作用是给成员变量赋默认值&#xff08;如 1、2、3&#xff09;&#xff0c;这更清晰、简单的方法是直接在成员变量声明时使用类内初始…

Java并发编程实战 Day 28:虚拟线程与Project Loom

【Java并发编程实战 Day 28】虚拟线程与Project Loom 文章内容 在“Java并发编程实战”系列的第28天&#xff0c;我们将聚焦于**虚拟线程&#xff08;Virtual Threads&#xff09;**和 Project Loom&#xff0c;这是 Java 在高并发场景下的一次重大革新。随着现代应用对性能和…

Linux系统移植⑦:uboot启动流程详解-board_init_r执行过程

Linux系统移植⑦&#xff1a;uboot启动流程详解-board_init_r执行过程 在uboot中&#xff0c;board_init_r 是启动流程中的一个关键函数&#xff0c;负责完成板级&#xff08;board-specific&#xff09;的后期初始化工作。以下是关于该函数的详细说明&#xff1a; 1. 函数作…

OpenStack入门体验

1.1云计算概述 相信大家都听到很多的阿里云、腾讯云、百度云等等这些词,那到底什么是云计算?云 计算又能做什么? 1.1.1什么是云计算 云计算(cloud computing)是一种基于网络的超级计算模式,基于用户的不同需求,提供所需的资源,包括计算资源、存储资源、网络资源等。云计算…

RK 安卓10/11平台 HDMI-IN 调试

这篇文章我们介绍一下在安卓9、10、11的版本上&#xff0c;rk平台的hdmi-in功能是如何实现的&#xff0c;下篇文章我们再介绍安卓12之后的版本有了什么变化。希望对在rk平台调试hdmi-in功能的朋友有一些帮助。 目录 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;…

MongoDB学习记录(快速入门)

MongoDB核心 基础概念 数据库 数据库是按照数据结构来组织、存储和管理数据的仓库。在内存中运行的&#xff0c;一旦程序运行结束或者计算机断电&#xff0c;程序运行中的数据都会丢失。我们需要将一些程序运行的数据持久化到硬盘之中&#xff0c;以确保数据的安全性。数据库…

阿里一面:微服务拆分需要考虑什么因素?

要拆分微服务&#xff0c;首先我们要了解微服务拆了会有什么问题&#xff1f;怎么合理拆服务&#xff1f; 拆分服务会带来什么问题&#xff1f; 举个电商系统下单扣库存的例子。 对于单体应用&#xff0c;通讯在进程内部进行&#xff0c;下单方法调用扣库存方法&#xff0c;…

3D高斯泼溅和4D高斯

1.高斯函数 想象你往平静的湖水里扔一块石头&#xff0c;水波会以石头落点为中心向外扩散&#xff0c;形成一个逐渐衰减的圆形波纹。高斯函数的形状就和这个波纹类似&#xff1a; 中心最高&#xff08;石头落点&#xff0c;波峰最强&#xff09;。越往外&#xff0c;高度&…

comfyui插件和comfyui mac安装

mac comfyui安装包 ComfyUI.zip&#xff0c;官方最新0.3.40&#xff0c;如果后续官方有迭代&#xff0c;可以直接通过git更新源码升级 comfyui插件下载&#xff0c;解压放到custom_nodes目录下&#xff0c;包含 comfyui-animatediff-evolved&#xff08;视频插件&#xff09; 和…