使用 Python 和 Pillow 给装修现场照片批量打时间水印并拼成施工日记九宫格(中文路径/EXIF 坑)
装修施工动辄两三个月,现场照片一天拍几十张,月底想整理成"施工日记"发给业主,最头疼两件事:一是照片不知道是哪天拍的,二是几百张图散着没法看。本文用纯 Python(Pillow)写一个本地小工具:批量给照片叠加「日期+工种」水印,再按 3×3 拼成九宫格日报图,全程不联网、双击可用。我会重点讲三个实战大坑——中文路径、EXIF 旋转、水印中文乱码,都是我踩过的。
一、整体思路
- 扫描某个目录下所有
.jpg/.png; - 读取拍摄时间(优先 EXIF,没有就退回文件修改时间);
- 在右下角叠加半透明文字水印(日期 + 自定义工种标签);
- 把当天照片每 9 张拼一张九宫格,输出到
日报/目录。
依赖只有一个:pip install Pillow。
二、中文路径:别用字符串硬拼
Windows 下路径带中文(如 D:/装修照片/水电/),最稳的做法是全程用 pathlib.Path,它内部用 os.fspath 正确转码,避免 open() 报 FileNotFoundError: [Errno 2]。
from pathlib import Path
root = Path(r"D:/装修照片/水电")
imgs = sorted(p for p in root.glob("*") if p.suffix.lower() in (".jpg", ".jpeg", ".png"))坑 1:别用 os.listdir() 再手动拼字符串,容易在 open 时因为 GBK 编码炸掉。用 Path 一步到位。
三、EXIF 旋转:手机拍的图可能"横着读"
很多手机照片在 Windows 看图正常,但 Pillow 打开却是旋转 90° 的——因为旋转信息存在 EXIF 的 Orientation 标签里,看图软件会自动纠正,Pillow 默认不纠正。批量处理前务必统一纠正:
from PIL import Image, ExifTags
def fix_orientation(img):
try:
exif = img._getexif()
if not exif:
return img
for k, v in exif.items():
if ExifTags.TAGS.get(k) == "Orientation":
if v == 3:
img = img.rotate(180, expand=True)
elif v == 6:
img = img.rotate(-90, expand=True)
elif v == 8:
img = img.rotate(90, expand=True)
except Exception:
pass
return img坑 2:不纠正直接拼图,九宫格里有一半图是歪的。这个纠正必须放在 resize 之前。
四、水印中文乱码:指定字体文件
Pillow 的 ImageDraw.text 默认字体不带中文字形,写中文会成方块。必须显式指定一个中文字体 ttf:
from PIL import ImageDraw, ImageFont
font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 36) # 微软雅黑坑 3:truetype 的路径同样可能含中文,用 Path 传入即可。字体大小要按图尺寸缩放,别写死像素。
叠加水印的函数:
def add_watermark(img, text):
draw = ImageDraw.Draw(img, "RGBA")
w, h = img.size
# 半透明黑底条
draw.rectangle([(w-360, h-60), (w, h)], fill=(0, 0, 0, 120))
draw.text((w-350, h-48), text, font=font, fill=(255, 255, 255, 230))
return img
注意:水印要在「缩略图」上打,而不是原图画质上,既能看清又不破坏原图。
五、拼九宫格
把 9 张缩略图贴到一张大图:
def make_grid(images, cols=3, thumb=360, gap=8):
rows = (len(images) + cols - 1) // cols
grid = Image.new("RGB", (cols*thumb + (cols+1)*gap, rows*thumb + (rows+1)*gap), (240,240,240))
for i, im in enumerate(images):
im = fix_orientation(im).convert("RGB")
im.thumbnail((thumb, thumb))
r, c = divmod(i, cols)
x = gap + c*(thumb+gap)
y = gap + r*(thumb+gap)
grid.paste(im, (x, y))
return grid
thumbnail 会等比例缩放且不拉伸变形,比手动 resize 安全。
六、按天归档
用拍摄日期分组,每天生成一张日报图:
from collections import defaultdict
from datetime import datetime
groups = defaultdict(list)
for p in imgs:
d = get_shoot_date(p) # 读 EXIF 或 mtime
groups[d.strftime("%Y-%m-%d")].append(p)
for day, paths in groups.items():
day_imgs = [add_watermark(fix_orientation(Image.open(p)), f"{day} 水电") for p in paths[:9]]
grid = make_grid(day_imgs)
grid.save(out_dir / f"{day}_施工日记.png")七、小结与避坑清单
- 路径一律用
pathlib.Path,避开中文编码雷区; - 开图先
fix_orientation纠正 EXIF 旋转,再缩放/拼图; - 中文水印必须
truetype指定字体,否则方块乱码; - 水印打在缩略图上,原图保持干净;
thumbnail等比缩放不变形,比硬编码resize稳。
把这套脚本跑起来,每天收工前 30 秒就能生成一张可发给业主的施工日报,比零散发图专业太多。完整可运行脚本和字体适配细节见我整理的本地工具包文档。
本文示例代码已在 Python 3.11 + Pillow 10 实测通过;字体路径请按本机实际位置调整。
到此这篇关于用 Python 和 Pillow 给装修现场照片批量打时间水印并拼成施工日记九宫格(中文路径/EXIF 坑)的文章就介绍到这了,更多相关Python Pillow对装修现场照片批量处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Windows下用py2exe将Python程序打包成exe程序的教程
这篇文章主要介绍了Windows下用py2exe将Python程序打包成exe程序的教程,文中主要针对Python3.x版本进行说明,需要的朋友可以参考下2015-04-04
基于Pyinstaller打包Python程序并压缩文件大小
这篇文章主要介绍了基于Pyinstaller打包Python程序并压缩文件大小,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-05-05
pytorch中DataLoader()过程中遇到的一些问题
这篇文章主要介绍了pytorch中DataLoader()过程中遇到的一些问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-05-05


最新评论