Python將大量圖片拼接成心形圖片(二)
阿新 • • 發佈:2018-12-26
前言
效果圖如下:
可以看出來,由小圖片拼接為最終的正方形的大圖,大圖的邊長由多個小圖組成,為了維持❤️形的對成性,故而大圖的邊長應該為奇數個小圖,因此在由圖片數量計算大圖的邊長時若為偶數應減一。
由大圖邊長各為5、7、9畫出預期心形圖的示意如下:
規律可自行總結,可能愛心的效果不是很好,如果有更好想法的歡迎交流討論,共同進步。
程式碼
下面將完整程式碼貼出來,具體的解釋在註釋中,有疑問的可以先看上一篇部落格:
Python將大量圖片拼成心形(一)
from PIL import Image import os import math import random import uuid # 處理的所有圖片及結果存放的總目錄 dir = "/Users/wleng/Downloads/圖片3" # 白底圖片所在的路徑 whiteImagePath = ["/Users/lengwei/Downloads/圖片3/white.png"] # 白底圖片所在的目錄 whiteGoalPath = "/Users/lengwei/Downloads/圖片3/白底色/" # 拼接後的圖片的總尺寸,根據尺寸和圖片數量計算出每張圖片的大小 totalSize = 1000 # 重設大小後的圖片所在的目錄 transferDir = '1' # 拼接結果圖片所在的目錄 resultDir = '2' # 計算每個拼接大圖需要多少個小圖作為邊長拼接 def getSize(num): # 最小邊長從5開始,由其心形規律得出n的計算公式(推理步驟不放出來了) n = math.floor(math.sqrt(2 * num + 27 / 4) - 1.5) # 若為偶數,則減一 if n % 2 == 0: n -= 1 return n # 獲取指定路徑下的所有圖片 def getImagesName(dir): allPicPath = [] # 所有圖片 for root, dirs, files in os.walk(dir): for file in files: if file.endswith('.png') or file.endswith('.jpg') or file.endswith('.jpeg'): allPicPath.append(dir + '/' + file) return allPicPath # 將圖片轉化為指定大小 def transferSize(allPicPath, height, width, goalPath): for i in range(len(allPicPath)): im = Image.open(allPicPath[i]) out = im.resize((height, width), Image.ANTIALIAS) out.save(goalPath + str((allPicPath[i].split('/')[len(allPicPath[i].split('/')) - 1]))) def main(dir): # 獲取所有指定目錄下所有圖片的路徑 allPicPath = getImagesName(dir+'/model') # 得到圖片數量 numOfPic = len(allPicPath) # 獲取生成圖片的邊長大小,並計算出每個圖片的邊長應該是多大 size = getSize(numOfPic) height = math.floor(totalSize / size) width = math.floor(totalSize / size) # 將用於拼接的圖片都格式化為統一大小的圖片 transferSize(allPicPath, height, width, dir + '/1/') # 獲取所有格式化後的拼接圖片的路徑 allTransPicPath = getImagesName(dir + '/' + transferDir) # 獲取用於填充多餘部分的格式化後的白色圖片的image # transferSize(whiteImagePath, height, width, whiteGoalPath[0]) # perPicNum = math.floor(math.sqrt(numOfPic)) toImage = Image.new('RGBA', (totalSize, totalSize)) # 隨機打亂用於拼接的圖片的順序,這樣可保證每次拼接出來的圖片順序都是不同的 random.shuffle(allTransPicPath) # 用於統計使用的拼圖的圖的數量 j = 0 print(len(allTransPicPath)) # 獲取白底圖片的image,並設定好同樣大小備用 im = Image.open(whiteImagePath[0]) out = im.resize((height, width), Image.ANTIALIAS) m = 1 # 給每行分頁貼上size個小圖片 for i in range(size): fromImage = "" if i == 0: k = 0 # 列印一個空白格 loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 # 列印一個圖案 loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) k += 1 # 列印 (size-4) 個空白格 for h in range(size - 4): loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 # 列印一個圖案 loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) k += 1 # 列印一個空白格 loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 elif i <= (size - 3) / 2 - 1 and i>0: k = 0 # 根據規律,先列印 i+2 個圖片 for s in range(i+2): loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) k += 1 # 然後列印 (size-(i+2)*2)個空白格 for h in range(size-(i+2)*2): loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 # 最後再列印 (i+2)個圖片 for s in range(i+2): loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) k += 1 elif i>(size - 3) / 2 - 1 and i<=(size - 3) / 2 + 1: # i在滿足條件的範圍內列印(size)個圖片 for k in range(size): loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) else: k = 0 for x in range(m): loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 for y in range(size-2*m): loc = ((k % size) * width, (int(i % size) * height)) print(loc) fromImage = Image.open(allTransPicPath[j]) j += 1 toImage.paste(fromImage, loc) k += 1 for x in range(m): loc = ((k % size) * width, (int(i % size) * height)) print(loc) toImage.paste(out, loc) k += 1 m += 1 # 在將所有的圖片都貼上到大畫布後將合成圖儲存到指定目錄下,並隨機分配一個名字 toImage.save(dir + '/' + resultDir + '/' + str(uuid.uuid4()) +'.png') if __name__ == '__main__': main(dir)
以上就是部落格的所有內容,如果對此有問題或者有更好的想法和建議,歡迎交流討論。