我大一刚入校的时候,我那高度近视的牛姓学长就告诉我,你咋恁想不开呢,报这个专业,赶紧想办法转专业吧,咱们专业到学校就是打杂的,当时还挺不服气的,后来果然把自己混成了一个干杂活的,人称校园杂工。猫有猫路,蛇有蛇道,在杂工生涯中,还是有几件颇为自得的事情,其一就是用Python帮助同事提高工作效率了。
需求
作为教育技术专业的学生,所学甚为芜杂,从教育理论到网站开发,从彩色电视机维修到摄录编,从美术原理到三维软件(第个菜单的第二个子菜单点一下选第三项),学的挺多的,啊扯远了,反正当初在学校也拍了很多抓不住重点的新闻照片,大家知道学校的大小照片都是要拍照挂网推文留档的,而且大概16年的时候,青岛市档案工作要求把所有的图片按照上图所示的格式保存,并且导入到档案管理系统。
原始照片的文件名大概是题名一列的样子,其他具体要求是:
- 当年所有的照片都要有一个档号,按照顺序排列
- 所有照片都要有一个小的缩略图,文件名是档号
- 然后还要有归档日期光盘号之类的
- 要计算每张光盘存放多少照片
- 自动更新光盘号
- 处理xls文档,最后选择xlrd模块
其实大部分要求都挺简单的,但是每张图片生成缩略图并且按照档号排列,这个工作真的是会把人逼疯的,估计负责档案的老师也是苦不堪言,受不了了,向领导求助(这比大包大揽最后搞砸好多了),然后就轮到我小孟尝哦不是小郎出场了,谁让我平时吹牛自己编程厉害呢。
当时已经自学过一段时间的Python了,正好拿来练手。
任务分解
简要分析
凡事超过3遍,就一定可以通过编程来解决,当然这句话很绝对,不过如果你讨厌重复的工作,有意识的通过编程来避免重复性的工作是非常重要的。
其实这个脚本并不难写,主要就是遍历文件,然后裁剪图片,把裁剪后的图片保存到新的文件夹,然后把数据写到xls就号了,档号和缩略图是最复杂的部分,表中其他的数据用excel自身的填充功能都可以很方便的完成。
麻烦的是拍照日期,一是题名中的文件日期其实不是很准确的,因为学校里用来存档的照片都是数码相机拍摄的照片,所以照片的EXIF信息是完整的(专业课《多媒体原理》中的内容),所以想到可以直接从EXIF信息中提取拍摄日期,当时其实没有做的太复杂直接读出来了事了,现在看来其实也可能有的图片EXIF信息是不准确的,需要跟题名的日期比对,当然程序会复杂一点,现在是写基本教程嘛,写意为主,有个大概差不多了,感兴趣的老师自然会深入去研究的。
可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
Exif信息是可以被任意编辑的,因此只有参考的功能。
图片处理
图片裁剪
至于裁剪图片,学习廖雪峰的Python课程的时候,知道Pillow(PIL)库可以用来在windows系统下处理图片,功能很强大,安装也很简单,只需要在命令行输入:
pip install pillow
读取EXIF信息
通过认真翻阅pillow的文档https://pillow.readthedocs.io/en/stable/,得知pillow可以方便的处理图片的元数据EXIF信息,欧耶。
处理excel文件
处理excel文件当时使用了比较简单的xlwd库,专门用来写xls文件的库。
程序实现
遍历所有照片
Python提供了用来操作文件系统的标准库os模块,于是翻阅os模块的文档,看到方法挺多的,其中有一个很重要的方法就是listdir
方法,用来打印出某个文件夹下面所有的子文件夹和文件,当然也有文件可以查看当前文件夹了。
在这里我重新搞了一个图片文件夹,用来演示处理档案。这些单反都是用数码相机拍摄的,EXIF信息是非常完整的。
在IDLE新建一个文件,命名为main.py,保存到docs文件夹:
此时的目录结构如下:
要遍历所有文件,要用到os模块的listdir方法,我们看下:
os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序。 它不包括 '.' 和'..' 即使它在文件夹中。
只支持在 Unix, Windows 下使用。
在IDLE中输入以下代码:
import os
# 如果不给lisdir提供参数
# 默认输出当前文件夹所有
# 文件和文件夹
files = os.listdir()
print(files)
运行程序,输出结果如下:
====================== RESTART: D:\coding\docs\main.py ======================
['images', 'main.py']
>>>
可以看到listdir方法返回了docs文件夹下所有的文件,包括子文件夹和文件,并保存在一个列表files变量之中。
但是我们需要处理的是images文件夹中的文件,所以,我们给listdir方法提供一个参数,表示路径,用于显示特定路径下的文件:
import os
# 如果不给lisdir提供参数
# 默认输出当前文件夹所有
# 文件和文件夹
files = os.listdir("images")
print(files)
运行代码输出如下:
与文件夹的截图是对应的
如何返回listdir方法返回的文件名代表的是文件和字符串呢,继续翻文档(其实我自己做的时候,是直接百度如何遍历文件拼凑的代码,在这里写文章才一步步的讲出来)
os模块下包含了path模块,path模块下的isfile
和isdir
方法可以用来判断一个路径是文件还是目录,所以遍历所有文件的过程就是:
- 用listidr返回所有的文件名
- 判断是图片还是文件夹
-
如果是文件夹继续用listdir返回包含的文件名
具体代码如下:
-
计算思维
抽取模型