python畅玩os模块以及顺便批量修改图片尺寸
作者:愿此后再无WA
最近gif做不了,找了很久终于发现了原因。
原来是!图 片 尺 寸 没 有 统 一!
说了也奇怪,之前制作的好好的现在突然就说要尺寸一致才行,那没办法了,只好从了。
谁叫他功能强呢?(这个软件叫ScreenToGif,在制作gif方面确实没的说。)
之前截图虽然有参考线,但毕竟也是手动截图的,所以还是会有一点点偏差。于是百度了诸多方法,都说用什么photoshop能批量修改图片尺寸,结果不还是要一个一个去点呢?
后知后觉,python功能这么强大,有难得倒python的吗?
身为python爱好者,必须用python搞起来!
修改图片用到的模块是PIL,而在修改图片的过程中OS模块起到非常重要的作用。OS模块相当于跑腿的,找到好看点的木头送给雕工师傅雕刻,而雕工师傅就是PIL了,OS模块就是让雕工师傅发现合适木头。哎,与其说师傅与木头,不如说伯乐和千里马吧,哈哈哈..
文章介绍
在批量修改图片尺寸的过程中,我们需要用到OS模块诸多方法。
因此,在这里我以实现修改图片尺寸为目标,着重讲解一下OS模块如何运用到实际需求中。
OS模块
简介
os(operating system)模块是提供各种 Python 程序与操作系统进行交互的接口。
常用功能
- 获取信息:OS模块能获取路径,目录名,文件名。
- 修改信息:OS模块能添加路径,创建目录,更改目录名/文件名, 删除目录,删除文件
(典型的增删改查)
▲(附)os.path
os下面有个比较常用的path模块,这模块的能帮助你更好的处理文件。它有什么作用呢?
1.判断
abspath表示返回绝对路径。
- 判断路径是否存在
os.path.exists(abspath)
- 判断是否是文件/目录 (当路径存在时才进行判断,否则返回False)
os.path.isdir(abspath) / os.path.isfile(abspath)
2.提供标准格式的字符串。
以下操作均不考虑路径/名称是否有效,只是单纯提供处理过的字符串。
- 将多个路径合并成一个路径。
os.path.join(A,B[,..])
AB均表示路径。该函数相当于
r"\\".join((A,B)) # 此处必须两个括号,第一个括号表示join方法,第二个括号表示元组
当给的路径出现多个盘符时(不合法路径),取最后一个盘符之后的路径。、
- 提供绝对路径。
os.path.abspath(path)
默认是返回你工作目录加上你传进去的路径。
- 返回最底层文件/目录名 或 除最底层文件/目录的目录。
# 返回文件/目录名 >>> print(os.path.basename("lishuaige//jiu//shi//shuai//ya")) ya # 返回文件/目录名的目录 >>> print(os.path.dirname("lishuaige//jiu//shi//shuai//ya")) lishuaige//jiu//shi//shuai
os.path模块终究只能用来看,真正能对文件修改的还是OS模块。
创建/删除 目录/文件
1.创建 目录(Create directory)/ 文件
os.mkdir(abspath) # 创建一层目录 os.makedirs(abspath) # 创建多层目录需要用makedirs否则会报错。
而创建文件是使用常规的with open方法,注意,创建文件时的文件目录必须已存在,否则会报错
with open(r'C:\Users\17591\Desktop\c.txt', 'w+') as fp: fp.write("lishuaige")
2.删除目录
os.removedirs(abspath) # 递归删除空目录也只能删除空目录,否则会报错
注意:删除是自深向浅删除直到遇到空文件停止。
os.rmdir(abspath) # 删除一个目录
3.删除文件
os.remove(abspath) # 删除的必须是文件而不是目录,否则会报错
更改 目录/文件 名/位置
无论是文件还是目录,都是使用os.rename方法进行改名。
这命令不仅能改名,还能将文件/目录移动到其他位置(前提是这个位置的上一层目录已经存在)。
os.rename(原绝对路径,新绝对路径)
▲获取 路径/目录/文件 名
1.获取指定路径下的目录和文件名
os.listdir(abspath)
返回一个列表,文件名与目录名都在里面。
2.★os.walk函数
这个函数功能强大的不行,就像它名字一样,随便逛随便看os系统信息,因此它的作用是能递归地获取目录下的所有信息(路径/目录/文件名)。(它借助了os.listdir函数)
批量处理图片尺寸
了解OS模块之后我们就要开始干正事了。
实现思路
首先要新建一个目录用于存放修改后的图片。我们的目的是统一图片尺寸,因为我们每张图片的大小都比较接近,所以我们以第一张图片的大小作为标准,将其余图片的大小设置成第一张图片的尺寸。然后保存到新建的目录当中。
(在图片大小与修改后的大小不一致的情况下,原图会经过一定比例放大或缩小得到修改后的图片,因此无需担心图片内容的丢失。)
注意:如果传入的路径存在多个图片文件夹,我们希望在每个存有图片的文件夹里面都新建一个文件夹来存放修改后的图片。
详细步骤
安装PIL库
进入pycharm的terminal 或 cmd命令行
输入
pip install pillow
即可完成安装PIL库。
创建文件夹
我们需要创建一个文件夹用来保存修改后的图片。如果这个文件夹已经存在的话,我们需要删除里面的文件。怎么删除?第一个方法是使用shutil的rmtree函数删除整个文件夹后再使用os.mkdir函数创个新的,第二个方法是使用我们os.walk函数逐步删除里面所有文件,但这样比较繁琐,如果遇到多个目录的时候删起来就难受了,所以还是用rmtree删除实在些。
因此我们定义一个创建文件夹作为输出路径的方法。
在遇到第一张图片时所在的目录创建(可能会在不同目录创建,取决于你传入的路径含有的图片文件夹。每存在一个图片文件夹就会在里面创建一个存放修改后图片的文件夹)
# 如果已存在文件夹则清空文件,否则创建一个新的 def initialize_folder(output_folder): print("初始化..") if os.path.exists(output_folder): shutil.rmtree(output_folder) os.mkdir(output_folder) print("初始化文件夹 %s 成功!" % (output_folder.split(os.sep)[-1]))
批量处理
我们使用os.walk遍历图片文件夹,如果文件是图片的格式的话,我们获取他的文件路径并确定导出路径。如果是第一张图片的话我们还需要初始化文件夹,以及获取图片尺寸。最后将图片尺寸,路径和保存路径交给PIL模块处理。最后给出些人性化提示。
# path: 图片文件夹路径 fname: 保存修改文件的目录名 def file_handling(path, fname): for dir_path, listdir, files in os.walk(path): # 根据目录路径获取目录名 os.sep表示分割符 dir_name = dir_path.split(os.sep)[-1] # 如果此时的目录跟保存路径一致,那么需要跳过 if dir_name == fname: continue print("正在处理 %s 文件夹文件..\n" % dir_name) # 设置进度 rate = 1 # 记录总数 c = len(files) for file in files: # 如果后缀名不是图片格式则需要跳过 if file.split('.')[-1].lower() not in "pngjpgjpeg": continue # 文件路径 file_path = os.path.join(dir_path, file) # 保存路径 export_path = os.path.join(dir_path, fname, file) if rate == 1: # 初始化文件夹 用于存放修改后的图片 initialize_folder(os.path.join(dir_path, fname)) img = Image.open(file_path) width = img.size[0] height = img.size[1] # 交给雕工师傅 resize_image(file_path, export_path, width, height) print("已完成 {:.2f} %\t{:d}个文件".format(rate / c * 100, rate)) rate += 1 print("保存成功!")
修改图片尺寸
三步走战略:打开->修改->保存。
我们修改图片尺寸使用的是PIL下面的Image模块的方法,需要提前导入。
from PIL import Image
最后使用resize方法修改大小即可,resize顾名思义,修改尺寸。
# 修改图片大小 def resize_image(file_path, export_path, width, height): img = Image.open(file_path) # Image.ANTIALIAS:抗锯齿,提高图片质量 r = img.resize((width, height), Image.ANTIALIAS) r.save(export_path)
主函数
作为函数的入口需要确定图片路径及目录名,然后调用以上方法。
if __name__ == '__main__': # 获取存放图片总路径 path = r'%s' % (input("请将您的存放图片的路径复制于此:")) # 指定输出文件夹名 fname = r'lishuaige' file_handling(path, fname)
完整代码
from PIL import Image import os import shutil # 修改图片大小 def resize_image(file_path, export_path, width, height): img = Image.open(file_path) # Image.ANTIALIAS:抗锯齿,提高图片质量 r = img.resize((width, height), Image.ANTIALIAS) r.save(export_path) # 如果已存在文件夹则清空文件,否则创建一个新的 def initialize_folder(output_folder): print("初始化..") if os.path.exists(output_folder): shutil.rmtree(output_folder) os.mkdir(output_folder) print("初始化文件夹 %s 成功!" % (output_folder.split(os.sep)[-1])) # path: 图片文件夹路径 fname: 保存修改文件的目录名 def file_handling(path, fname): for dir_path, listdir, files in os.walk(path): # 根据目录路径获取目录名 os.sep表示分割符 dir_name = dir_path.split(os.sep)[-1] # 如果此时的目录跟保存路径一致,那么需要跳过 if dir_name == fname: continue print("正在处理 %s 文件夹文件..\n" % dir_name) # 设置进度 rate = 1 # 记录总数 c = len(files) for file in files: # 如果后缀名不是图片格式则需要跳过 if file.split('.')[-1].lower() not in "pngjpgjpeg": continue # 文件路径 file_path = os.path.join(dir_path, file) # 保存路径 export_path = os.path.join(dir_path, fname, file) if rate == 1: # 初始化文件夹 用于存放修改后的图片 initialize_folder(os.path.join(dir_path, fname)) img = Image.open(file_path) width = img.size[0] height = img.size[1] # 交给雕工师傅 resize_image(file_path, export_path, width, height) print("已完成 {:.2f} %\t{:d}个文件".format(rate / c * 100, rate)) rate += 1 print("保存成功!") if __name__ == '__main__': # 获取存放图片总路径 path = r'%s' % (input("请将您的存放图片的路径复制于此:")) # 指定输出文件夹名 fname = r'lishuaige' file_handling(path, fname)
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。