文章目錄
- 前言
- Github
- 效果
- 實(shí)現(xiàn)過程
- 整體代碼
前言
看電影的時(shí)候發(fā)現(xiàn)一個(gè)照片墻的功能,覺得這樣生成照片挺好玩的,于是就動手用Python做了一下,覺得用來作照片紀(jì)念的效果可能會不錯(cuò)。
Github
https://github.com/jiandi1027/photo.git
效果
實(shí)現(xiàn)過程
1.獲取圖片文件夾的圖片個(gè)數(shù)N,將底圖拆分成X
Y塊區(qū)域,且使X * Y
(為了保證整體的協(xié)調(diào),會舍棄幾張圖片,比如5張時(shí)可能只取2
# 打開圖片
base = Image.open(baseImgPath)
base = base.convert('RGBA')
# 獲取圖片文件夾圖片并打亂順序
files = glob.glob(imagesPath + '/*.*')
random.shuffle(files)
# 圖片數(shù)量
num = len(files)
# 底圖大小
x = base.size[0]
y = base.size[1]
# 每張圖片數(shù)量 這個(gè)公式是為了xNum * yNum 的總圖片數(shù)量
2.遍歷文件夾的圖片,依次填充生成最終合成圖
for file in files:
fromImage = Image.open(file)
i = int(num % xNum)
j = int(num / xNum)
out = fromImage.resize((xSize, ySize), Image.ANTIALIAS).convert('RGBA')
toImage.paste(out, (i * xSize, j * ySize))
toImage = toImage.convert('RGBA')
img = Image.blend(base, toImage, 0.3)
# 顯示圖片
photo = ImageTk.PhotoImage(img)
showLabel.config(image=photo)
showLabel.image = photo
if num < xNum * yNum:
num = num + 1
3.生成結(jié)束后保存圖片
toImage.save(‘generator.png’)
img.save(“final.png”)
4.建立可視化界面
5.Pyinstaller生成exe可執(zhí)行文件
安裝pyinstaller模塊,執(zhí)行命令生成exe文件
pyinstaller -F -w test.py (-w就是取消窗口)
整體代碼
Python的語法和設(shè)計(jì)規(guī)范還沒學(xué)過,所以代碼規(guī)范代碼復(fù)用之類的可能會有點(diǎn)不到位,本博文主要是一個(gè)思路與整體流程的記錄。
后續(xù)又優(yōu)化了一下一些特效,比如合成圖片采用隨機(jī)位置,增加黑白,流年等顯示特效,透明度自選等。
import PIL.Image as Image
import glob
import random
import tkinter.filedialog
from tkinter.filedialog import askdirectory, Label, Button, Radiobutton, Entry
import threading
import numpy as np
from PIL import ImageTk
alpha = 0.3
imagesPath = ''
# 滑動條回調(diào) 修改透明度
def resize(ev=None):
global alpha
alpha = scale.get() / 100
# 黑白
def blackWithe(image):
# r,g,b = r*0.299+g*0.587+b*0.114
im = np.asarray(image.convert('RGB'))
trans = np.array([[0.299, 0.587, 0.114], [0.299, 0.587, 0.114], [0.299, 0.587, 0.114]]).transpose()
im = np.dot(im, trans)
return Image.fromarray(np.array(im).astype('uint8'))
# 流年
def fleeting(image, params=12):
im = np.asarray(image.convert('RGB'))
im1 = np.sqrt(im * [1.0, 0.0, 0.0]) * params
im2 = im * [0.0, 1.0, 1.0]
im = im1 + im2
return Image.fromarray(np.array(im).astype('uint8'))
# 舊電影
def oldFilm(image):
im = np.asarray(image.convert('RGB'))
# r=r*0.393+g*0.769+b*0.189 g=r*0.349+g*0.686+b*0.168 b=r*0.272+g*0.534b*0.131
trans = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]).transpose()
# clip 超過255的顏色置為255
im = np.dot(im, trans).clip(max=255)
return Image.fromarray(np.array(im).astype('uint8'))
# 反色
def reverse(image):
im = 255 - np.asarray(image.convert('RGB'))
return Image.fromarray(np.array(im).astype('uint8'))
def chooseBaseImagePath():
name = tkinter.filedialog.askopenfilename()
if name != '':
global baseImgPath
baseImgPath = name
baseImageLabel.config(text=name)
baseImg = Image.open(baseImgPath)
widthEntry.delete(0, tkinter.END)
heightEntry.delete(0, tkinter.END)
widthEntry.insert(0, baseImg.size[0])
heightEntry.insert(0, baseImg.size[1])
else:
baseImageLabel.config(text="您沒有選擇任何文件")
def chooseImagesPath():
name = askdirectory()
if name != '':
global imagesPath
imagesPath = name
ImagesLabel.config(text=name)
else:
ImagesLabel.config(text="您沒有選擇任何文件")
def thread_it(func, *args):
# 創(chuàng)建
t = threading.Thread(target=func, args=args)
# 守護(hù) !!!
t.setDaemon(True)
# 啟動
t.start()
def test():
MyThread(1, "Thread-1", 1).start()
baseImgPath = ''
def generator():
baseImg = Image.open(baseImgPath)
baseImg = baseImg.convert('RGBA')
files = glob.glob(imagesPath + '/*.*') # 獲取圖片
random.shuffle(files)
num = len(files)
# 模板圖片大小
x = baseImg.size[0]
y = baseImg.size[1]
# 每張圖片數(shù)量 這個(gè)公式是為了xNum * yNum 的總圖片數(shù)量
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
