缘由
这两年网上出现了使用python中的PIL或是pillow库拼接图片和朋友圈图像的例子,让我非常感兴趣,比较典型的是这几个例子:
我实操了一下,发现还是有些小问题,下面是我消化吸收和改进的过程。改进的地方:
1.存放图片的文件夹是任意指定的,里面文件名没有要求,不需要按照序号1,2,……这样的命名,更实用;
2.图片的合并效果更好,是根据图片集的图片的个数来确定背景画板的大小,而不是让图片来适应画板,这就避免合并图边缘的空白或黑边问题,同时对图片集大小没有限制,任意个数的图片都能拼接。
3.背景画布的大小可以灵活调整,你只需要确定每行放几张图片,每张图片的大小是多少,就可以得到超长图或是扁平图之类的。
需要用到的知识点
PIL(Python Imaging Library)已经是Python平台事实上的图像处理标准库。PIL功能强大,简单易用。由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此在python中,安装pillow库就可以使用PIL库了。
Image 类是PIL库中一个非常重要的类,通过这个类来创建实例可以有直接载入图像文件,读取处理过的图像。
以下是Image类几个最常用的方法。
new('RGBA', (x,y))
创建一张图片,默认是黑色的。可以修改参数。
image = Image.new('RGB', (width, height), (255, 255, 255))
open(filename), save(outfilename)
open(filename) 打开一个图片文件把图片读进来。save(outfilename)保存图片。
resize(size,size)
调整图片大小(缩放图片)。近千张图片,先要缩小一下。
安装依赖库
sudo pip install pillow
代码
下面是我将平时喜爱的歌手专辑的封面整理后,拼接得到的大图,每个album的大小一般为300*300.
#!/usr/bin/env python
#encoding: utf-8
#description: 将指定文件夹下面的图片拼接为一张大图(没有黑边)
#date: 2018-12-18
import PIL.Image as Image
import os
import math
#==========基本配置信息==========
#待合成图片所在目录
dir_in = '/home/taoyx/图片/Mac专用Album/'
#输出大图目录
dir_out = '/home/taoyx/program_develop/python_dev/img_joint/'
#单张图片大小预设
img_w = 300
img_h = 300
#每行图片个数,为了输出美观,要结合图片集大小灵活调整,图片总数最好能整除col
col = 37
#================================
#先统计图片目录中的图片个数
img_list = os.listdir(dir_in)
total_cnt = len(img_list)
print('Path:%s, images total:[%d]' %(dir_in, total_cnt))
#确定画板的宽和高,math.ceil返回浮点数还需取整才行
row = int(math.ceil(total_cnt / col))
bg_w = img_w * col
bg_h = row * img_h
print('image:(%d,%d), background:(%d,%d), col:%d, row:%d' %(img_w, img_h, bg_w, bg_h, col, row))
#创建指定大小的画板
bg = Image.new('RGBA',(bg_w, bg_h))
cnt = 0
w = 0
h = 0
#逐个将图片粘贴进来
for fn in os.listdir(dir_in):
#修复部分文件名前面带有'._'前缀的bug,导致找不到指定文件
if fn[0] == '.' and fn[1] == '_':
fn = fn[2:]
print('file name:%s' %fn)
fname = os.path.join(dir_in, os.path.basename(fn))
#print('full file name:%s' %fname)
try:
img = Image.open(fname)
except IOError:
print 'IOError:%s' %fname
else:
#将每张图片缩放到指定大小
img = img.resize((img_w, img_h), Image.ANTIALIAS)
#注意精确确定每张图片在合成背景上所在的像素区域
w = cnt % col
if cnt != 0 and w == 0:
h += 1
cnt += 1
print('count:%d, position:(%d,%d)' %(cnt, w, h))
bg.paste(img, (w * img_w, h * img_h))
#保存最后的合并图到指定输出目录
bg.save(dir_out + 'album_all.png')
在命令行执行
python img_joint.py
效果图
下面是对某电影海报文件夹内海报图片的拼接效果