【相關學習推薦:python教學】
文章目錄
- 前言
- Github
- 效果
- 實作過程
- #整體程式碼
前言
看電影的時候發現一個照片牆的功能,覺得這樣生成照片挺好玩的,於是就動手用Python做了一下,覺得用來做照片紀念的效果可能會不錯。
P:後面了解到我想做的功能叫蒙太奇拼圖,所以這篇部落格記錄先留著,閒下來會去看一下蒙太奇拼圖的演算法
Github
https://github.com/jiandi1027/photo.git
效果
實作過程
1.取得圖片資料夾的圖片個數N,將底圖拆分成XY區塊區域,並且讓X * Y
# 打开图片 base = Image.open(baseImgPath) base = base.convert('RGBA') # 获取图片文件夹图片并打乱顺序 files = glob.glob(imagesPath + '/*.*') random.shuffle(files) # 图片数量 num = len(files) # 底图大小 x = base.size[0] y = base.size[1] # 每张图片数量 这个公式是为了xNum * yNum 的总图片数量<num又成比例的最大整数 yNum = int((num / (y / x)) ** 0.5) if yNum == 0: yNum = 1 xNum = int(num / yNum) # 图片大小 因为像素没有小数点 为防止黑边所以+1 xSize = int(x / xNum) + 1 ySize = int(y / yNum) + 1
#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.產生結束後儲存圖片
toImage.save('generator.png')
img.save(“final.png”)
4.建立視覺化介面
5.Pyinstaller產生exe執行檔
安裝pyinstaller模組,執行指令產生exe檔
pyinstaller -F -w test.py (-w就是取消窗口)
整體程式碼
# Python的語法和設計規格還沒學過,所以程式碼規範程式碼重複使用之類的可能會有點不到位,本部落格文章主要是一個思路與整體流程的記錄。
後續又優化了一下一些特效,例如合成圖片採用隨機位置,增加黑白,流年等顯示特效,透明度自選等。
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 = '' # 滑动条回调 修改透明度 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): # 创建 t = threading.Thread(target=func, args=args) # 守护 !!! 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] # 每张图片数量 这个公式是为了xNum * yNum 的总图片数量<num又成比例的最大整数 yNum = int((num / (y / x)) ** 0.5) if yNum == 0: yNum = 1 xNum = int(num / yNum) # 图片大小 因为像素没有小数点 为防止黑边所以+1 xSize = int(x / xNum) + 1 ySize = int(y / yNum) + 1 # 生成数量的随机列表 用于随机位置合成图片 l = [n for n in range(0, xNum * yNum)] random.shuffle(l) toImage = Image.new('RGB', (x, y)) num = 1 for file in files: if num <= xNum * yNum: num = num + 1 else: break fromImage = Image.open(file) temp = l.pop() i = int(temp % xNum) j = int(temp / xNum) out = fromImage.resize((xSize, ySize), Image.ANTIALIAS).convert('RGBA') toImage.paste(out, (i * xSize, j * ySize)) toImage = toImage.convert('RGBA') img = Image.blend(baseImg, toImage, alpha) # 特效 但是会读取像素会降低效率 choose = v.get() if choose == 1: img = blackWithe(img) elif choose == 2: img = fleeting(img) elif choose == 3: img = oldFilm(img) elif choose == 4: img = reverse(img) resize = img.resize((300, 300), Image.ANTIALIAS).convert('RGBA') # 显示图片 photo = ImageTk.PhotoImage(resize) showLabel.config(image=photo) showLabel.image = photo toImage.save('generator.png') img = img.resize((int(widthEntry.get()),int(heightEntry.get())), Image.ANTIALIAS).convert('RGBA') img.save("final.png") resize.save("resize.png") class MyThread(threading.Thread): # 继承父类threading.Thread def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 generator() root = tkinter.Tk() root.title('generator') root.geometry('500x550') baseImageLabel = Label(root, text='') baseImageLabel.place(x=10, y=10) baseImageBtn = Button(root, text="选择底图", command=chooseBaseImagePath).place(x=10, y=30) ImagesLabel = Label(root, text='') ImagesLabel.place(x=10, y=60) ImagesBtn = Button(root, text="选择合成图文件夹", command=chooseImagesPath).place(x=10, y=80) v = tkinter.IntVar() v.set(0) Radiobutton(root, variable=v, text='默认', value=0, ).place(x=10, y=120) Radiobutton(root, variable=v, text='黑白', value=1, ).place(x=110, y=120) Radiobutton(root, variable=v, text='流年', value=2, ).place(x=210, y=120) Radiobutton(root, variable=v, text='旧电影', value=3, ).place(x=310, y=120) Radiobutton(root, variable=v, text='反色', value=4, ).place(x=410, y=120) scaleLabel = Label(root, text='透明度').place(x=10, y=170) scale = tkinter.Scale(root, from_=0, to=100, orient=tkinter.HORIZONTAL, command=resize) scale.set(30) # 设置初始值 scale.pack(fill=tkinter.X, expand=1) scale.place(x=70, y=150) Label(root, text='宽(像素)').place(x=180, y=170) widthEntry = Entry(root, bd=1) widthEntry.place(x=230, y=173, width=100) Label(root, text='高(像素)').place(x=320, y=170) heightEntry = Entry(root, bd=1) heightEntry.place(x=370, y=173, width=100) generatorBtn = Button(root, text="生成", command=test).place(x=10, y=220) showLabel = Label(root) showLabel.place(x=100, y=220) root.mainloop()
#想了解更多程式設計學習,請關注php培訓欄位!
以上是Python照片合成的方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3漢化版
中文版,非常好用