由於腦子裏的一些想法,須要將一些照片拼接在一塊兒,首先想到了使用APP直接操做,結果下載了許多應用後發現最多隻能支持九張照片的拼接。而後又找了些美圖秀秀之類,都沒法知足個人需求,甚至我都想到使用PS去進行操做,可是若是使用PS那可就變成了一項耗時間的活了呢。因而繼續的查找解決方案,在一個小角落裏找到了使用Pillow搭建照片牆的例子,心想這就是我想要的,細細查找發現果不其然,一會兒明朗了許多。在此對使用 Python + Pillow 完成的拼圖實現進行記錄。python
可參考以前的博文,Python 及其庫的安裝。緩存
需求:將一個文件夾中按名稱排序的方式進行拼圖操做,逐行或逐列操做。oop
預計流程:ui
其中圖片預處理能夠爲拉伸、旋轉、裁剪等變換,由於我後續須要拼圖時全部照片都應該爲正方形,所以我須要對圖片進行一個裁剪操做使圖片比例爲 1:1,爲了保證裁剪區域在圖像正中,須要進行判斷長短邊操做。this
進行合併圖片時須要空餘區域儘量少,且合併圖片比例不能太畸形。例如 30 張圖片能夠分爲 5 × 6 排布,31 張照片能夠分佈爲 4 × 8 排布。最理想狀態是腳本自動識別圖片個數併合理分配,這塊功能暫時沒有寫入 DEMO 中,行與列目前須要手動分配。code
在 Python 腳本中引用 Pillow 的方法也能夠參見 DEMO 程序。其中,排序
bol_auto_place
暫時爲可選項,置爲 True
表示將自動分配合並後畫布大小,目前只有根據圖片多少開平方,而後合併爲一個大正方形圖片,手動設置合併排布時須要將其置爲 False
。圖片
row
爲合併圖片分佈行參數,bol_auto_place == False
時有效。ip
col
爲合併圖片分佈列參數,bol_auto_place == False
時有效。ci
nw
爲緩存圖片寬度設定,nh
爲緩存圖片高度設定。合併文件的大小由排布及緩存圖片大小自動設定。
DEMO 腳本中所使用到的一些 function 有不懂的可百度或谷歌,查看各自的詳細描述。腳本在使用時與圖片放在一塊兒,而後點擊運行,運行期間將會顯示當前處理圖片,處理完成後將會展現合併圖片。合併完成後圖片以 PNG 格式存儲於同路徑下splicing_picture.png
文件。DEMO 程序的源代碼及幾個參考文件可點此進行下載。
##################################################### # Notice ! # # This script file should be placed in the same # # folder as the image. # ##################################################### import sys, os, shutil, math from PIL import Image ##################################################### # parameter setting # ##################################################### bol_auto_place = False # auto place the image as a squared image, if 'True', ignore var 'row' and 'col' below row = 4 # row number which means col number images per row col = 8 # col number which means row number images per col nw = 400 # sub image size, nw x nh nh = 400 path = os.getcwd(); # acquire current folder path if os.path.exists('tmp'): # ensure the 'tmp' folder is empty shutil.rmtree('tmp') os.makedirs('tmp') file_ls = os.listdir() # list all files in this folder i = 0 # a counter for images for file in file_ls: name, extension = os.path.splitext(file); # get file info[name, extension] if (extension == '.png' or extension == '.jpg' or extension == '.jpeg') and name != 'splicing_picture': # select the image i += 1 # image counter++ print('%s...%s%s' % (i, name, extension)) os.chdir(path) # ensure the image folder in every loop im = Image.open(file) # open the image w, h = im.size # get image info #print('Original image size: %sx%s' % (w, h)) if nw == nh: # if image should be 1:1 size if w >= h: box = ((w - h) // 2, 0, (w + h) // 2, h) else: box = (0, (h - w) // 2, w, (h + w) // 2) region = im.crop(box) # crop the image to 1:1 and keep center region else: region = im # do nothing sname = '%s%s' % (str(i), '.png') # rename 'x.png', x is a number from 1 to N os.chdir('tmp') # get into the folder 'tmp' region.save(sname, 'png') # save the square image os.chdir(path) # ensure the path os.chdir('tmp') if bol_auto_place: # auto place a big 1:1 square image row = math.ceil(i ** 0.5) col = math.ceil(i ** 0.5) dest_im = Image.new('RGBA', (col * nw, row * nh), (255, 255, 255)) # the image size of splicing image, background color is white for x in range(1, col + 1): # loop place the sub image for y in range(1,row + 1): try: src_im = Image.open("%s.png" % str( x + ( y - 1 ) * col)) # open files in order resize_im = src_im.resize((nw, nh), Image.ANTIALIAS) # resize again dest_im.paste(resize_im, ((x-1) * nw, (y-1) * nh)) # paste to dest_im except IOError: pass os.chdir(path) # ensure the path shutil.rmtree('tmp') # delete the 'tmp' dest_im.save('splicing_picture.png', 'png') dest_im.show() # finish
30 張照片按照 4 × 8 的排布方式,圖片拼合後效果圖以下所示。我的對這樣的結果仍是至關滿意的,也能夠調整成 5 × 6 的排布方式,只需更改 row
與 col
的參數設定後從新運行便可。