1. 程式人生 > >Python將大量圖片拼接成心形圖片(二)

Python將大量圖片拼接成心形圖片(二)

前言

效果圖如下:
在這裡插入圖片描述

可以看出來,由小圖片拼接為最終的正方形的大圖,大圖的邊長由多個小圖組成,為了維持❤️形的對成性,故而大圖的邊長應該為奇數個小圖,因此在由圖片數量計算大圖的邊長時若為偶數應減一。

由大圖邊長各為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)

以上就是部落格的所有內容,如果對此有問題或者有更好的想法和建議,歡迎交流討論。